Update to using latesst telemetry API

Telemetry API surface has changed so this updates as well to stay inline with that.
This commit is contained in:
Logan Ramos 2022-12-15 09:49:25 -05:00
Родитель ac706d483c
Коммит fdabcdde4a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: D9CCFF14F0B18183
8 изменённых файлов: 86 добавлений и 68 удалений

Просмотреть файл

@ -5,13 +5,13 @@
const fs = require('fs');
// Reads dist/node/common/baseTelemetryAppender.js and replaces PACKAGE_JSON_VERSION with the number from the package.json
// Reads dist/node/common/util.js and replaces PACKAGE_JSON_VERSION with the number from the package.json
const packageJson = require('./package.json');
const baseTelemetryAppender = fs.readFileSync('./dist/node/common/baseTelemetryAppender.js', 'utf8');
const newBaseTelemetryAppender = baseTelemetryAppender.replace(/PACKAGE_JSON_VERSION/g, packageJson.version);
fs.writeFileSync('./dist/node/common/baseTelemetryAppender.js', newBaseTelemetryAppender);
const baseUtil = fs.readFileSync('./dist/node/common/util.js', 'utf8');
const newBaseUtil = baseUtil.replace(/PACKAGE_JSON_VERSION/g, packageJson.version);
fs.writeFileSync('./dist/node/common/util.js', newBaseUtil);
// Reads dist/browser/common/baseTelemetryAppender.js and replaces PACKAGE_JSON_VERSION with the number from the package.json
const baseTelemetryAppenderBrowser = fs.readFileSync('./dist/browser/common/baseTelemetryAppender.js', 'utf8');
const newBaseTelemetryAppenderBrowser = baseTelemetryAppenderBrowser.replace(/PACKAGE_JSON_VERSION/g, packageJson.version);
fs.writeFileSync('./dist/browser/common/baseTelemetryAppender.js', newBaseTelemetryAppenderBrowser);
// Reads dist/browser/common/util.js and replaces PACKAGE_JSON_VERSION with the number from the package.json
const baseUtilBrowser = fs.readFileSync('./dist/browser/common/util.js', 'utf8');
const newBaseUtilBrowser = baseUtilBrowser.replace(/PACKAGE_JSON_VERSION/g, packageJson.version);
fs.writeFileSync('./dist/browser/common/util.js', newBaseUtilBrowser);

Просмотреть файл

@ -1,7 +1,7 @@
{
"name": "@vscode/extension-telemetry",
"description": "A module for Visual Studio Code extensions to report consistent telemetry.",
"version": "0.7.2-preview",
"version": "0.7.3-preview",
"author": {
"name": "Microsoft Corporation"
},
@ -11,7 +11,7 @@
"sideEffects": false,
"license": "MIT",
"engines": {
"vscode": "^1.73.0"
"vscode": "^1.74.0"
},
"scripts": {
"prepack": "node injectVersion.js",

Просмотреть файл

@ -55,15 +55,17 @@ export default class TelemetryReporter extends BaseTelemetryReporter {
clientFactory = (key: string) => oneDataSystemClientFactory(key, vscode);
}
const appender = new BaseTelemetryAppender(key, clientFactory, {
const osShim = {
release: navigator.appVersion,
platform: "web",
architecture: "web",
});
};
const appender = new BaseTelemetryAppender(key, clientFactory);
// AIF is no longer supported
if (key && (key.indexOf("AIF") === 0)) {
throw new Error("AIF keys are no longer supported. Please switch to 1DS keys for 1st party extensions");
}
super(appender, vscode);
super(appender, vscode, { additionalCommonProperties: TelemetryUtil.getAdditionalCommonProperties(osShim) });
}
}

Просмотреть файл

@ -33,42 +33,14 @@ export class BaseTelemetryAppender implements ILazyTelemetryAppender {
private _clientFactory: (key: string) => Promise<BaseTelemetryClient>;
private _key: string;
// We always want the built-in common properties
public readonly ignoreBuiltInCommonProperties: boolean = false;
constructor(
key: string,
clientFactory: (key: string) => Promise<BaseTelemetryClient>,
private osShim: { release: string, platform: string, architecture: string }
) {
this._clientFactory = clientFactory;
this._key = key;
}
// This also includes the common properties which core mixes in
// __GDPR__COMMON__ "common.os" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.nodeArch" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.platformversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.extname" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.extversion" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.vscodemachineid" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.vscodesessionid" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.vscodeversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.uikind" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.remotename" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.isnewappinstall" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.product" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.telemetryclientversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
public get additionalCommonProperties() {
return {
"common.os": this.osShim.platform,
"common.nodeArch": this.osShim.architecture,
"common.platformversion": (this.osShim.release || "").replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, "$1$2$3"),
// Do not change this string as it gets found and replaced upon packaging
"common.telemetryclientversion": "PACKAGE_JSON_VERSION"
};
}
/**
* Sends the event to the passed in telemetry client
* The appender does no telemetry level checks as those are done by the reporter.
@ -91,14 +63,14 @@ export class BaseTelemetryAppender implements ILazyTelemetryAppender {
* @param exception The exception to collect
* @param data Data associated with the exception
*/
logException(exception: Error, data?: AppenderData): void {
logError(exception: Error, data?: AppenderData): void {
if (!this._telemetryClient) {
if (this._instantiationStatus !== InstantiationStatus.INSTANTIATED) {
this._exceptionQueue.push({ exception, data });
}
return;
}
// No-op TODO @lramos15 remove once removed from API surface
// No-op TODO @lramos15 convert into an unhandled error event
}
/**
@ -118,7 +90,7 @@ export class BaseTelemetryAppender implements ILazyTelemetryAppender {
private _flushQueues(): void {
this._eventQueue.forEach(({ eventName, data }) => this.logEvent(eventName, data));
this._eventQueue = [];
this._exceptionQueue.forEach(({ exception, data }) => this.logException(exception, data));
this._exceptionQueue.forEach(({ exception, data }) => this.logError(exception, data));
this._exceptionQueue = [];
}

Просмотреть файл

@ -36,8 +36,9 @@ export class BaseTelemetryReporter {
constructor(
private telemetryAppender: ILazyTelemetryAppender,
private readonly vscodeAPI: typeof vscode,
initializationOptions?: vscode.TelemetryInitializationOptions
) {
this.telemetryLogger = this.vscodeAPI.env.createTelemetryLogger(this.telemetryAppender);
this.telemetryLogger = this.vscodeAPI.env.createTelemetryLogger(this.telemetryAppender, initializationOptions);
// Keep track of the user's opt-in status
this.updateUserOptIn();
@ -175,7 +176,7 @@ export class BaseTelemetryReporter {
dangerous: boolean
): void {
if (dangerous) {
this.telemetryAppender.logException(error, { properties, measurements });
this.telemetryAppender.logError(error, { properties, measurements });
} else {
this.telemetryLogger.logError(error, { properties, measurements });
}

Просмотреть файл

@ -44,6 +44,30 @@ export class TelemetryUtil {
);
}
// This also includes the common properties which core mixes in
// __GDPR__COMMON__ "common.os" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.nodeArch" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.platformversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.extname" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.extversion" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.vscodemachineid" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.vscodesessionid" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.vscodeversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.uikind" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.remotename" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.isnewappinstall" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.product" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// __GDPR__COMMON__ "common.telemetryclientversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
public static getAdditionalCommonProperties(osShim: { release: string, platform: string, architecture: string }) {
return {
"common.os": osShim.platform,
"common.nodeArch": osShim.architecture,
"common.platformversion": (osShim.release || "").replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, "$1$2$3"),
// Do not change this string as it gets found and replaced upon packaging
"common.telemetryclientversion": "PACKAGE_JSON_VERSION"
};
}
// Get singleton instance of TelemetryUtil
public static getInstance(): TelemetryUtil {
if (!TelemetryUtil._instance) {

Просмотреть файл

@ -73,7 +73,7 @@ const appInsightsClientFactory = async (key: string, replacementOptions?: Replac
flush: async () => {
try {
appInsightsClient?.flush();
} catch(e: any) {
} catch (e: any) {
throw new Error("Failed to flush app insights!\n" + e.message);
}
}
@ -151,14 +151,16 @@ export default class TelemetryReporter extends BaseTelemetryReporter {
clientFactory = (key: string) => oneDataSystemClientFactory(key, vscode, getXHROverride());
}
const appender = new BaseTelemetryAppender(key, clientFactory, {
const osShim = {
release: os.release(),
platform: os.platform(),
architecture: os.arch(),
});
};
const appender = new BaseTelemetryAppender(key, clientFactory,);
if (key && key.indexOf("AIF-") === 0) {
throw new Error("AIF keys are no longer supported. Please switch to 1DS keys for 1st party extensions");
}
super(appender, vscode);
super(appender, vscode, { additionalCommonProperties: TelemetryUtil.getAdditionalCommonProperties(osShim) });
}
}

53
vscode.proposed.telemetryLogger.d.ts поставляемый
Просмотреть файл

@ -5,8 +5,35 @@
declare module 'vscode' {
/**
* A special value wrapper denoting a value that is safe to not clean.
* This is to be used when you can guarantee no identifiable information is contained in the value and the cleaning is improperly redacting it.
*/
export class TrustedTelemetryValue<T = any> {
readonly value: T;
constructor(value: T);
}
export interface TelemetryInitializationOptions {
/**
* Whether or not you want to avoid having the built-in common properties such as os, extension name, etc injected into the data object.
* Defaults to false if not defined.
*/
readonly ignoreBuiltInCommonProperties?: boolean;
/**
* Any additional common properties which should be injected into the data object.
*/
readonly additionalCommonProperties?: Record<string, any>;
/**
* Whether or not unhandled errors on the extension host caused by your extension should be logged to your appender.
* Defaults to false if not defined.
*/
readonly ignoreUnhandledErrors?: boolean;
}
export interface TelemetryLogger {
//TODO feels weird having this on all loggers
readonly onDidChangeEnableStates: Event<TelemetryLogger>;
readonly isUsageEnabled: boolean;
readonly isErrorsEnabled: boolean;
@ -17,7 +44,7 @@ declare module 'vscode' {
* @param eventName The event name to log
* @param data The data to log
*/
logUsage(eventName: string, data?: Record<string, any>): void;
logUsage(eventName: string, data?: Record<string, any | TrustedTelemetryValue>): void;
/**
* After completing cleaning, telemetry setting checks, and data mix-in calls `TelemetryAppender.logEvent` to log the event. Differs from `logUsage` in that it will log the event if the telemetry setting is Error+.
@ -25,31 +52,21 @@ declare module 'vscode' {
* @param eventName The event name to log
* @param data The data to log
*/
logError(eventName: string, data?: Record<string, any>): void;
logError(eventName: string, data?: Record<string, any | TrustedTelemetryValue>): void;
/**
* Calls `TelemetryAppender.logException`. Does cleaning, telemetry checks, and data mix-in.
* Automatically supports echoing to extension telemetry output channel.
* Will also automatically log any exceptions thrown within the extension host process.
* @param exception The error object which contains the stack trace cleaned of PII
* @param error The error object which contains the stack trace cleaned of PII
* @param data Additional data to log alongside the stack trace
*/
logError(exception: Error, data?: Record<string, any>): void;
logError(error: Error, data?: Record<string, any | TrustedTelemetryValue>): void;
dispose(): void;
}
export interface TelemetryAppender {
/**
* Whether or not you want to avoid having the built-in common properties such as os, extension name, etc injected into the data object.
*/
readonly ignoreBuiltInCommonProperties: boolean;
/**
* Any additional common properties which should be injected into the data object.
*/
readonly additionalCommonProperties?: Record<string, string | number | boolean>;
/**
* User-defined function which logs an event, used within the TelemetryLogger
* @param eventName The name of the event which you are logging
@ -59,10 +76,10 @@ declare module 'vscode' {
/**
* User-defined function which logs an error, used within the TelemetryLogger
* @param exception The exception being logged
* @param error The error being logged
* @param data Any additional data to be collected with the exception
*/
logException(exception: Error, data?: Record<string, any>): void;
logError(error: Error, data?: Record<string, any>): void;
/**
* Optional flush function which will give your appender one last chance to send any remaining events as the TelemetryLogger is being disposed
@ -76,6 +93,6 @@ declare module 'vscode' {
* @param appender The core piece which we call when it is time to log telemetry. It is highly recommended that you don't call the methods within the appender directly as the logger provides extra guards and cleaning.
* @returns An instantiated telemetry logger which you can use for recording telemetry
*/
export function createTelemetryLogger(appender: TelemetryAppender): TelemetryLogger;
export function createTelemetryLogger(appender: TelemetryAppender, options?: TelemetryInitializationOptions): TelemetryLogger;
}
}