Skip to content
This repository was archived by the owner on Sep 17, 2021. It is now read-only.

Commit bc5358c

Browse files
committed
Fixing telemetry so that users show in dashboard
1 parent f5c6cbd commit bc5358c

File tree

4 files changed

+148
-4
lines changed

4 files changed

+148
-4
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,15 @@
117117
"postinstall": "node ./node_modules/vscode/bin/install"
118118
},
119119
"dependencies": {
120+
"applicationinsights": "^1.0.6",
120121
"chrome-devtools-frontend": "^1.0.602557",
121122
"vscode": "^1.1.18",
122-
"vscode-extension-telemetry": "^0.1.0",
123123
"ws": "^6.1.0"
124124
},
125125
"devDependencies": {
126126
"@types/node": "^10.5.2",
127-
"@types/shelljs": "^0.8.0",
127+
"@types/shelljs": "^0.8.0",
128+
"@types/ws": "^6.0.1",
128129
"shelljs": "^0.8.2",
129130
"ts-node": "^7.0.1",
130131
"tslint": "^5.11.0",

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as path from 'path';
22
import * as vscode from 'vscode';
3-
import TelemetryReporter from 'vscode-extension-telemetry';
43
import WebSocket from 'ws';
4+
import TelemetryReporter from './telemetry';
55
import QuickPickItem = vscode.QuickPickItem;
66
import * as utils from './utils';
77

src/telemetry.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*---------------------------------------------------------
2+
* Copyright (C) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------*/
4+
// Edited to fix the user id reporting
5+
6+
'use strict';
7+
8+
process.env['APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL'] = 'true';
9+
10+
import * as appInsights from 'applicationinsights';
11+
import * as fs from 'fs';
12+
import * as os from 'os';
13+
import * as path from 'path';
14+
import * as vscode from 'vscode';
15+
16+
export default class TelemetryReporter extends vscode.Disposable {
17+
private appInsightsClient: appInsights.TelemetryClient | undefined;
18+
private userOptIn: boolean = false;
19+
private toDispose: vscode.Disposable[] = [];
20+
21+
private static TELEMETRY_CONFIG_ID = 'telemetry';
22+
private static TELEMETRY_CONFIG_ENABLED_ID = 'enableTelemetry';
23+
24+
private logStream: fs.WriteStream | undefined;
25+
26+
constructor(private extensionId: string, private extensionVersion: string, key: string) {
27+
super(() => this.toDispose.forEach((d) => d && d.dispose()));
28+
let logFilePath = process.env['VSCODE_LOGS'] || '';
29+
if (logFilePath && extensionId && process.env['VSCODE_LOG_LEVEL'] === 'trace') {
30+
logFilePath = path.join(logFilePath, `${extensionId}.txt`);
31+
this.logStream = fs.createWriteStream(logFilePath, { flags: 'a', encoding: 'utf8', autoClose: true });
32+
}
33+
this.updateUserOptIn(key);
34+
this.toDispose.push(vscode.workspace.onDidChangeConfiguration(() => this.updateUserOptIn(key)));
35+
}
36+
37+
private updateUserOptIn(key: string): void {
38+
const config = vscode.workspace.getConfiguration(TelemetryReporter.TELEMETRY_CONFIG_ID);
39+
if (this.userOptIn !== config.get<boolean>(TelemetryReporter.TELEMETRY_CONFIG_ENABLED_ID, true)) {
40+
this.userOptIn = config.get<boolean>(TelemetryReporter.TELEMETRY_CONFIG_ENABLED_ID, true);
41+
if (this.userOptIn) {
42+
this.createAppInsightsClient(key);
43+
} else {
44+
this.dispose();
45+
}
46+
}
47+
}
48+
49+
private createAppInsightsClient(key: string) {
50+
// Check if another instance is already initialized
51+
if (appInsights.defaultClient) {
52+
this.appInsightsClient = new appInsights.TelemetryClient(key);
53+
// No other way to enable offline mode
54+
this.appInsightsClient.channel.setUseDiskRetryCaching(true);
55+
} else {
56+
appInsights.setup(key)
57+
.setAutoCollectRequests(false)
58+
.setAutoCollectPerformance(false)
59+
.setAutoCollectExceptions(false)
60+
.setAutoCollectDependencies(false)
61+
.setAutoDependencyCorrelation(false)
62+
.setAutoCollectConsole(false)
63+
.setUseDiskRetryCaching(true)
64+
.start();
65+
this.appInsightsClient = appInsights.defaultClient;
66+
}
67+
68+
this.appInsightsClient.commonProperties = this.getCommonProperties();
69+
70+
// Add the user and session id's to the context so that the analytics will correctly assign users
71+
if (vscode && vscode.env) {
72+
this.appInsightsClient.context.tags[this.appInsightsClient.context.keys.userId] = vscode.env.machineId;
73+
this.appInsightsClient.context.tags[this.appInsightsClient.context.keys.sessionId] = vscode.env.sessionId;
74+
}
75+
76+
// Check if it's an Asimov key to change the endpoint
77+
if (key && key.indexOf('AIF-') === 0) {
78+
this.appInsightsClient.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
79+
}
80+
}
81+
82+
// __GDPR__COMMON__ "common.os" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
83+
// __GDPR__COMMON__ "common.platformversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
84+
// __GDPR__COMMON__ "common.extname" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
85+
// __GDPR__COMMON__ "common.extversion" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
86+
// __GDPR__COMMON__ "common.vscodemachineid" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
87+
// __GDPR__COMMON__ "common.vscodesessionid" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
88+
// __GDPR__COMMON__ "common.vscodeversion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
89+
private getCommonProperties(): { [key: string]: string } {
90+
// tslint:disable-next-line:no-null-keyword
91+
const commonProperties = Object.create(null);
92+
commonProperties['common.os'] = os.platform();
93+
commonProperties['common.platformversion'] = (os.release() || '').replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, '$1$2$3');
94+
commonProperties['common.extname'] = this.extensionId;
95+
commonProperties['common.extversion'] = this.extensionVersion;
96+
if (vscode && vscode.env) {
97+
commonProperties['common.vscodemachineid'] = vscode.env.machineId;
98+
commonProperties['common.vscodesessionid'] = vscode.env.sessionId;
99+
commonProperties['common.vscodeversion'] = vscode.version;
100+
}
101+
return commonProperties;
102+
}
103+
104+
public sendTelemetryEvent(eventName: string, properties?: { [key: string]: string }, measurements?: { [key: string]: number }): void {
105+
if (this.userOptIn && eventName && this.appInsightsClient) {
106+
this.appInsightsClient.trackEvent({
107+
name: `${this.extensionId}/${eventName}`,
108+
properties: properties,
109+
measurements: measurements
110+
});
111+
112+
if (this.logStream) {
113+
this.logStream.write(`telemetry/${eventName} ${JSON.stringify({ properties, measurements })}\n`);
114+
}
115+
}
116+
}
117+
118+
public dispose(): Promise<any> {
119+
const flushEventsToLogger = new Promise<any>(resolve => {
120+
if (!this.logStream) {
121+
return resolve(void 0);
122+
}
123+
this.logStream.on('finish', resolve);
124+
this.logStream.end();
125+
});
126+
127+
const flushEventsToAI = new Promise<any>(resolve => {
128+
if (this.appInsightsClient) {
129+
this.appInsightsClient.flush({
130+
callback: () => {
131+
// All data flushed
132+
this.appInsightsClient = undefined;
133+
resolve(void 0);
134+
}
135+
});
136+
} else {
137+
resolve(void 0);
138+
}
139+
});
140+
return Promise.all([flushEventsToAI, flushEventsToLogger]);
141+
}
142+
}

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"node_modules/*",
1414
"src/types/*"
1515
]
16-
}
16+
},
17+
"skipLibCheck": true
1718
},
1819
"include": [
1920
"src/**/*"

0 commit comments

Comments
 (0)