Skip to content

Commit

Permalink
Merge pull request #188 from microsoft/lramos15/old-parrotfish
Browse files Browse the repository at this point in the history
Use web basic SDK for both node + web to reduce bundle size
  • Loading branch information
lramos15 committed Nov 1, 2023
2 parents d02e6c5 + 894a9af commit 690c5c8
Show file tree
Hide file tree
Showing 8 changed files with 309 additions and 2,995 deletions.
3,039 changes: 215 additions & 2,824 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 13 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vscode/extension-telemetry",
"description": "A module for Visual Studio Code extensions to report consistent telemetry.",
"version": "0.8.5",
"version": "0.9.0",
"author": {
"name": "Microsoft Corporation"
},
Expand All @@ -20,23 +20,22 @@
"compile": "tsc -p 'src/browser/tsconfig.json' && tsc -p 'src/node/tsconfig.json'"
},
"dependencies": {
"@microsoft/1ds-core-js": "^3.2.13",
"@microsoft/1ds-post-js": "^3.2.13",
"@microsoft/applicationinsights-web-basic": "^3.0.2",
"applicationinsights": "^2.7.1"
"@microsoft/1ds-core-js": "^4.0.3",
"@microsoft/1ds-post-js": "^4.0.3",
"@microsoft/applicationinsights-web-basic": "^3.0.4"
},
"devDependencies": {
"@types/mocha": "^10.0.1",
"@types/node": "^20.4.9",
"@types/sinon": "^10.0.16",
"@types/mocha": "^10.0.3",
"@types/node": "^20.8.9",
"@types/sinon": "^10.0.20",
"@types/vscode": "^1.75.0",
"@typescript-eslint/eslint-plugin": "^6.3.0",
"@typescript-eslint/parser": "^6.3.0",
"eslint": "^8.46.0",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"eslint": "^8.52.0",
"mocha": "^10.2.0",
"sinon": "^15.2.0",
"typescript": "^5.1.6",
"user-agent-data-types": "^0.3.1"
"sinon": "^17.0.0",
"typescript": "^5.2.2",
"user-agent-data-types": "^0.4.2"
},
"repository": {
"type": "git",
Expand Down
55 changes: 4 additions & 51 deletions src/browser/telemetryReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,12 @@
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import type { ApplicationInsights } from "@microsoft/applicationinsights-web-basic";
import * as vscode from "vscode";
import { oneDataSystemClientFactory } from "../common/1dsClientFactory";
import { BaseTelemetrySender, BaseTelemetryClient } from "../common/baseTelemetrySender";
import { SenderData, BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetryReporter";
import { BaseTelemetrySender } from "../common/baseTelemetrySender";
import { BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetryReporter";
import { TelemetryUtil } from "../common/util";

const webAppInsightsClientFactory = async (key: string, replacementOptions?: ReplacementOption[]): Promise<BaseTelemetryClient> => {
let appInsightsClient: ApplicationInsights | undefined;
try {
const web = await import/* webpackMode: "eager" */ ("@microsoft/applicationinsights-web-basic");
appInsightsClient = new web.ApplicationInsights({
instrumentationKey: key,
disableAjaxTracking: true,
disableExceptionTracking: true,
disableFetchTracking: true,
disableCorrelationHeaders: true,
disableCookiesUsage: true,
autoTrackPageVisitTime: false,
emitLineDelimitedJson: false,
disableInstrumentationKeyValidation: true
},
);
} catch (e) {
return Promise.reject(e);
}
// Sets the appinsights client into a standardized form
const telemetryClient: BaseTelemetryClient = {
logEvent: (eventName: string, data?: SenderData) => {
const properties = { ...data?.properties, ...data?.measurements };
if (replacementOptions?.length) {
TelemetryUtil.applyReplacements(properties, replacementOptions);
}
appInsightsClient?.track(
{ name: eventName, data: properties },
);
},
flush: async () => {
appInsightsClient?.flush(false);
},
dispose: async () => {
const unloadPromise = new Promise<void>((resolve) => {
appInsightsClient?.unload(true, () => {
resolve();
appInsightsClient = undefined;
}, 1000);
}
);
return unloadPromise;
}
};
return telemetryClient;
};
import { appInsightsClientFactory } from "../common/appInsightsClientFactory";

function getBrowserRelease(navigator: Navigator): string {
if (navigator.userAgentData) {
Expand All @@ -67,7 +20,7 @@ function getBrowserRelease(navigator: Navigator): string {

export default class TelemetryReporter extends BaseTelemetryReporter {
constructor(key: string, replacementOptions?: ReplacementOption[]) {
let clientFactory = (key: string) => webAppInsightsClientFactory(key, replacementOptions);
let clientFactory = (key: string) => appInsightsClientFactory(key, undefined, replacementOptions);
// If key is usable by 1DS use the 1DS SDk
if (TelemetryUtil.shouldUseOneDataSystemSDK(key)) {
clientFactory = (key: string) => oneDataSystemClientFactory(key, vscode);
Expand Down
1 change: 0 additions & 1 deletion src/browser/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"module": "ES2020",
"moduleResolution": "node",
"outDir": "../../dist/browser",
"typeRoots": []
},
"include": [".", "../common", "../../node_modules/user-agent-data-types"]
}
72 changes: 72 additions & 0 deletions src/common/appInsightsClientFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import type { ApplicationInsights } from "@microsoft/applicationinsights-web-basic";
import type { IXHROverride } from "@microsoft/applicationinsights-core-js";
import { BreezeChannelIdentifier } from "@microsoft/applicationinsights-common";
import { ReplacementOption, SenderData } from "./baseTelemetryReporter";
import { BaseTelemetryClient } from "./baseTelemetrySender";
import { TelemetryUtil } from "./util";
import type { IChannelConfiguration } from "@microsoft/1ds-post-js";

export const appInsightsClientFactory = async (key: string, xhrOverride?: IXHROverride, replacementOptions?: ReplacementOption[]): Promise<BaseTelemetryClient> => {
let appInsightsClient: ApplicationInsights | undefined;
try {
const basicAISDK = await import/* webpackMode: "eager" */("@microsoft/applicationinsights-web-basic");
appInsightsClient = new basicAISDK.ApplicationInsights({
instrumentationKey: key,
disableAjaxTracking: true,
disableExceptionTracking: true,
disableFetchTracking: true,
disableCorrelationHeaders: true,
disableCookiesUsage: true,
autoTrackPageVisitTime: false,
emitLineDelimitedJson: false,
disableInstrumentationKeyValidation: true
},
);

if (xhrOverride) {
appInsightsClient.config.extensionConfig = {};
// Configure the channel to use a XHR Request override since it's not available in node
const channelConfig: IChannelConfiguration = {
alwaysUseXhrOverride: true,
httpXHROverride: xhrOverride
};
appInsightsClient.config.extensionConfig[BreezeChannelIdentifier] = channelConfig;
}
} catch (e) {
return Promise.reject(e);
}
// Sets the appinsights client into a standardized form
const telemetryClient: BaseTelemetryClient = {
logEvent: (eventName: string, data?: SenderData) => {
const properties = { ...data?.properties, ...data?.measurements };
if (replacementOptions?.length) {
TelemetryUtil.applyReplacements(properties, replacementOptions);
}
appInsightsClient?.track({
name: eventName,
data: properties,
baseType: "EventData",
baseData: { name: eventName, properties: data?.properties, measurements: data?.measurements }
});
},
flush: async () => {
appInsightsClient?.flush(false);
},
dispose: async () => {
const unloadPromise = new Promise<void>((resolve) => {
appInsightsClient?.unload(true, () => {
resolve();
appInsightsClient = undefined;
}, 1000);
}
);
return unloadPromise;
}
};
return telemetryClient;
};
2 changes: 1 addition & 1 deletion src/common/baseTelemetryReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class BaseTelemetryReporter {
const propertyValue = modifiedProperties[propertyKey];
if (typeof propertyKey === "string" && propertyValue !== undefined) {
// Trusted values are not sanitized, which is what we want for raw telemetry
modifiedProperties[propertyKey] = new this.vscodeAPI.TelemetryTrustedValue<string>(typeof propertyValue === 'string' ? propertyValue : propertyValue.value);
modifiedProperties[propertyKey] = new this.vscodeAPI.TelemetryTrustedValue<string>(typeof propertyValue === "string" ? propertyValue : propertyValue.value);
}
}

Expand Down
107 changes: 4 additions & 103 deletions src/node/telemetryReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,111 +5,12 @@
import * as os from "os";
import * as vscode from "vscode";
import * as https from "https";
import { type TelemetryClient } from "applicationinsights";
import { SenderData, BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetryReporter";
import { BaseTelemetrySender, BaseTelemetryClient } from "../common/baseTelemetrySender";
import { BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetryReporter";
import { BaseTelemetrySender } from "../common/baseTelemetrySender";
import { TelemetryUtil } from "../common/util";
import type { IXHROverride, IPayloadData } from "@microsoft/1ds-post-js";
import { oneDataSystemClientFactory } from "../common/1dsClientFactory";
/**
* A factory function which creates a telemetry client to be used by an sender to send telemetry in a node application.
*
* @param key The app insights key
* @param replacementOptions Optional list of {@link ReplacementOption replacements} to apply to the telemetry client. This allows
* the sender to filter out any sensitive or unnecessary information from the telemetry server.
*
* @returns A promise which resolves to the telemetry client or rejects upon error
*/
const appInsightsClientFactory = async (key: string, replacementOptions?: ReplacementOption[]): Promise<BaseTelemetryClient> => {
let appInsightsClient: TelemetryClient | undefined;
try {
process.env["APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL"] = "1";
const appInsights = await import(/* webpackMode: "eager" */ "applicationinsights");
//check if another instance is already initialized
if (appInsights.defaultClient) {
appInsightsClient = new appInsights.TelemetryClient(key);
// no other way to enable offline mode
appInsightsClient.channel.setUseDiskRetryCaching(true);
} else {
appInsights.setup(key)
.setAutoCollectRequests(false)
.setAutoCollectPerformance(false)
.setAutoCollectExceptions(false)
.setAutoCollectDependencies(false)
.setAutoDependencyCorrelation(false)
.setAutoCollectConsole(false)
.setAutoCollectHeartbeat(false)
.setAutoCollectIncomingRequestAzureFunctions(false)
.setUseDiskRetryCaching(true)
.start();
appInsightsClient = appInsights.defaultClient;
}
if (vscode && vscode.env) {
appInsightsClient.context.tags[appInsightsClient.context.keys.userId] = vscode.env.machineId;
appInsightsClient.context.tags[appInsightsClient.context.keys.sessionId] = vscode.env.sessionId;
appInsightsClient.context.tags[appInsightsClient.context.keys.cloudRole] = vscode.env.appName;
appInsightsClient.context.tags[appInsightsClient.context.keys.cloudRoleInstance] = vscode.env.appName;
}
} catch (e: any) {
return Promise.reject("Failed to initialize app insights!\n" + e.message);
}

if (replacementOptions?.length) {
addReplacementOptions(appInsightsClient, replacementOptions);
}

// Sets the appinsights client into a standardized form
const telemetryClient: BaseTelemetryClient = {
logEvent: (eventName: string, data?: SenderData) => {
try {
appInsightsClient?.trackEvent({
name: eventName,
properties: data?.properties,
measurements: data?.measurements
});
} catch (e: any) {
throw new Error("Failed to log event to app insights!\n" + e.message);
}
},
flush: async () => {
try {
appInsightsClient?.flush();
} catch (e: any) {
throw new Error("Failed to flush app insights!\n" + e.message);
}
},
dispose: async () => {
appInsightsClient?.flush({ isAppCrashing: true });
appInsightsClient = undefined;
}
};
return telemetryClient;
};

/**
* Adds replacement options to this {@link TelemetryClient}.
*
* If any replacement options are specified, this function will search through any event about to be
* sent to the telemetry server and replace any matches with the specified replacement string. Both
* the envelope and the base data will be searched.
*
* @param appInsightsClient The {@link TelemetryClient} to add the filters to.
* @param replacementOptions The replacement options to add.
*/
function addReplacementOptions(appInsightsClient: TelemetryClient, replacementOptions: ReplacementOption[]) {
appInsightsClient.addTelemetryProcessor((event) => {
if (Array.isArray(event.tags)) {
event.tags.forEach(tag => TelemetryUtil.applyReplacements(tag, replacementOptions));
} else if (event.tags) {
TelemetryUtil.applyReplacements(event.tags, replacementOptions);
}

if (event.data.baseData) {
TelemetryUtil.applyReplacements(event.data.baseData, replacementOptions);
}
return true;
});
}
import { appInsightsClientFactory } from "../common/appInsightsClientFactory";

/**
* Create a replacement for the XHTMLRequest object utilizing nodes HTTP module.
Expand Down Expand Up @@ -154,7 +55,7 @@ function getXHROverride() {

export default class TelemetryReporter extends BaseTelemetryReporter {
constructor(key: string, replacementOptions?: ReplacementOption[]) {
let clientFactory = (key: string) => appInsightsClientFactory(key, replacementOptions);
let clientFactory = (key: string) => appInsightsClientFactory(key, getXHROverride(), replacementOptions);
// If key is usable by 1DS use the 1DS SDk
if (TelemetryUtil.shouldUseOneDataSystemSDK(key)) {
clientFactory = (key: string) => oneDataSystemClientFactory(key, vscode, getXHROverride());
Expand Down
1 change: 0 additions & 1 deletion src/node/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"module": "CommonJS",
"moduleResolution": "node",
"outDir": "../../dist/node",
"typeRoots": []
},
"include": [".", "../common", "../../vscode.proposed.telemetryLogger.d.ts"]
}

0 comments on commit 690c5c8

Please sign in to comment.