Skip to content

Commit 28da8ed

Browse files
authored
Add some tests for extension telemetry (microsoft#163584)
* Add some tests for extension telemetry * Fix failing tests * More attempts at fixing failing tests * Ok, I think I fixed the tests this time
1 parent d494522 commit 28da8ed

File tree

4 files changed

+151
-7
lines changed

4 files changed

+151
-7
lines changed

src/vs/platform/telemetry/test/common/telemetryLogAppender.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class TestTelemetryLogger extends AbstractLogger implements ILogger {
5858
flush(): void { }
5959
}
6060

61-
class TestTelemetryLoggerService implements ILoggerService {
61+
export class TestTelemetryLoggerService implements ILoggerService {
6262
_serviceBrand: undefined;
6363

6464
logger?: TestTelemetryLogger;

src/vs/workbench/api/common/extHostTelemetry.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ export class ExtHostTelemetry implements ExtHostTelemetryShape {
3434
@IExtHostInitDataService private readonly initData: IExtHostInitDataService,
3535
@ILoggerService loggerService: ILoggerService,
3636
) {
37-
console.log(this.initData.environment.extensionTelemetryLogResource);
3837
this._outputLogger = loggerService.createLogger(URI.revive(this.initData.environment.extensionTelemetryLogResource));
3938
this._outputLogger.info('Below are logs for extension telemetry events sent to the telemetry output channel API once the log level is set to trace.');
4039
this._outputLogger.info('===========================================================');
@@ -183,16 +182,16 @@ export class ExtHostTelemetryLogger {
183182
if (!this._apiObject) {
184183
const that = this;
185184
const obj: vscode.TelemetryLogger = {
186-
logUsage: that.logUsage,
185+
logUsage: that.logUsage.bind(that),
187186
get isUsageEnabled() {
188187
return that._telemetryEnablements.isUsageEnabled;
189188
},
190189
get isErrorsEnabled() {
191190
return that._telemetryEnablements.isErrorsEnabled;
192191
},
193-
logError: that.logError,
194-
dispose: that.dispose,
195-
onDidChangeEnableStates: that._onDidChangeEnableStates.event
192+
logError: that.logError.bind(that),
193+
dispose: that.dispose.bind(that),
194+
onDidChangeEnableStates: that._onDidChangeEnableStates.event.bind(that)
196195
};
197196
this._apiObject = Object.freeze(obj);
198197
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as assert from 'assert';
7+
import { URI } from 'vs/base/common/uri';
8+
import { ExtensionIdentifier, IExtensionDescription, TargetPlatform } from 'vs/platform/extensions/common/extensions';
9+
import { DEFAULT_LOG_LEVEL } from 'vs/platform/log/common/log';
10+
import { ITelemetryInfo, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
11+
import { TestTelemetryLoggerService } from 'vs/platform/telemetry/test/common/telemetryLogAppender.test';
12+
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
13+
import { ExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
14+
import { IEnvironment } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
15+
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
16+
import type { TelemetryAppender } from 'vscode';
17+
18+
suite('ExtHostTelemetry', function () {
19+
20+
const mockEnvironment: IEnvironment = {
21+
isExtensionDevelopmentDebug: false,
22+
extensionDevelopmentLocationURI: undefined,
23+
extensionTestsLocationURI: undefined,
24+
appRoot: undefined,
25+
appName: 'test',
26+
extensionTelemetryLogResource: URI.parse('fake'),
27+
appHost: 'test',
28+
appLanguage: 'en',
29+
globalStorageHome: URI.parse('fake'),
30+
workspaceStorageHome: URI.parse('fake'),
31+
appUriScheme: 'test',
32+
};
33+
34+
const mockTelemetryInfo: ITelemetryInfo = {
35+
firstSessionDate: '2020-01-01T00:00:00.000Z',
36+
sessionId: 'test',
37+
machineId: 'test',
38+
};
39+
40+
const mockRemote = {
41+
authority: 'test',
42+
isRemote: false,
43+
connectionData: null
44+
};
45+
46+
const mockExtensionIdentifier: IExtensionDescription = {
47+
identifier: new ExtensionIdentifier('test-extension'),
48+
targetPlatform: TargetPlatform.UNIVERSAL,
49+
isBuiltin: true,
50+
isUserBuiltin: true,
51+
isUnderDevelopment: true,
52+
name: 'test-extension',
53+
publisher: 'vscode',
54+
version: '1.0.0',
55+
engines: { vscode: '*' },
56+
extensionLocation: URI.parse('fake')
57+
};
58+
59+
test('Ensure logger gets proper telemetry level during initialization', function () {
60+
const extensionTelemetry = new ExtHostTelemetry(new class extends mock<IExtHostInitDataService>() {
61+
override environment: IEnvironment = mockEnvironment;
62+
override telemetryInfo: ITelemetryInfo = mockTelemetryInfo;
63+
override remote = mockRemote;
64+
}, new TestTelemetryLoggerService(DEFAULT_LOG_LEVEL));
65+
extensionTelemetry.$initializeTelemetryLevel(TelemetryLevel.USAGE, { usage: true, error: true });
66+
let config = extensionTelemetry.getTelemetryDetails();
67+
assert.strictEqual(config.isCrashEnabled, true);
68+
assert.strictEqual(config.isUsageEnabled, true);
69+
assert.strictEqual(config.isErrorsEnabled, true);
70+
71+
// Initialize would never be called twice, but this is just for testing
72+
extensionTelemetry.$initializeTelemetryLevel(TelemetryLevel.ERROR, { usage: true, error: true });
73+
config = extensionTelemetry.getTelemetryDetails();
74+
assert.strictEqual(config.isCrashEnabled, true);
75+
assert.strictEqual(config.isUsageEnabled, false);
76+
assert.strictEqual(config.isErrorsEnabled, true);
77+
78+
extensionTelemetry.$initializeTelemetryLevel(TelemetryLevel.CRASH, { usage: true, error: true });
79+
config = extensionTelemetry.getTelemetryDetails();
80+
assert.strictEqual(config.isCrashEnabled, true);
81+
assert.strictEqual(config.isUsageEnabled, false);
82+
assert.strictEqual(config.isErrorsEnabled, false);
83+
84+
extensionTelemetry.$initializeTelemetryLevel(TelemetryLevel.USAGE, { usage: false, error: true });
85+
config = extensionTelemetry.getTelemetryDetails();
86+
assert.strictEqual(config.isCrashEnabled, true);
87+
assert.strictEqual(config.isUsageEnabled, false);
88+
assert.strictEqual(config.isErrorsEnabled, true);
89+
});
90+
91+
test('Simple log event to TelemetryLogger', function () {
92+
const sentData: any[] = [];
93+
const sentExceptions: any[] = [];
94+
let flushCalled = false;
95+
96+
// This is the appender which the extension would contribute
97+
const appender: TelemetryAppender = {
98+
logEvent: (eventName: string, data) => {
99+
sentData.push({ eventName, data });
100+
},
101+
logException: (exception, data) => {
102+
sentExceptions.push({ exception, data });
103+
},
104+
ignoreBuiltInCommonProperties: false,
105+
flush: () => {
106+
flushCalled = true;
107+
}
108+
};
109+
110+
const extensionTelemetry = new ExtHostTelemetry(new class extends mock<IExtHostInitDataService>() {
111+
override environment: IEnvironment = mockEnvironment;
112+
override telemetryInfo: ITelemetryInfo = mockTelemetryInfo;
113+
override remote = mockRemote;
114+
}, new TestTelemetryLoggerService(DEFAULT_LOG_LEVEL));
115+
116+
extensionTelemetry.$initializeTelemetryLevel(TelemetryLevel.USAGE, { usage: true, error: true });
117+
118+
// Create the logger usting the appender
119+
const logger = extensionTelemetry.instantiateLogger(mockExtensionIdentifier, appender);
120+
121+
logger.logUsage('test-event', { 'test-data': 'test-data' });
122+
assert.strictEqual(sentData.length, 1);
123+
assert.strictEqual(sentData[0].eventName, `${mockExtensionIdentifier.name}/test-event`);
124+
assert.strictEqual(sentData[0].data['test-data'], 'test-data');
125+
126+
logger.logUsage('test-event', { 'test-data': 'test-data' });
127+
assert.strictEqual(sentData.length, 2);
128+
129+
logger.logError('test-event', { 'test-data': 'test-data' });
130+
assert.strictEqual(sentData.length, 3);
131+
132+
logger.logError(new Error('test-error'), { 'test-data': 'test-data' });
133+
assert.strictEqual(sentData.length, 3);
134+
assert.strictEqual(sentExceptions.length, 1);
135+
136+
137+
// Assert not flushed
138+
assert.strictEqual(flushCalled, false);
139+
140+
// Call flush and assert that flush occurs
141+
logger.dispose();
142+
assert.strictEqual(flushCalled, true);
143+
144+
});
145+
});

src/vscode-dts/vscode.proposed.telemetryLogger.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ declare module 'vscode' {
4848
/**
4949
* Any additional common properties which should be injected into the data object.
5050
*/
51-
readonly additionalCommonProperties: Record<string, string | number | boolean>;
51+
readonly additionalCommonProperties?: Record<string, string | number | boolean>;
5252

5353
/**
5454
* User-defined function which logs an event, used within the TelemetryLogger

0 commit comments

Comments
 (0)