mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-17 23:35:54 +01:00
Move appenders to be better controlled by services (#133465)
* Cleanup telemetry appenders to be owned by service * Add telemetry level to services * simplify * Fix compile * Rename supportsTelemetryLogging -> supportsTelemetry Co-authored-by: SteVen Batten <sbatten@microsoft.com>
This commit is contained in:
@@ -61,11 +61,11 @@ import { ISharedProcessConfiguration } from 'vs/platform/sharedProcess/node/shar
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { NativeStorageService } from 'vs/platform/storage/electron-sandbox/storageService';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { ICustomEndpointTelemetryService, ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ICustomEndpointTelemetryService, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { combinedAppender, getTelemetryLevel, ITelemetryAppender, NullAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry, ITelemetryAppender, NullAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
|
||||
import { CustomEndpointTelemetryService } from 'vs/platform/telemetry/node/customEndpointTelemetryService';
|
||||
import { LocalReconnectConstants, TerminalIpcChannels, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
@@ -213,21 +213,21 @@ class SharedProcessMain extends Disposable {
|
||||
// Telemetry
|
||||
let telemetryService: ITelemetryService;
|
||||
let telemetryAppender: ITelemetryAppender;
|
||||
let telemetryLevel = getTelemetryLevel(productService, environmentService);
|
||||
if (telemetryLevel >= TelemetryLevel.LOG) {
|
||||
const appenders: ITelemetryAppender[] = [];
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
telemetryAppender = new TelemetryLogAppender(loggerService, environmentService);
|
||||
|
||||
appenders.push(telemetryAppender);
|
||||
const { appRoot, extensionsPath, installSourcePath } = environmentService;
|
||||
|
||||
// Application Insights
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey && telemetryLevel >= TelemetryLevel.USER) {
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey) {
|
||||
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey);
|
||||
this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender);
|
||||
appenders.push(appInsightsAppender);
|
||||
}
|
||||
|
||||
telemetryService = new TelemetryService({
|
||||
appender: telemetryAppender,
|
||||
appenders,
|
||||
commonProperties: resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
|
||||
sendErrorTelemetry: true,
|
||||
piiPaths: [appRoot, extensionsPath]
|
||||
|
||||
@@ -65,10 +65,10 @@ import { IStateMainService } from 'vs/platform/state/electron-main/state';
|
||||
import { StorageDatabaseChannel } from 'vs/platform/storage/electron-main/storageIpc';
|
||||
import { IStorageMainService, StorageMainService } from 'vs/platform/storage/electron-main/storageMainService';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { ITelemetryService, machineIdKey, TelemetryConfiguration, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService, machineIdKey, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { NullTelemetryService, getTelemetryLevel, getTelemetryConfiguration } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { getTelemetryLevel, NullTelemetryService, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IUpdateService } from 'vs/platform/update/common/update';
|
||||
import { UpdateChannel } from 'vs/platform/update/common/updateIpc';
|
||||
import { DarwinUpdateService } from 'vs/platform/update/electron-main/updateService.darwin';
|
||||
@@ -531,12 +531,12 @@ export class CodeApplication extends Disposable {
|
||||
services.set(IURLService, new SyncDescriptor(NativeURLService));
|
||||
|
||||
// Telemetry
|
||||
if (getTelemetryLevel(this.productService, this.environmentMainService) >= TelemetryLevel.USER) {
|
||||
if (supportsTelemetry(this.productService, this.environmentMainService)) {
|
||||
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), hostname(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const piiPaths = [this.environmentMainService.appRoot, this.environmentMainService.extensionsPath];
|
||||
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
const config: ITelemetryServiceConfig = { appenders: [appender], commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
|
||||
services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config]));
|
||||
} else {
|
||||
@@ -981,8 +981,8 @@ export class CodeApplication extends Disposable {
|
||||
const argvString = argvContent.value.toString();
|
||||
const argvJSON = JSON.parse(stripComments(argvString));
|
||||
if (argvJSON['enable-crash-reporter'] === undefined) {
|
||||
const telemetryConfig = getTelemetryConfiguration(this.configurationService);
|
||||
const enableCrashReporterSetting = telemetryConfig === TelemetryConfiguration.ON || telemetryConfig === TelemetryConfiguration.ERROR;
|
||||
const telemetryConfig = getTelemetryLevel(this.configurationService);
|
||||
const enableCrashReporterSetting = telemetryConfig >= TelemetryLevel.ERROR;
|
||||
const enableCrashReporter = typeof enableCrashReporterSetting === 'boolean' ? enableCrashReporterSetting : true;
|
||||
const additionalArgvContent = [
|
||||
'',
|
||||
@@ -1044,3 +1044,4 @@ export class CodeApplication extends Disposable {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { RequestService } from 'vs/platform/request/node/requestService';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { ITelemetryService, machineIdKey, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService, machineIdKey } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { combinedAppender, getTelemetryLevel, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
|
||||
import { buildTelemetryMessage } from 'vs/platform/telemetry/node/telemetry';
|
||||
|
||||
@@ -89,7 +89,10 @@ class CliMain extends Disposable {
|
||||
await this.doRun(environmentService, extensionManagementCLIService, fileService);
|
||||
|
||||
// Flush the remaining data in AI adapter (with 1s timeout)
|
||||
return raceTimeout(combinedAppender(...appenders).flush(), 1000);
|
||||
await Promise.all(appenders.map(a => {
|
||||
raceTimeout(a.flush(), 1000);
|
||||
}));
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,7 +151,7 @@ class CliMain extends Disposable {
|
||||
|
||||
// Telemetry
|
||||
const appenders: AppInsightsAppender[] = [];
|
||||
if (getTelemetryLevel(productService, environmentService) >= TelemetryLevel.USER) {
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey) {
|
||||
appenders.push(new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey));
|
||||
}
|
||||
@@ -156,7 +159,7 @@ class CliMain extends Disposable {
|
||||
const { appRoot, extensionsPath, installSourcePath } = environmentService;
|
||||
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appender: combinedAppender(...appenders),
|
||||
appenders,
|
||||
sendErrorTelemetry: false,
|
||||
commonProperties: (async () => {
|
||||
let machineId: string | undefined = undefined;
|
||||
|
||||
@@ -38,7 +38,7 @@ import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayo
|
||||
import { ILabelService, ResourceLabelFormatter, IFormatterChangeEvent } from 'vs/platform/label/common/label';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification';
|
||||
import { IProgressRunner, IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryInfo, ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, IWorkspaceFoldersWillChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
@@ -574,7 +574,7 @@ export class SimpleResourcePropertiesService implements ITextResourcePropertiesS
|
||||
export class StandaloneTelemetryService implements ITelemetryService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
public isOptedIn = false;
|
||||
public telemetryLevel = TelemetryLevel.NONE;
|
||||
public sendErrorTelemetry = false;
|
||||
|
||||
public setEnabled(value: boolean): void {
|
||||
|
||||
@@ -24,8 +24,8 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { asJson, asText, IRequestService, isSuccess } from 'vs/platform/request/common/request';
|
||||
import { getServiceMachineId } from 'vs/platform/serviceMachineId/common/serviceMachineId';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService, TelemetryConfiguration, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryConfiguration, getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
const CURRENT_TARGET_PLATFORM = isWeb ? TargetPlatform.WEB : getTargetPlatform(platform, arch);
|
||||
|
||||
@@ -959,7 +959,7 @@ export async function resolveMarketplaceHeaders(version: string, productService:
|
||||
'User-Agent': `VSCode ${version}`
|
||||
};
|
||||
const uuid = await getServiceMachineId(environmentService, fileService, storageService);
|
||||
if (getTelemetryLevel(productService, environmentService) >= TelemetryLevel.USER && getTelemetryConfiguration(configurationService) === TelemetryConfiguration.ON) {
|
||||
if (supportsTelemetry(productService, environmentService) && getTelemetryLevel(configurationService) === TelemetryLevel.USAGE) {
|
||||
headers['X-Market-User-Id'] = uuid;
|
||||
}
|
||||
return headers;
|
||||
|
||||
@@ -43,13 +43,11 @@ export interface ITelemetryService {
|
||||
|
||||
publicLogError2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>): Promise<void>;
|
||||
|
||||
setEnabled(value: boolean): void;
|
||||
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo>;
|
||||
|
||||
setExperimentProperty(name: string, value: string): void;
|
||||
|
||||
isOptedIn: boolean;
|
||||
telemetryLevel: TelemetryLevel;
|
||||
}
|
||||
|
||||
export interface ITelemetryEndpoint {
|
||||
@@ -81,8 +79,8 @@ export const TELEMETRY_OLD_SETTING_ID = 'telemetry.enableTelemetry';
|
||||
|
||||
export const enum TelemetryLevel {
|
||||
NONE = 0,
|
||||
LOG = 1,
|
||||
USER = 2
|
||||
ERROR = 2,
|
||||
USAGE = 3
|
||||
}
|
||||
|
||||
export const enum TelemetryConfiguration {
|
||||
|
||||
@@ -13,11 +13,11 @@ import { ConfigurationScope, Extensions, IConfigurationRegistry } from 'vs/platf
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ITelemetryData, ITelemetryInfo, ITelemetryService, TelemetryConfiguration, TELEMETRY_OLD_SETTING_ID, TELEMETRY_SECTION_ID, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryConfiguration, ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ITelemetryData, ITelemetryInfo, ITelemetryService, TelemetryConfiguration, TelemetryLevel, TELEMETRY_OLD_SETTING_ID, TELEMETRY_SECTION_ID, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel, ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
export interface ITelemetryServiceConfig {
|
||||
appender: ITelemetryAppender;
|
||||
appenders: ITelemetryAppender[];
|
||||
sendErrorTelemetry?: boolean;
|
||||
commonProperties?: Promise<{ [name: string]: any }>;
|
||||
piiPaths?: string[];
|
||||
@@ -30,13 +30,11 @@ export class TelemetryService implements ITelemetryService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private _appender: ITelemetryAppender;
|
||||
private _appenders: ITelemetryAppender[];
|
||||
private _commonProperties: Promise<{ [name: string]: any; }>;
|
||||
private _experimentProperties: { [name: string]: string } = {};
|
||||
private _piiPaths: string[];
|
||||
private _userOptIn: boolean;
|
||||
private _errorOptIn: boolean;
|
||||
private _enabled: boolean;
|
||||
private _telemetryLevel: TelemetryLevel;
|
||||
public readonly sendErrorTelemetry: boolean;
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
@@ -46,12 +44,10 @@ export class TelemetryService implements ITelemetryService {
|
||||
config: ITelemetryServiceConfig,
|
||||
@IConfigurationService private _configurationService: IConfigurationService
|
||||
) {
|
||||
this._appender = config.appender;
|
||||
this._appenders = config.appenders;
|
||||
this._commonProperties = config.commonProperties || Promise.resolve({});
|
||||
this._piiPaths = config.piiPaths || [];
|
||||
this._userOptIn = true;
|
||||
this._errorOptIn = true;
|
||||
this._enabled = true;
|
||||
this._telemetryLevel = TelemetryLevel.USAGE;
|
||||
this.sendErrorTelemetry = !!config.sendErrorTelemetry;
|
||||
|
||||
// static cleanup pattern for: `file:///DANGEROUS/PATH/resources/app/Useful/Information`
|
||||
@@ -62,15 +58,15 @@ export class TelemetryService implements ITelemetryService {
|
||||
}
|
||||
|
||||
|
||||
this._updateUserOptIn();
|
||||
this._configurationService.onDidChangeConfiguration(this._updateUserOptIn, this, this._disposables);
|
||||
this._updateTelemetryLevel();
|
||||
this._configurationService.onDidChangeConfiguration(this._updateTelemetryLevel, this, this._disposables);
|
||||
type OptInClassification = {
|
||||
optIn: { classification: 'SystemMetaData', purpose: 'BusinessInsight', isMeasurement: true };
|
||||
};
|
||||
type OptInEvent = {
|
||||
optIn: boolean;
|
||||
};
|
||||
this.publicLog2<OptInEvent, OptInClassification>('optInStatus', { optIn: this._userOptIn });
|
||||
this.publicLog2<OptInEvent, OptInClassification>('optInStatus', { optIn: this._telemetryLevel === TelemetryLevel.USAGE });
|
||||
|
||||
this._commonProperties.then(values => {
|
||||
const isHashedId = /^[a-f0-9]+$/i.test(values['common.machineId']);
|
||||
@@ -95,10 +91,6 @@ export class TelemetryService implements ITelemetryService {
|
||||
this._experimentProperties[name] = value;
|
||||
}
|
||||
|
||||
setEnabled(value: boolean): void {
|
||||
this._enabled = value;
|
||||
}
|
||||
|
||||
// TODO: @sbatten @lramos15 bring this code in after one iteration
|
||||
// private _convertOldTelemetrySettingToNew(): void {
|
||||
// const telemetryValue = this._configurationService.getValue(TELEMETRY_OLD_SETTING_ID);
|
||||
@@ -107,14 +99,12 @@ export class TelemetryService implements ITelemetryService {
|
||||
// }
|
||||
// }
|
||||
|
||||
private _updateUserOptIn(): void {
|
||||
const telemetryConfig = getTelemetryConfiguration(this._configurationService);
|
||||
this._errorOptIn = telemetryConfig !== TelemetryConfiguration.OFF;
|
||||
this._userOptIn = telemetryConfig === TelemetryConfiguration.ON;
|
||||
private _updateTelemetryLevel(): void {
|
||||
this._telemetryLevel = getTelemetryLevel(this._configurationService);
|
||||
}
|
||||
|
||||
get isOptedIn(): boolean {
|
||||
return this._userOptIn && this._enabled;
|
||||
get telemetryLevel(): TelemetryLevel {
|
||||
return this._telemetryLevel;
|
||||
}
|
||||
|
||||
async getTelemetryInfo(): Promise<ITelemetryInfo> {
|
||||
@@ -134,9 +124,9 @@ export class TelemetryService implements ITelemetryService {
|
||||
this._disposables.dispose();
|
||||
}
|
||||
|
||||
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<any> {
|
||||
private _log(eventName: string, eventLevel: TelemetryLevel, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<any> {
|
||||
// don't send events when the user is optout
|
||||
if (!this.isOptedIn) {
|
||||
if (this.telemetryLevel < eventLevel) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -156,7 +146,8 @@ export class TelemetryService implements ITelemetryService {
|
||||
return undefined;
|
||||
});
|
||||
|
||||
this._appender.log(eventName, data);
|
||||
// Log to the appenders of sufficient level
|
||||
this._appenders.forEach(a => a.log(eventName, data));
|
||||
|
||||
}, err => {
|
||||
// unsure what to do now...
|
||||
@@ -164,17 +155,21 @@ export class TelemetryService implements ITelemetryService {
|
||||
});
|
||||
}
|
||||
|
||||
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<any> {
|
||||
return this._log(eventName, TelemetryLevel.USAGE, data, anonymizeFilePaths);
|
||||
}
|
||||
|
||||
publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>, anonymizeFilePaths?: boolean): Promise<any> {
|
||||
return this.publicLog(eventName, data as ITelemetryData, anonymizeFilePaths);
|
||||
}
|
||||
|
||||
publicLogError(errorEventName: string, data?: ITelemetryData): Promise<any> {
|
||||
if (!this.sendErrorTelemetry || !this._errorOptIn) {
|
||||
if (!this.sendErrorTelemetry) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
// Send error event and anonymize paths
|
||||
return this.publicLog(errorEventName, data, true);
|
||||
return this._log(errorEventName, TelemetryLevel.ERROR, data, true);
|
||||
}
|
||||
|
||||
publicLogError2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>): Promise<any> {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Promises } from 'vs/base/common/async';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { safeStringify } from 'vs/base/common/objects';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
@@ -31,8 +30,7 @@ export const NullTelemetryService = new class implements ITelemetryService {
|
||||
}
|
||||
|
||||
setExperimentProperty() { }
|
||||
setEnabled() { }
|
||||
isOptedIn = true;
|
||||
telemetryLevel = TelemetryLevel.NONE;
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo> {
|
||||
return Promise.resolve({
|
||||
instanceId: 'someValue.instanceId',
|
||||
@@ -60,13 +58,6 @@ export interface ITelemetryAppender {
|
||||
flush(): Promise<any>;
|
||||
}
|
||||
|
||||
export function combinedAppender(...appenders: ITelemetryAppender[]): ITelemetryAppender {
|
||||
return {
|
||||
log: (e, d) => appenders.forEach(a => a.log(e, d)),
|
||||
flush: () => Promises.settled(appenders.map(a => a.flush())),
|
||||
};
|
||||
}
|
||||
|
||||
export const NullAppender: ITelemetryAppender = { log: () => null, flush: () => Promise.resolve(null) };
|
||||
|
||||
|
||||
@@ -107,44 +98,40 @@ export function configurationTelemetry(telemetryService: ITelemetryService, conf
|
||||
/**
|
||||
* Determines how telemetry is handled based on the current running configuration.
|
||||
* To log telemetry locally, the client must not disable telemetry via the CLI
|
||||
* If client is a built product and telemetry is enabled via the product.json, defer to user setting
|
||||
* Note that when running from sources, we log telemetry locally but do not send it
|
||||
* If client is a built product and telemetry is enabled via the product.json, telemetry is supported
|
||||
* This function is only used to determine if telemetry contructs should occur, but is not impacted by user configuration
|
||||
*
|
||||
* @param productService
|
||||
* @param environmentService
|
||||
* @returns NONE - telemetry is completely disabled, LOG - telemetry is logged locally but not sent, USER - verify with user setting
|
||||
* @returns false - telemetry is completely disabled, true - telemetry is logged locally, but may not be sent
|
||||
*/
|
||||
export function getTelemetryLevel(productService: IProductService, environmentService: IEnvironmentService): TelemetryLevel {
|
||||
if (environmentService.disableTelemetry || !productService.enableTelemetry) {
|
||||
return TelemetryLevel.NONE;
|
||||
}
|
||||
|
||||
if (!environmentService.isBuilt) {
|
||||
return TelemetryLevel.LOG;
|
||||
}
|
||||
|
||||
return TelemetryLevel.USER;
|
||||
export function supportsTelemetry(productService: IProductService, environmentService: IEnvironmentService): boolean {
|
||||
return !(environmentService.disableTelemetry || !productService.enableTelemetry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines how telemetry is handled based on the current running configuration.
|
||||
* To log telemetry locally, the client must not disable telemetry via the CLI
|
||||
* If client is a built product and telemetry is enabled via the product.json, defer to user setting
|
||||
* Note that when running from sources, we log telemetry locally but do not send it
|
||||
* Determines how telemetry is handled based on the user's configuration.
|
||||
*
|
||||
* @param configurationService
|
||||
* @returns OFF, ERROR, ON
|
||||
*/
|
||||
export function getTelemetryConfiguration(configurationService: IConfigurationService): TelemetryConfiguration {
|
||||
export function getTelemetryLevel(configurationService: IConfigurationService): TelemetryLevel {
|
||||
const newConfig = configurationService.getValue<TelemetryConfiguration>(TELEMETRY_SETTING_ID);
|
||||
const oldConfig = configurationService.getValue(TELEMETRY_OLD_SETTING_ID);
|
||||
|
||||
// Check old config for disablement
|
||||
if (oldConfig !== undefined && oldConfig === false) {
|
||||
return TelemetryConfiguration.OFF;
|
||||
return TelemetryLevel.NONE;
|
||||
}
|
||||
|
||||
return newConfig ?? TelemetryConfiguration.ON;
|
||||
switch (newConfig ?? TelemetryConfiguration.ON) {
|
||||
case TelemetryConfiguration.ON:
|
||||
return TelemetryLevel.USAGE;
|
||||
case TelemetryConfiguration.ERROR:
|
||||
return TelemetryLevel.ERROR;
|
||||
case TelemetryConfiguration.OFF:
|
||||
return TelemetryLevel.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Properties {
|
||||
|
||||
@@ -12,8 +12,6 @@ import { ICustomEndpointTelemetryService, ITelemetryData, ITelemetryEndpoint, IT
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { combinedAppender } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
export class CustomEndpointTelemetryService implements ICustomEndpointTelemetryService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
@@ -48,13 +46,13 @@ export class CustomEndpointTelemetryService implements ICustomEndpointTelemetryS
|
||||
);
|
||||
|
||||
const channel = client.getChannel('telemetryAppender');
|
||||
const appender = combinedAppender(
|
||||
const appenders = [
|
||||
new TelemetryAppenderClient(channel),
|
||||
new TelemetryLogAppender(this.loggerService, this.environmentService, `[${endpoint.id}] `),
|
||||
);
|
||||
];
|
||||
|
||||
this.customTelemetryServices.set(endpoint.id, new TelemetryService({
|
||||
appender,
|
||||
appenders,
|
||||
sendErrorTelemetry: endpoint.sendErrorTelemetry
|
||||
}, this.configurationService));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as Errors from 'vs/base/common/errors';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
|
||||
import { ITelemetryData, TelemetryConfiguration } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryData, TelemetryConfiguration, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { ITelemetryAppender, NullAppender } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
@@ -89,7 +89,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
test('Disposing', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, new TestConfigurationService());
|
||||
let service = new TelemetryService({ appenders: [testAppender] }, new TestConfigurationService());
|
||||
|
||||
return service.publicLog('testPrivateEvent').then(() => {
|
||||
assert.strictEqual(testAppender.getEventsCount(), 3);
|
||||
@@ -102,7 +102,7 @@ suite('TelemetryService', () => {
|
||||
// event reporting
|
||||
test('Simple event', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, new TestConfigurationService());
|
||||
let service = new TelemetryService({ appenders: [testAppender] }, new TestConfigurationService());
|
||||
|
||||
return service.publicLog('testEvent').then(_ => {
|
||||
assert.strictEqual(testAppender.getEventsCount(), 3);
|
||||
@@ -117,7 +117,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
test('Event with data', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, new TestConfigurationService());
|
||||
let service = new TelemetryService({ appenders: [testAppender] }, new TestConfigurationService());
|
||||
|
||||
return service.publicLog('testEvent', {
|
||||
'stringProp': 'property',
|
||||
@@ -144,7 +144,7 @@ suite('TelemetryService', () => {
|
||||
test('common properties added to *all* events, simple event', function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({
|
||||
appender: testAppender,
|
||||
appenders: [testAppender],
|
||||
commonProperties: Promise.resolve({ foo: 'JA!', get bar() { return Math.random(); } })
|
||||
}, new TestConfigurationService());
|
||||
|
||||
@@ -162,7 +162,7 @@ suite('TelemetryService', () => {
|
||||
test('common properties added to *all* events, event with data', function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({
|
||||
appender: testAppender,
|
||||
appenders: [testAppender],
|
||||
commonProperties: Promise.resolve({ foo: 'JA!', get bar() { return Math.random(); } })
|
||||
}, new TestConfigurationService());
|
||||
|
||||
@@ -181,7 +181,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
test('TelemetryInfo comes from properties', function () {
|
||||
let service = new TelemetryService({
|
||||
appender: NullAppender,
|
||||
appenders: [NullAppender],
|
||||
commonProperties: Promise.resolve({
|
||||
sessionID: 'one',
|
||||
['common.instanceId']: 'two',
|
||||
@@ -200,7 +200,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
test('telemetry on by default', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, new TestConfigurationService());
|
||||
let service = new TelemetryService({ appenders: [testAppender] }, new TestConfigurationService());
|
||||
|
||||
return service.publicLog('testEvent').then(() => {
|
||||
assert.strictEqual(testAppender.getEventsCount(), 3);
|
||||
@@ -241,7 +241,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
try {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let testError = new Error('test');
|
||||
@@ -330,7 +330,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let personInfoWithSpaces = settings.personalInfo.slice(0, 2) + ' ' + settings.personalInfo.slice(2);
|
||||
@@ -354,7 +354,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousFilenameError: any = new Error('dangerousFilename');
|
||||
@@ -386,7 +386,7 @@ suite('TelemetryService', () => {
|
||||
try {
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithoutImportantInfoError: any = new Error(settings.dangerousPathWithoutImportantInfo);
|
||||
@@ -416,7 +416,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithoutImportantInfoError: any = new Error('dangerousPathWithoutImportantInfo');
|
||||
@@ -446,7 +446,7 @@ suite('TelemetryService', () => {
|
||||
try {
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo);
|
||||
@@ -479,7 +479,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo');
|
||||
@@ -511,7 +511,7 @@ suite('TelemetryService', () => {
|
||||
try {
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo);
|
||||
@@ -540,7 +540,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo');
|
||||
@@ -569,7 +569,7 @@ suite('TelemetryService', () => {
|
||||
try {
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender, piiPaths: [settings.personalInfo + '/resources/app/'] });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender], piiPaths: [settings.personalInfo + '/resources/app/'] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo);
|
||||
@@ -602,7 +602,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender, piiPaths: [settings.personalInfo + '/resources/app/'] });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender], piiPaths: [settings.personalInfo + '/resources/app/'] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo');
|
||||
@@ -634,7 +634,7 @@ suite('TelemetryService', () => {
|
||||
try {
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let missingModelError: any = new Error(settings.missingModelMessage);
|
||||
@@ -667,7 +667,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let missingModelError: any = new Error('missingModelMessage');
|
||||
@@ -700,7 +700,7 @@ suite('TelemetryService', () => {
|
||||
try {
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let noSuchFileError: any = new Error(settings.noSuchFileMessage);
|
||||
@@ -737,7 +737,7 @@ suite('TelemetryService', () => {
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new JoinableTelemetryService({ appender: testAppender });
|
||||
let service = new JoinableTelemetryService({ appenders: [testAppender] });
|
||||
const errorTelemetry = new ErrorTelemetry(service);
|
||||
|
||||
let noSuchFileError: any = new Error('noSuchFileMessage');
|
||||
@@ -768,7 +768,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
test('Telemetry Service sends events when telemetry is on', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, new TestConfigurationService());
|
||||
let service = new TelemetryService({ appenders: [testAppender] }, new TestConfigurationService());
|
||||
|
||||
return service.publicLog('testEvent').then(() => {
|
||||
assert.strictEqual(testAppender.getEventsCount(), 3);
|
||||
@@ -783,7 +783,7 @@ suite('TelemetryService', () => {
|
||||
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({
|
||||
appender: testAppender
|
||||
appenders: [testAppender]
|
||||
}, new class extends TestConfigurationService {
|
||||
override onDidChangeConfiguration = emitter.event;
|
||||
override getValue() {
|
||||
@@ -791,15 +791,15 @@ suite('TelemetryService', () => {
|
||||
}
|
||||
}());
|
||||
|
||||
assert.strictEqual(service.isOptedIn, false);
|
||||
assert.strictEqual(service.telemetryLevel, TelemetryLevel.NONE);
|
||||
|
||||
telemetryLevel = TelemetryConfiguration.ON;
|
||||
emitter.fire({});
|
||||
assert.strictEqual(service.isOptedIn, true);
|
||||
assert.strictEqual(service.telemetryLevel, TelemetryLevel.USAGE);
|
||||
|
||||
telemetryLevel = TelemetryConfiguration.ERROR;
|
||||
emitter.fire({});
|
||||
assert.strictEqual(service.isOptedIn, false);
|
||||
assert.strictEqual(service.telemetryLevel, TelemetryLevel.ERROR);
|
||||
|
||||
service.dispose();
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITelemetryService, TelemetryConfiguration, TelemetryLevel, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService, TelemetryLevel, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { MainThreadTelemetryShape, MainContext, IExtHostContext, ExtHostTelemetryShape, ExtHostContext } from '../common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
@@ -11,7 +11,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { getTelemetryConfiguration, getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTelemetry)
|
||||
export class MainThreadTelemetry extends Disposable implements MainThreadTelemetryShape {
|
||||
@@ -30,7 +30,7 @@ export class MainThreadTelemetry extends Disposable implements MainThreadTelemet
|
||||
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTelemetry);
|
||||
|
||||
if (getTelemetryLevel(this._productService, this._environmenService) >= TelemetryLevel.LOG) {
|
||||
if (supportsTelemetry(this._productService, this._environmenService)) {
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectedKeys.includes(TELEMETRY_SETTING_ID)) {
|
||||
this._proxy.$onDidChangeTelemetryEnabled(this.telemetryEnabled);
|
||||
@@ -42,11 +42,11 @@ export class MainThreadTelemetry extends Disposable implements MainThreadTelemet
|
||||
}
|
||||
|
||||
private get telemetryEnabled(): boolean {
|
||||
if (getTelemetryLevel(this._productService, this._environmenService) < TelemetryLevel.USER) {
|
||||
if (!supportsTelemetry(this._productService, this._environmenService)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getTelemetryConfiguration(this._configurationService) === TelemetryConfiguration.ON;
|
||||
return getTelemetryLevel(this._configurationService) === TelemetryLevel.USAGE;
|
||||
}
|
||||
|
||||
$publicLog(eventName: string, data: any = Object.create(null)): void {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler, Queue } from 'vs/base/common/async';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { ICustomEndpointTelemetryService, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ICustomEndpointTelemetryService, ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { normalizeDriveLetter } from 'vs/base/common/labels';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
|
||||
@@ -1039,7 +1039,7 @@ export class DebugSession implements IDebugSession {
|
||||
// only log telemetry events from debug adapter if the debug extension provided the telemetry key
|
||||
// and the user opted in telemetry
|
||||
const telemetryEndpoint = this.raw.dbgr.getCustomTelemetryEndpoint();
|
||||
if (telemetryEndpoint && this.telemetryService.isOptedIn) {
|
||||
if (telemetryEndpoint && this.telemetryService.telemetryLevel !== TelemetryLevel.NONE) {
|
||||
// __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly.
|
||||
let data = event.body.data;
|
||||
if (!telemetryEndpoint.sendErrorTelemetry && event.body.data) {
|
||||
|
||||
@@ -22,11 +22,10 @@ import { isWeb } from 'vs/base/common/platform';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleaner';
|
||||
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { getErrorMessage } from 'vs/base/common/errors';
|
||||
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions);
|
||||
workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(SetLogLevelAction), 'Developer: Set Log Level...', CATEGORIES.Developer.value);
|
||||
@@ -54,7 +53,7 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution {
|
||||
this.registerLogChannel(Constants.rendererLogChannelId, nls.localize('rendererLog', "Window"), this.environmentService.logFile);
|
||||
|
||||
const registerTelemetryChannel = () => {
|
||||
if (getTelemetryLevel(this.productService, this.environmentService) >= TelemetryLevel.LOG && this.logService.getLevel() === LogLevel.Trace) {
|
||||
if (supportsTelemetry(this.productService, this.environmentService) && this.logService.getLevel() === LogLevel.Trace) {
|
||||
this.registerLogChannel(Constants.telemetryLogChannelId, nls.localize('telemetryLog', "Telemetry"), this.environmentService.telemetryLogResource);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remot
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderCommand, SaveLocalFileCommand, RemoteFileDialogContext } from 'vs/workbench/services/dialogs/browser/simpleFileDialog';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { TelemetryConfiguration, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryConfiguration } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { TelemetryLevel, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
class RemoteChannelsContribution implements IWorkbenchContribution {
|
||||
|
||||
@@ -113,7 +113,7 @@ class RemoteTelemetryEnablementUpdater extends Disposable implements IWorkbenchC
|
||||
}
|
||||
|
||||
private updateRemoteTelemetryEnablement(): Promise<void> {
|
||||
if (getTelemetryConfiguration(this.configurationService) === TelemetryConfiguration.OFF) {
|
||||
if (getTelemetryLevel(this.configurationService) === TelemetryLevel.NONE) {
|
||||
return this.remoteAgentService.disableTelemetry();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { sha1Hex } from 'vs/base/browser/hash';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService, IFileStat } from 'vs/platform/files/common/files';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { ITextFileService, } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
@@ -36,7 +36,7 @@ export class WorkspaceTags implements IWorkbenchContribution {
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService
|
||||
) {
|
||||
if (this.telemetryService.isOptedIn) {
|
||||
if (this.telemetryService.telemetryLevel === TelemetryLevel.USAGE) {
|
||||
this.report();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { asText, IRequestService } from 'vs/platform/request/common/request';
|
||||
import { ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DEFAULT_MARKDOWN_STYLES, renderMarkdownDocument } from 'vs/workbench/contrib/markdown/browser/markdownDocumentRenderer';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
export class ReleaseNotesManager {
|
||||
|
||||
@@ -195,7 +195,7 @@ export class ReleaseNotesManager {
|
||||
}
|
||||
|
||||
private async addGAParameters(uri: URI, origin: string, experiment = '1'): Promise<URI> {
|
||||
if (getTelemetryLevel(this._productService, this._environmentService) >= TelemetryLevel.USER) {
|
||||
if (supportsTelemetry(this._productService, this._environmentService)) {
|
||||
if (uri.scheme === 'https' && uri.authority === 'code.visualstudio.com') {
|
||||
const info = await this._telemetryService.getTelemetryInfo();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platfor
|
||||
import { welcomePageBackground, welcomePageProgressBackground, welcomePageProgressForeground, welcomePageTileBackground, welcomePageTileHoverBackground, welcomePageTileShadow } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedColors';
|
||||
import { activeContrastBorder, buttonBackground, buttonForeground, buttonHoverBackground, contrastBorder, descriptionForeground, focusBorder, foreground, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { firstSessionDateStorageKey, ITelemetryService, TelemetryConfiguration } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { firstSessionDateStorageKey, ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { gettingStartedCheckedCodicon, gettingStartedUncheckedCodicon } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedIcons';
|
||||
import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
@@ -67,7 +67,7 @@ import { GettingStartedIndexList } from './gettingStartedList';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { getTelemetryConfiguration } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
const SLIDE_TRANSITION_TIME_MS = 250;
|
||||
const configurationKey = 'workbench.startupEditor';
|
||||
@@ -1392,7 +1392,7 @@ export class GettingStartedPage extends EditorPane {
|
||||
const stepListComponent = this.detailsScrollbar.getDomNode();
|
||||
|
||||
const categoryFooter = $('.getting-started-footer');
|
||||
if (this.editorInput.showTelemetryNotice && getTelemetryConfiguration(this.configurationService) !== TelemetryConfiguration.OFF && product.enableTelemetry) {
|
||||
if (this.editorInput.showTelemetryNotice && getTelemetryLevel(this.configurationService) !== TelemetryLevel.NONE && product.enableTelemetry) {
|
||||
const mdRenderer = this._register(this.instantiationService.createInstance(MarkdownRenderer, {}));
|
||||
|
||||
const privacyStatementCopy = localize('privacy statement', "privacy statement");
|
||||
|
||||
@@ -22,8 +22,8 @@ import { GettingStartedInput, gettingStartedInputTypeId } from 'vs/workbench/con
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { getTelemetryConfiguration } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { TelemetryConfiguration } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
const configurationKey = 'workbench.startupEditor';
|
||||
const oldConfigurationKey = 'workbench.welcome.enabled';
|
||||
@@ -52,7 +52,7 @@ export class WelcomePageContribution implements IWorkbenchContribution {
|
||||
// Always open Welcome page for first-launch, no matter what is open or which startupEditor is set.
|
||||
if (
|
||||
product.enableTelemetry
|
||||
&& getTelemetryConfiguration(this.configurationService) !== TelemetryConfiguration.OFF
|
||||
&& getTelemetryLevel(this.configurationService) !== TelemetryLevel.NONE
|
||||
&& !this.environmentService.skipWelcome
|
||||
&& !this.storageService.get(telemetryOptOutStorageKey, StorageScope.GLOBAL)
|
||||
) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import * as platform from 'vs/base/common/platform';
|
||||
import type { IKeyValueStorage, IExperimentationTelemetry, IExperimentationFilterProvider, ExperimentationService as TASClient } from 'tas-client-umd';
|
||||
import { MementoObject, Memento } from 'vs/workbench/common/memento';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryData } from 'vs/base/common/actions';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
@@ -199,7 +199,7 @@ export class ExperimentService implements ITASExperimentService {
|
||||
@IProductService private productService: IProductService
|
||||
) {
|
||||
|
||||
if (productService.tasConfig && this.experimentsEnabled && this.telemetryService.isOptedIn) {
|
||||
if (productService.tasConfig && this.experimentsEnabled && this.telemetryService.telemetryLevel === TelemetryLevel.USAGE) {
|
||||
this.tasClient = this.setupTASClient();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import { getServiceMachineId } from 'vs/platform/serviceMachineId/common/service
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { getTelemetryConfiguration, getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { TelemetryConfiguration, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
class ExtensionResourceLoaderService implements IExtensionResourceLoaderService {
|
||||
|
||||
@@ -52,7 +52,7 @@ class ExtensionResourceLoaderService implements IExtensionResourceLoaderService
|
||||
'X-Client-Name': `${this._productService.applicationName}${isWeb ? '-web' : ''}`,
|
||||
'X-Client-Version': this._productService.version
|
||||
};
|
||||
if (getTelemetryLevel(this._productService, this._environmentService) >= TelemetryLevel.USER && getTelemetryConfiguration(this._configurationService) === TelemetryConfiguration.ON) {
|
||||
if (supportsTelemetry(this._productService, this._environmentService) && getTelemetryLevel(this._configurationService) === TelemetryLevel.USAGE) {
|
||||
requestInit.headers['X-Machine-Id'] = machineId;
|
||||
}
|
||||
if (this._productService.commit) {
|
||||
|
||||
@@ -11,10 +11,10 @@ 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 { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ITelemetryData, ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryData, ITelemetryInfo, ITelemetryService, TelemetryLevel } 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 { combinedAppender, ITelemetryAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ITelemetryAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { resolveWorkbenchCommonProperties } from 'vs/workbench/services/telemetry/browser/workbenchCommonProperties';
|
||||
@@ -117,7 +117,7 @@ export class TelemetryService extends Disposable implements ITelemetryService {
|
||||
// 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 config: ITelemetryServiceConfig = {
|
||||
appender: combinedAppender(new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)),
|
||||
appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)],
|
||||
commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, environmentService.options && environmentService.options.resolveCommonTelemetryProperties),
|
||||
sendErrorTelemetry: false,
|
||||
};
|
||||
@@ -128,16 +128,12 @@ export class TelemetryService extends Disposable implements ITelemetryService {
|
||||
}
|
||||
}
|
||||
|
||||
setEnabled(value: boolean): void {
|
||||
return this.impl.setEnabled(value);
|
||||
}
|
||||
|
||||
setExperimentProperty(name: string, value: string): void {
|
||||
return this.impl.setExperimentProperty(name, value);
|
||||
}
|
||||
|
||||
get isOptedIn(): boolean {
|
||||
return this.impl.isOptedIn;
|
||||
get telemetryLevel(): TelemetryLevel {
|
||||
return this.impl.telemetryLevel;
|
||||
}
|
||||
|
||||
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void> {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITelemetryService, ITelemetryInfo, ITelemetryData, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
|
||||
@@ -35,10 +35,10 @@ export class TelemetryService extends Disposable implements ITelemetryService {
|
||||
) {
|
||||
super();
|
||||
|
||||
if (getTelemetryLevel(productService, environmentService) >= TelemetryLevel.LOG) {
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
const channel = sharedProcessService.getChannel('telemetryAppender');
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appender: new TelemetryAppenderClient(channel),
|
||||
appenders: [new TelemetryAppenderClient(channel)],
|
||||
commonProperties: resolveWorkbenchCommonProperties(storageService, fileService, environmentService.os.release, environmentService.os.hostname, productService.commit, productService.version, environmentService.machineId, productService.msftInternalDomains, environmentService.installSourcePath, environmentService.remoteAuthority),
|
||||
piiPaths: [environmentService.appRoot, environmentService.extensionsPath],
|
||||
sendErrorTelemetry: true
|
||||
@@ -52,16 +52,12 @@ export class TelemetryService extends Disposable implements ITelemetryService {
|
||||
this.sendErrorTelemetry = this.impl.sendErrorTelemetry;
|
||||
}
|
||||
|
||||
setEnabled(value: boolean): void {
|
||||
return this.impl.setEnabled(value);
|
||||
}
|
||||
|
||||
setExperimentProperty(name: string, value: string): void {
|
||||
return this.impl.setExperimentProperty(name, value);
|
||||
}
|
||||
|
||||
get isOptedIn(): boolean {
|
||||
return this.impl.isOptedIn;
|
||||
get telemetryLevel(): TelemetryLevel {
|
||||
return this.impl.telemetryLevel;
|
||||
}
|
||||
|
||||
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void> {
|
||||
|
||||
@@ -24,7 +24,7 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryInfo, ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
@@ -162,7 +162,7 @@ suite.skip('TextSearch performance (integration)', () => {
|
||||
|
||||
class TestTelemetryService implements ITelemetryService {
|
||||
public _serviceBrand: undefined;
|
||||
public isOptedIn = true;
|
||||
public telemetryLevel = TelemetryLevel.USAGE;
|
||||
public sendErrorTelemetry = true;
|
||||
|
||||
public events: any[] = [];
|
||||
|
||||
Reference in New Issue
Block a user