Switch to 1DS endpoint (#20769)

* Update to 1DS client

* remove product config

* Update ai keys

* use our own event prefix

* re-enable telemetry

* Update distro and remove default enableTelemetry

* distro

* Remove asimovKey references

* add comment

* distro

* distro

* distro

* add files that break precommit hook

* cleanup/fixes

* distro

* distro + event prefix update

* distro

* more
This commit is contained in:
Charles Gagnon
2022-11-03 08:45:06 -07:00
committed by GitHub
parent ca78491238
commit fb05c4304e
54 changed files with 795 additions and 462 deletions

View File

@@ -4,12 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import { Server } from 'vs/base/parts/ipc/node/ipc.cp';
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
const appender = new AppInsightsAppender(process.argv[2], JSON.parse(process.argv[3]), process.argv[4]);
const appender = new OneDataSystemAppender(false, process.argv[2], JSON.parse(process.argv[3]), process.argv[4]);
process.once('exit', () => appender.flush());
const channel = new TelemetryAppenderChannel([appender]);
const server = new Server('telemetry');
server.registerChannel('telemetryAppender', channel);

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { ApplicationInsights } from '@microsoft/applicationinsights-web';
import { Disposable } from 'vs/base/common/lifecycle';
import { IObservableValue } from 'vs/base/common/observableValue';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -11,103 +10,21 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ILoggerService } from 'vs/platform/log/common/log';
import { IProductService } from 'vs/platform/product/common/productService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { OneDataSystemWebAppender } from 'vs/platform/telemetry/browser/1dsAppender';
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
import { ITelemetryData, ITelemetryInfo, ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
import { ITelemetryData, ITelemetryInfo, ITelemetryService, TelemetryLevel, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender';
import { ITelemetryServiceConfig, TelemetryService as BaseTelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { ITelemetryAppender, NullTelemetryService, supportsTelemetry, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils';
import { getTelemetryLevel, isInternalTelemetry, ITelemetryAppender, NullTelemetryService, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { resolveWorkbenchCommonProperties } from 'vs/workbench/services/telemetry/browser/workbenchCommonProperties';
class WebAppInsightsAppender implements ITelemetryAppender {
private _aiClient: ApplicationInsights | undefined;
private _aiClientLoaded = false;
private _telemetryCache: { eventName: string; data: any }[] = [];
constructor(private _eventPrefix: string, aiKey: string) {
const endpointUrl = 'https://mobile.events.data.microsoft.com/collect/v1';
import('@microsoft/applicationinsights-web').then(aiLibrary => {
this._aiClient = new aiLibrary.ApplicationInsights({
config: {
instrumentationKey: aiKey,
endpointUrl,
disableAjaxTracking: true,
disableExceptionTracking: true,
disableFetchTracking: true,
disableCorrelationHeaders: true,
disableCookiesUsage: true,
autoTrackPageVisitTime: false,
emitLineDelimitedJson: true,
},
});
this._aiClient.loadAppInsights();
// Client is loaded we can now flush the cached events
this._aiClientLoaded = true;
this._telemetryCache.forEach(cacheEntry => this.log(cacheEntry.eventName, cacheEntry.data));
this._telemetryCache = [];
// If we cannot access the endpoint this most likely means it's being blocked
// and we should not attempt to send any telemetry.
fetch(endpointUrl).catch(() => (this._aiClient = undefined));
}).catch(err => {
console.error(err);
});
}
/**
* Logs a telemetry event with eventName and data
* @param eventName The event name
* @param data The data associated with the events
*/
public log(eventName: string, data: any): void {
if (!this._aiClient && this._aiClientLoaded) {
return;
} else if (!this._aiClient && !this._aiClientLoaded) {
this._telemetryCache.push({ eventName, data });
return;
}
data = validateTelemetryData(data);
// Web does not expect properties and measurements so we must
// spread them out. This is different from desktop which expects them
data = { ...data.properties, ...data.measurements };
// undefined assertion is ok since above two if statements cover both cases
this._aiClient!.trackEvent({ name: this._eventPrefix + '/' + eventName }, data);
}
/**
* Flushes all the telemetry data still in the buffer
*/
public flush(): Promise<any> {
if (this._aiClient) {
this._aiClient.flush();
this._aiClient = undefined;
}
return Promise.resolve(undefined);
}
}
class WebTelemetryAppender implements ITelemetryAppender {
constructor(private _appender: ITelemetryAppender) { }
log(eventName: string, data: any): void {
this._appender.log(eventName, data);
}
flush(): Promise<void> {
return this._appender.flush();
}
}
export class TelemetryService extends Disposable implements ITelemetryService {
declare readonly _serviceBrand: undefined;
private impl: ITelemetryService;
private impl: ITelemetryService = NullTelemetryService;
public readonly sendErrorTelemetry = true;
constructor(
@@ -120,19 +37,46 @@ export class TelemetryService extends Disposable implements ITelemetryService {
) {
super();
if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.asimovKey) {
this.impl = this.initializeService(environmentService, loggerService, configurationService, storageService, productService, remoteAgentService);
// When the level changes it could change from off to on and we want to make sure telemetry is properly intialized
this._register(configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(TELEMETRY_SETTING_ID)) {
this.impl = this.initializeService(environmentService, loggerService, configurationService, storageService, productService, remoteAgentService);
}
}));
}
/**
* Initializes the telemetry service to be a full fledged service.
* This is only done once and only when telemetry is enabled as this will also ping the endpoint to
* ensure its not adblocked and we can send telemetry
*/
private initializeService(
environmentService: IBrowserWorkbenchEnvironmentService,
loggerService: ILoggerService,
configurationService: IConfigurationService,
storageService: IStorageService,
productService: IProductService,
remoteAgentService: IRemoteAgentService
) {
const telemetrySupported = supportsTelemetry(productService, environmentService) && productService.aiConfig?.ariaKey;
if (telemetrySupported && getTelemetryLevel(configurationService) !== TelemetryLevel.NONE && this.impl === NullTelemetryService) {
// If remote server is present send telemetry through that, else use the client side appender
const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey);
const appenders = [];
const isInternal = isInternalTelemetry(productService, configurationService);
const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new OneDataSystemWebAppender(isInternal, 'adsworkbench', null, productService.aiConfig?.ariaKey); // {{SQL CARBON EDIT}} Use our own event prefix
appenders.push(telemetryProvider);
appenders.push(new TelemetryLogAppender(loggerService, environmentService));
const config: ITelemetryServiceConfig = {
appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)],
appenders,
commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties),
sendErrorTelemetry: this.sendErrorTelemetry,
};
this.impl = this._register(new BaseTelemetryService(config, configurationService, productService));
} else {
this.impl = NullTelemetryService;
return this._register(new BaseTelemetryService(config, configurationService, productService));
}
return this.impl;
}
setExperimentProperty(name: string, value: string): void {
@@ -164,4 +108,5 @@ export class TelemetryService extends Disposable implements ITelemetryService {
}
}
registerSingleton(ITelemetryService, TelemetryService);
registerSingleton(ITelemetryService, TelemetryService, true);