提交 261f0f1c 编写于 作者: J Joao Moreno

wip: telemetry service in shared process

上级 1f74e3c5
......@@ -97,9 +97,9 @@ var writable = new stream.Writable({
write: function () { /* No OP */ }
});
process.__defineGetter__('stdout', function() { return writable; });
process.__defineGetter__('stderr', function() { return writable; });
process.__defineGetter__('stdin', function() { return writable; });
// process.__defineGetter__('stdout', function() { return writable; });
// process.__defineGetter__('stderr', function() { return writable; });
// process.__defineGetter__('stdin', function() { return writable; });
// Handle uncaught exceptions
process.on('uncaughtException', function (err) {
......
......@@ -7,10 +7,10 @@
import {TPromise} from 'vs/base/common/winjs.base';
import {IServer} from 'vs/base/parts/ipc/common/ipc';
import {AIAdapter} from './aiAdapter';
import {AppInsightsAppender} from 'vs/platform/telemetry/node/aiAdapter';
import {IAIChannel} from './ai.ipc';
const adapter: { [handle: number]: AIAdapter } = Object.create(null);
const adapter: { [handle: number]: AppInsightsAppender } = Object.create(null);
let idPool = 0;
export function registerAIChannel(server: IServer) {
......@@ -20,7 +20,7 @@ export function registerAIChannel(server: IServer) {
case 'create': {
let handle = idPool++;
let {key, eventPrefix, data} = arg;
adapter[handle] = new AIAdapter(eventPrefix, data, key);
adapter[handle] = new AppInsightsAppender(eventPrefix, data, key);
return TPromise.as(handle);
}
case 'log': {
......
......@@ -19,6 +19,11 @@ import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/comm
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import product from 'vs/platform/product';
import { ITelemetryAppender, combinedAppender, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { AppInsightsAppender } from 'vs/platform/telemetry/node/aiAdapter';
function quit(err?: Error) {
if (err) {
console.error(err);
......@@ -40,6 +45,23 @@ function setupPlanB(parentPid: number): void {
}, 5000);
}
const eventPrefix = 'monacoworkbench';
function createAppender(): ITelemetryAppender {
const result: ITelemetryAppender[] = [];
const { key, asimovKey } = product.aiConfig;
if (key) {
result.push(new AppInsightsAppender(eventPrefix, null, key));
}
if (asimovKey) {
result.push(new AppInsightsAppender(eventPrefix, null, asimovKey));
}
return combinedAppender(...result);
}
function main(server: Server): void {
const services = new ServiceCollection();
......@@ -50,13 +72,31 @@ function main(server: Server): void {
const instantiationService = new InstantiationService(services);
instantiationService.invokeFunction(accessor => {
const extensionManagementService = accessor.get(IExtensionManagementService);
const channel = new ExtensionManagementChannel(extensionManagementService);
server.registerChannel('extensions', channel);
registerAIChannel(server);
// eventually clean up old extensions
setTimeout(() => (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions(), 5000);
const { appRoot, extensionsPath } = accessor.get(IEnvironmentService);
const appender = createAppender();
const config: ITelemetryServiceConfig = {
appender,
commonProperties: TPromise.as({}), //resolveCommonProperties(storageService, contextService),
piiPaths: [appRoot, extensionsPath]
};
const services = new ServiceCollection();
services.set(ITelemetryService, new SyncDescriptor(TelemetryService, config));
const instantiationService2 = instantiationService.createChild(services);
instantiationService2.invokeFunction(accessor => {
const telemetryService = accessor.get(ITelemetryService);
console.log(telemetryService);
const extensionManagementService = accessor.get(IExtensionManagementService);
const channel = new ExtensionManagementChannel(extensionManagementService);
server.registerChannel('extensions', channel);
registerAIChannel(server);
// eventually clean up old extensions
setTimeout(() => (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions(), 5000);
});
});
}
......
......@@ -10,6 +10,7 @@ export const IEnvironmentService = createDecorator<IEnvironmentService>('environ
export interface IEnvironmentService {
serviceId: ServiceIdentifier<any>;
appRoot: string;
userDataPath: string;
extensionsPath: string;
}
......@@ -10,11 +10,15 @@ import pkg from 'vs/platform/package';
import * as os from 'os';
import * as path from 'path';
import { parseArgs } from 'vs/code/node/argv';
import URI from 'vs/base/common/uri';
export class EnvironmentService implements IEnvironmentService {
serviceId = IEnvironmentService;
private _appRoot: string;
get appRoot(): string { return this._appRoot; }
private _userDataPath: string;
get userDataPath(): string { return this._userDataPath; }
......@@ -24,6 +28,7 @@ export class EnvironmentService implements IEnvironmentService {
constructor() {
const argv = parseArgs(process.argv);
this._appRoot = path.dirname(URI.parse(require.toUrl('')).fsPath);
this._userDataPath = paths.getUserDataPath(process.platform, pkg.name, process.argv);
const userHome = path.join(os.homedir(), product.dataFolderName);
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { ITelemetryAppender } from './telemetry';
export interface ITelemetryLog {
eventName: string;
data?: any;
}
export interface ITelemetryAppenderChannel extends IChannel {
call(command: 'log', data: ITelemetryLog): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class TelemetryAppenderChannel implements ITelemetryAppenderChannel {
constructor(private appender: ITelemetryAppender) { }
call(command: string, { eventName, data }: ITelemetryLog): TPromise<any> {
return this.appender.log(eventName, data);
}
}
export class TelemetryAppenderClient implements ITelemetryAppender {
constructor(private channel: ITelemetryAppenderChannel) { }
log(eventName: string, data?: any): any {
return this.channel.call('log', { eventName, data });
}
dispose(): any {
// TODO
}
}
\ No newline at end of file
......@@ -8,36 +8,34 @@ import * as appInsights from 'applicationinsights';
import {isObject} from 'vs/base/common/types';
import {safeStringify, mixin} from 'vs/base/common/objects';
import {TPromise} from 'vs/base/common/winjs.base';
import {ITelemetryAppender} from '../common/telemetry';
namespace AI {
let _initialized = false;
let _initialized = false;
function ensureAIEngineIsInitialized(): void {
if (_initialized === false) {
// we need to pass some fake key, otherwise AI throws an exception
appInsights.setup('2588e01f-f6c9-4cd6-a348-143741f8d702')
.setAutoCollectConsole(false)
.setAutoCollectExceptions(false)
.setAutoCollectPerformance(false)
.setAutoCollectRequests(false);
function ensureAIEngineIsInitialized(): void {
if (_initialized === false) {
// we need to pass some fake key, otherwise AI throws an exception
appInsights.setup('2588e01f-f6c9-4cd6-a348-143741f8d702')
.setAutoCollectConsole(false)
.setAutoCollectExceptions(false)
.setAutoCollectPerformance(false)
.setAutoCollectRequests(false);
_initialized = true;
}
_initialized = true;
}
}
export function getClient(aiKey: string): typeof appInsights.client {
function getClient(aiKey: string): typeof appInsights.client {
ensureAIEngineIsInitialized();
ensureAIEngineIsInitialized();
const client = appInsights.getClient(aiKey);
client.channel.setOfflineMode(true);
client.context.tags[client.context.keys.deviceMachineName] = ''; //prevent App Insights from reporting machine name
if (aiKey.indexOf('AIF-') === 0) {
client.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
}
return client;
const client = appInsights.getClient(aiKey);
client.channel.setOfflineMode(true);
client.context.tags[client.context.keys.deviceMachineName] = ''; //prevent App Insights from reporting machine name
if (aiKey.indexOf('AIF-') === 0) {
client.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
}
return client;
}
interface Properties {
......@@ -48,7 +46,7 @@ interface Measurements {
[key: string]: number;
}
export class AIAdapter {
export class AppInsightsAppender implements ITelemetryAppender {
private _aiClient: typeof appInsights.client;
......@@ -62,7 +60,7 @@ export class AIAdapter {
}
if (typeof aiKeyOrClientFactory === 'string') {
this._aiClient = AI.getClient(aiKeyOrClientFactory);
this._aiClient = getClient(aiKeyOrClientFactory);
} else if (typeof aiKeyOrClientFactory === 'function') {
this._aiClient = aiKeyOrClientFactory();
}
......@@ -74,7 +72,7 @@ export class AIAdapter {
const measurements: Measurements = Object.create(null);
const flat = Object.create(null);
AIAdapter._flaten(data, flat);
AppInsightsAppender._flaten(data, flat);
for (let prop in flat) {
// enforce property names less than 150 char, take the last 150 char
......@@ -120,7 +118,7 @@ export class AIAdapter {
} else if (isObject(value)) {
if (order < 2) {
AIAdapter._flaten(value, result, order + 1, index + '.');
AppInsightsAppender._flaten(value, result, order + 1, index + '.');
} else {
result[index] = safeStringify(value);
}
......@@ -135,7 +133,7 @@ export class AIAdapter {
return;
}
data = mixin(data, this._defaultData);
let {properties, measurements} = AIAdapter._getData(data);
let {properties, measurements} = AppInsightsAppender._getData(data);
this._aiClient.trackEvent(this._eventPrefix + '/' + eventName, properties, measurements);
}
......
......@@ -5,7 +5,7 @@
'use strict';
import * as assert from 'assert';
import {AIAdapter} from 'vs/base/parts/ai/node/aiAdapter';
import {AppInsightsAppender} from 'vs/platform/telemetry/node/aiAdapter';
interface IAppInsightsEvent {
eventName: string;
......@@ -41,12 +41,12 @@ class AppInsightsMock {
suite('AIAdapter', () => {
var appInsightsMock: AppInsightsMock;
var adapter: AIAdapter;
var adapter: AppInsightsAppender;
var prefix = 'prefix';
setup(() => {
appInsightsMock = new AppInsightsMock();
adapter = new AIAdapter(prefix, undefined, () => appInsightsMock);
adapter = new AppInsightsAppender(prefix, undefined, () => appInsightsMock);
});
teardown(() => {
......@@ -61,7 +61,7 @@ suite('AIAdapter', () => {
});
test('addional data', () => {
adapter = new AIAdapter(prefix, { first: '1st', second: 2, third: true }, () => appInsightsMock);
adapter = new AppInsightsAppender(prefix, { first: '1st', second: 2, third: true }, () => appInsightsMock);
adapter.log('testEvent');
assert.equal(appInsightsMock.events.length, 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册