mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 (#14050)
* Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 * Fix breaks * Extension management fixes * Fix breaks in windows bundling * Fix/skip failing tests * Update distro * Add clear to nuget.config * Add hygiene task * Bump distro * Fix hygiene issue * Add build to hygiene exclusion * Update distro * Update hygiene * Hygiene exclusions * Update tsconfig * Bump distro for server breaks * Update build config * Update darwin path * Add done calls to notebook tests * Skip failing tests * Disable smoke tests
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
import { toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { globals } from 'vs/base/common/platform';
|
||||
import BaseErrorTelemetry, { ErrorEvent } from '../common/errorTelemetry';
|
||||
import BaseErrorTelemetry, { ErrorEvent } from 'vs/platform/telemetry/common/errorTelemetry';
|
||||
|
||||
export default class ErrorTelemetry extends BaseErrorTelemetry {
|
||||
protected installErrorListeners(): void {
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import * as Platform from 'vs/base/common/platform';
|
||||
import * as uuid from 'vs/base/common/uuid';
|
||||
import { cleanRemoteAuthority } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { firstSessionDateStorageKey, lastSessionDateStorageKey, machineIdKey } from 'vs/platform/telemetry/common/telemetry';
|
||||
import product from 'vs/platform/product/common/product'; // {{SQL CARBON EDIT}}
|
||||
|
||||
export async function resolveWorkbenchCommonProperties(
|
||||
storageService: IStorageService,
|
||||
commit: string | undefined,
|
||||
version: string | undefined,
|
||||
remoteAuthority?: string,
|
||||
resolveAdditionalProperties?: () => { [key: string]: any }
|
||||
): Promise<{ [name: string]: string | undefined }> {
|
||||
const result: { [name: string]: string | undefined; } = Object.create(null);
|
||||
const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
|
||||
let machineId = storageService.get(machineIdKey, StorageScope.GLOBAL);
|
||||
if (!machineId) {
|
||||
machineId = uuid.generateUuid();
|
||||
storageService.store(machineIdKey, machineId, StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: In the web, session date information is fetched from browser storage, so these dates are tied to a specific
|
||||
* browser and not the machine overall.
|
||||
*/
|
||||
// __GDPR__COMMON__ "common.firstSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.firstSessionDate'] = firstSessionDate;
|
||||
// __GDPR__COMMON__ "common.lastSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.lastSessionDate'] = lastSessionDate || '';
|
||||
// __GDPR__COMMON__ "common.isNewSession" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.isNewSession'] = !lastSessionDate ? '1' : '0';
|
||||
// __GDPR__COMMON__ "common.remoteAuthority" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.remoteAuthority'] = cleanRemoteAuthority(remoteAuthority);
|
||||
|
||||
// __GDPR__COMMON__ "common.machineId" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
|
||||
result['common.machineId'] = machineId;
|
||||
// __GDPR__COMMON__ "sessionID" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['sessionID'] = uuid.generateUuid() + Date.now();
|
||||
// __GDPR__COMMON__ "commitHash" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['commitHash'] = commit;
|
||||
// __GDPR__COMMON__ "version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['version'] = version;
|
||||
// __GDPR__COMMON__ "common.platform" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.platform'] = Platform.PlatformToString(Platform.platform);
|
||||
// __GDPR__COMMON__ "common.product" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.product'] = 'web';
|
||||
// __GDPR__COMMON__ "common.userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.userAgent'] = Platform.userAgent;
|
||||
result['quality'] = product.quality || 'dev'; // {{SQL CARBON EDIT}} Add quality
|
||||
|
||||
// dynamic properties which value differs on each call
|
||||
let seq = 0;
|
||||
const startTime = Date.now();
|
||||
Object.defineProperties(result, {
|
||||
// __GDPR__COMMON__ "timestamp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
'timestamp': {
|
||||
get: () => new Date(),
|
||||
enumerable: true
|
||||
},
|
||||
// __GDPR__COMMON__ "common.timesincesessionstart" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
|
||||
'common.timesincesessionstart': {
|
||||
get: () => Date.now() - startTime,
|
||||
enumerable: true
|
||||
},
|
||||
// __GDPR__COMMON__ "common.sequence" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
|
||||
'common.sequence': {
|
||||
get: () => seq++,
|
||||
enumerable: true
|
||||
}
|
||||
});
|
||||
|
||||
if (resolveAdditionalProperties) {
|
||||
mixin(result, resolveAdditionalProperties());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
33
src/vs/platform/telemetry/common/telemetryLogAppender.ts
Normal file
33
src/vs/platform/telemetry/common/telemetryLogAppender.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ILogger, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
export class TelemetryLogAppender extends Disposable implements ITelemetryAppender {
|
||||
|
||||
private readonly logger: ILogger;
|
||||
|
||||
constructor(
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService
|
||||
) {
|
||||
super();
|
||||
this.logger = this._register(loggerService.getLogger(environmentService.telemetryLogResource));
|
||||
this.logger.info('The below are logs for every telemetry event sent from VS Code once the log level is set to trace.');
|
||||
this.logger.info('===========================================================');
|
||||
}
|
||||
|
||||
flush(): Promise<any> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
log(eventName: string, data: any): void {
|
||||
this.logger.trace(`telemetry/${eventName}`, validateTelemetryData(data));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { localize } from 'vs/nls';
|
||||
import { escapeRegExpCharacters } from 'vs/base/common/strings';
|
||||
import { ITelemetryService, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -207,6 +208,7 @@ export class TelemetryService implements ITelemetryService {
|
||||
|
||||
const TELEMETRY_SECTION_ID = 'telemetry';
|
||||
|
||||
|
||||
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
|
||||
'id': TELEMETRY_SECTION_ID,
|
||||
'order': 110,
|
||||
@@ -215,7 +217,10 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfigurat
|
||||
'properties': {
|
||||
'telemetry.enableTelemetry': {
|
||||
'type': 'boolean',
|
||||
'description': localize('telemetry.enableTelemetry', "Enable usage data and errors to be sent to a Microsoft online service."),
|
||||
'markdownDescription':
|
||||
!product.privacyStatementUrl ?
|
||||
localize('telemetry.enableTelemetry', "Enable usage data and errors to be sent to a Microsoft online service.") :
|
||||
localize('telemetry.enableTelemetryMd', "Enable usage data and errors to be sent to a Microsoft online service. Read our privacy statement [here]({0}).", product.privacyStatementUrl),
|
||||
'default': true,
|
||||
'tags': ['usesOnlineServices']
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationService, ConfigurationTarget, ConfigurationTargetToString } from 'vs/platform/configuration/common/configuration';
|
||||
import { ITelemetryService, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { safeStringify } from 'vs/base/common/objects';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
@@ -55,26 +54,6 @@ export function combinedAppender(...appenders: ITelemetryAppender[]): ITelemetry
|
||||
export const NullAppender: ITelemetryAppender = { log: () => null, flush: () => Promise.resolve(null) };
|
||||
|
||||
|
||||
export class LogAppender implements ITelemetryAppender {
|
||||
|
||||
private commonPropertiesRegex = /^sessionID$|^version$|^timestamp$|^commitHash$|^common\./;
|
||||
constructor(@ILogService private readonly _logService: ILogService) { }
|
||||
|
||||
flush(): Promise<any> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
log(eventName: string, data: any): void {
|
||||
const strippedData: { [key: string]: any } = {};
|
||||
Object.keys(data).forEach(key => {
|
||||
if (!this.commonPropertiesRegex.test(key)) {
|
||||
strippedData[key] = data[key];
|
||||
}
|
||||
});
|
||||
this._logService.trace(`telemetry/${eventName}`, strippedData);
|
||||
}
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"URIDescriptor" : {
|
||||
"mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as appInsights from 'applicationinsights';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
function getClient(aiKey: string): appInsights.TelemetryClient {
|
||||
|
||||
async function getClient(aiKey: string): Promise<appInsights.TelemetryClient> {
|
||||
const appInsights = await import('applicationinsights');
|
||||
let client: appInsights.TelemetryClient;
|
||||
if (appInsights.defaultClient) {
|
||||
client = new appInsights.TelemetryClient(aiKey);
|
||||
@@ -37,23 +37,49 @@ function getClient(aiKey: string): appInsights.TelemetryClient {
|
||||
|
||||
export class AppInsightsAppender implements ITelemetryAppender {
|
||||
|
||||
private _aiClient?: appInsights.TelemetryClient;
|
||||
private _aiClient: string | appInsights.TelemetryClient | undefined;
|
||||
private _asyncAIClient: Promise<appInsights.TelemetryClient> | null;
|
||||
|
||||
constructor(
|
||||
private _eventPrefix: string,
|
||||
private _defaultData: { [key: string]: any } | null,
|
||||
aiKeyOrClientFactory: string | (() => appInsights.TelemetryClient), // allow factory function for testing
|
||||
@ILogService private _logService?: ILogService
|
||||
) {
|
||||
if (!this._defaultData) {
|
||||
this._defaultData = Object.create(null);
|
||||
}
|
||||
|
||||
if (typeof aiKeyOrClientFactory === 'string') {
|
||||
this._aiClient = getClient(aiKeyOrClientFactory);
|
||||
} else if (typeof aiKeyOrClientFactory === 'function') {
|
||||
if (typeof aiKeyOrClientFactory === 'function') {
|
||||
this._aiClient = aiKeyOrClientFactory();
|
||||
} else {
|
||||
this._aiClient = aiKeyOrClientFactory;
|
||||
}
|
||||
this._asyncAIClient = null;
|
||||
}
|
||||
|
||||
private _withAIClient(callback: (aiClient: appInsights.TelemetryClient) => void): void {
|
||||
if (!this._aiClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this._aiClient !== 'string') {
|
||||
callback(this._aiClient);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._asyncAIClient) {
|
||||
this._asyncAIClient = getClient(this._aiClient);
|
||||
}
|
||||
|
||||
this._asyncAIClient.then(
|
||||
(aiClient) => {
|
||||
callback(aiClient);
|
||||
},
|
||||
(err) => {
|
||||
onUnexpectedError(err);
|
||||
console.error(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
log(eventName: string, data?: any): void {
|
||||
@@ -63,25 +89,24 @@ export class AppInsightsAppender implements ITelemetryAppender {
|
||||
data = mixin(data, this._defaultData);
|
||||
data = validateTelemetryData(data);
|
||||
|
||||
if (this._logService) {
|
||||
this._logService.trace(`telemetry/${eventName}`, data);
|
||||
}
|
||||
this._aiClient.trackEvent({
|
||||
this._withAIClient((aiClient) => aiClient.trackEvent({
|
||||
name: this._eventPrefix + '/' + eventName,
|
||||
properties: data.properties,
|
||||
measurements: data.measurements
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
flush(): Promise<any> {
|
||||
if (this._aiClient) {
|
||||
return new Promise(resolve => {
|
||||
this._aiClient!.flush({
|
||||
callback: () => {
|
||||
// all data flushed
|
||||
this._aiClient = undefined;
|
||||
resolve(undefined);
|
||||
}
|
||||
this._withAIClient((aiClient) => {
|
||||
aiClient.flush({
|
||||
callback: () => {
|
||||
// all data flushed
|
||||
this._aiClient = undefined;
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
|
||||
import BaseErrorTelemetry from '../common/errorTelemetry';
|
||||
import BaseErrorTelemetry from 'vs/platform/telemetry/common/errorTelemetry';
|
||||
|
||||
export default class ErrorTelemetry extends BaseErrorTelemetry {
|
||||
protected installErrorListeners(): void {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import { readdirSync } from 'vs/base/node/pfs';
|
||||
import { statSync, readFileSync } from 'fs';
|
||||
import { join } from 'vs/base/common/path';
|
||||
@@ -43,4 +42,4 @@ export function buildTelemetryMessage(appRoot: string, extensionsPath?: string):
|
||||
contents = readFileSync(join(appRoot, 'telemetry-extensions.json')).toString();
|
||||
mergeTelemetry(contents, 'vscode-extensions');
|
||||
return JSON.stringify(mergedTelemetry, null, 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
|
||||
import { instanceStorageKey, firstSessionDateStorageKey, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { cleanRemoteAuthority } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
import product from 'vs/platform/product/common/product'; // {{ SQL CARBON EDIT }}
|
||||
|
||||
export async function resolveWorkbenchCommonProperties(
|
||||
storageService: IStorageService,
|
||||
commit: string | undefined,
|
||||
version: string | undefined,
|
||||
machineId: string,
|
||||
msftInternalDomains: string[] | undefined,
|
||||
installSourcePath: string,
|
||||
remoteAuthority?: string
|
||||
): Promise<{ [name: string]: string | boolean | undefined }> {
|
||||
const result = await resolveCommonProperties(commit, version, machineId, msftInternalDomains, installSourcePath, undefined);
|
||||
const instanceId = storageService.get(instanceStorageKey, StorageScope.GLOBAL)!;
|
||||
const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
|
||||
// __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.version.shell'] = process.versions && process.versions['electron'];
|
||||
// __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.version.renderer'] = process.versions && process.versions['chrome'];
|
||||
// __GDPR__COMMON__ "common.firstSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.firstSessionDate'] = firstSessionDate;
|
||||
// __GDPR__COMMON__ "common.lastSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.lastSessionDate'] = lastSessionDate || '';
|
||||
// __GDPR__COMMON__ "common.isNewSession" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.isNewSession'] = !lastSessionDate ? '1' : '0';
|
||||
// __GDPR__COMMON__ "common.instanceId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.instanceId'] = instanceId;
|
||||
// __GDPR__COMMON__ "common.remoteAuthority" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.remoteAuthority'] = cleanRemoteAuthority(remoteAuthority);
|
||||
|
||||
result['common.application.name'] = product.nameLong; // {{SQL CARBON EDIT}}
|
||||
setUsageDates(storageService);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
function setUsageDates(storageService: IStorageService): void {
|
||||
// daily last usage date
|
||||
const appStartDate = new Date('January 1, 2000');
|
||||
const dailyLastUseDate = storageService.get('telemetry.dailyLastUseDate', StorageScope.GLOBAL, appStartDate.toUTCString());
|
||||
storageService.store('telemetry.dailyLastUseDate', dailyLastUseDate, StorageScope.GLOBAL);
|
||||
|
||||
// weekly last usage date
|
||||
const weeklyLastUseDate = storageService.get('telemetry.weeklyLastUseDate', StorageScope.GLOBAL, appStartDate.toUTCString());
|
||||
storageService.store('telemetry.weeklyLastUseDate', weeklyLastUseDate, StorageScope.GLOBAL);
|
||||
|
||||
// monthly last usage date
|
||||
const monthlyLastUseDate = storageService.get('telemetry.monthlyLastUseDate', StorageScope.GLOBAL, appStartDate.toUTCString());
|
||||
storageService.store('telemetry.monthlyLastUseDate', monthlyLastUseDate, StorageScope.GLOBAL);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/browser/workbenchCommonProperties';
|
||||
import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/common/storage';
|
||||
|
||||
suite('Browser Telemetry - common properties', function () {
|
||||
|
||||
const commit: string = (undefined)!;
|
||||
const version: string = (undefined)!;
|
||||
let testStorageService: IStorageService;
|
||||
|
||||
setup(() => {
|
||||
testStorageService = new InMemoryStorageService();
|
||||
});
|
||||
|
||||
test('mixes in additional properties', async function () {
|
||||
const resolveCommonTelemetryProperties = () => {
|
||||
return {
|
||||
'userId': '1'
|
||||
};
|
||||
};
|
||||
|
||||
const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, undefined, resolveCommonTelemetryProperties);
|
||||
|
||||
assert.ok('commitHash' in props);
|
||||
assert.ok('sessionID' in props);
|
||||
assert.ok('timestamp' in props);
|
||||
assert.ok('common.platform' in props);
|
||||
assert.ok('common.timesincesessionstart' in props);
|
||||
assert.ok('common.sequence' in props);
|
||||
assert.ok('version' in props);
|
||||
assert.ok('common.firstSessionDate' in props, 'firstSessionDate');
|
||||
assert.ok('common.lastSessionDate' in props, 'lastSessionDate');
|
||||
assert.ok('common.isNewSession' in props, 'isNewSession');
|
||||
assert.ok('common.machineId' in props, 'machineId');
|
||||
|
||||
assert.equal(props['userId'], '1');
|
||||
});
|
||||
|
||||
test('mixes in additional dyanmic properties', async function () {
|
||||
let i = 1;
|
||||
const resolveCommonTelemetryProperties = () => {
|
||||
return Object.defineProperties({}, {
|
||||
'userId': {
|
||||
get: () => {
|
||||
return i++;
|
||||
},
|
||||
enumerable: true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, undefined, resolveCommonTelemetryProperties);
|
||||
assert.equal(props['userId'], '1');
|
||||
|
||||
const props2 = await resolveWorkbenchCommonProperties(testStorageService, commit, version, undefined, resolveCommonTelemetryProperties);
|
||||
assert.equal(props2['userId'], '2');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { LogLevel, ILoggerService, AbstractLogService, DEFAULT_LOG_LEVEL, ILogger } from 'vs/platform/log/common/log';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
class TestTelemetryLogger extends AbstractLogService implements ILogger {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
public logs: string[] = [];
|
||||
|
||||
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
|
||||
super();
|
||||
this.setLevel(logLevel);
|
||||
}
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Trace) {
|
||||
this.logs.push(message + JSON.stringify(args));
|
||||
}
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Debug) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Info) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
warn(message: string | Error, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Warning) {
|
||||
this.logs.push(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
error(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Error) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
critical(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Critical) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void { }
|
||||
flush(): void { }
|
||||
}
|
||||
|
||||
class TestTelemetryLoggerService implements ILoggerService {
|
||||
_serviceBrand: undefined;
|
||||
|
||||
logger: TestTelemetryLogger;
|
||||
|
||||
constructor(logLevel: LogLevel) {
|
||||
this.logger = new TestTelemetryLogger(logLevel);
|
||||
}
|
||||
|
||||
getLogger(): ILogger {
|
||||
return this.logger;
|
||||
}
|
||||
}
|
||||
|
||||
suite('TelemetryLogAdapter', () => {
|
||||
|
||||
test('Do not Log Telemetry if log level is not trace', async () => {
|
||||
const testLoggerService = new TestTelemetryLoggerService(DEFAULT_LOG_LEVEL);
|
||||
const testObject = new TelemetryLogAppender(testLoggerService, new TestInstantiationService().stub(IEnvironmentService, {}));
|
||||
testObject.log('testEvent', { hello: 'world', isTrue: true, numberBetween1And3: 2 });
|
||||
assert.equal(testLoggerService.logger.logs.length, 2);
|
||||
});
|
||||
|
||||
test('Log Telemetry if log level is trace', async () => {
|
||||
const testLoggerService = new TestTelemetryLoggerService(LogLevel.Trace);
|
||||
const testObject = new TelemetryLogAppender(testLoggerService, new TestInstantiationService().stub(IEnvironmentService, {}));
|
||||
testObject.log('testEvent', { hello: 'world', isTrue: true, numberBetween1And3: 2 });
|
||||
assert.equal(testLoggerService.logger.logs[2], 'telemetry/testEvent' + JSON.stringify([{
|
||||
properties: {
|
||||
hello: 'world',
|
||||
},
|
||||
measurements: {
|
||||
isTrue: 1, numberBetween1And3: 2
|
||||
}
|
||||
}]));
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
|
||||
import { ILogService, AbstractLogService, LogLevel, DEFAULT_LOG_LEVEL } from 'vs/platform/log/common/log';
|
||||
import { TelemetryClient, Contracts } from 'applicationinsights';
|
||||
|
||||
class AppInsightsMock extends TelemetryClient {
|
||||
@@ -27,56 +26,6 @@ class AppInsightsMock extends TelemetryClient {
|
||||
}
|
||||
}
|
||||
|
||||
class TestableLogService extends AbstractLogService implements ILogService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
public logs: string[] = [];
|
||||
|
||||
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
|
||||
super();
|
||||
this.setLevel(logLevel);
|
||||
}
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Trace) {
|
||||
this.logs.push(message + JSON.stringify(args));
|
||||
}
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Debug) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Info) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
warn(message: string | Error, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Warning) {
|
||||
this.logs.push(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
error(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Error) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
critical(message: string, ...args: any[]): void {
|
||||
if (this.getLevel() <= LogLevel.Critical) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void { }
|
||||
flush(): void { }
|
||||
}
|
||||
|
||||
suite('AIAdapter', () => {
|
||||
let appInsightsMock: AppInsightsMock;
|
||||
let adapter: AppInsightsAppender;
|
||||
@@ -181,26 +130,4 @@ suite('AIAdapter', () => {
|
||||
assert.equal(appInsightsMock.events[0].measurements!['nestedObj.testMeasurement'], 1);
|
||||
});
|
||||
|
||||
test('Do not Log Telemetry if log level is not trace', () => {
|
||||
const logService = new TestableLogService(LogLevel.Info);
|
||||
adapter = new AppInsightsAppender(prefix, { 'common.platform': 'Windows' }, () => appInsightsMock, logService);
|
||||
adapter.log('testEvent', { hello: 'world', isTrue: true, numberBetween1And3: 2 });
|
||||
assert.equal(logService.logs.length, 0);
|
||||
});
|
||||
|
||||
test('Log Telemetry if log level is trace', () => {
|
||||
const logService = new TestableLogService(LogLevel.Trace);
|
||||
adapter = new AppInsightsAppender(prefix, { 'common.platform': 'Windows' }, () => appInsightsMock, logService);
|
||||
adapter.log('testEvent', { hello: 'world', isTrue: true, numberBetween1And3: 2 });
|
||||
assert.equal(logService.logs.length, 1);
|
||||
assert.equal(logService.logs[0], 'telemetry/testEvent' + JSON.stringify([{
|
||||
properties: {
|
||||
hello: 'world',
|
||||
'common.platform': 'Windows'
|
||||
},
|
||||
measurements: {
|
||||
isTrue: 1, numberBetween1And3: 2
|
||||
}
|
||||
}]));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
|
||||
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { IStorageService, StorageScope, InMemoryStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
|
||||
suite('Telemetry - common properties', function () {
|
||||
const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'telemetryservice');
|
||||
const installSource = path.join(parentDir, 'installSource');
|
||||
|
||||
const commit: string = (undefined)!;
|
||||
const version: string = (undefined)!;
|
||||
let testStorageService: IStorageService;
|
||||
|
||||
setup(() => {
|
||||
testStorageService = new InMemoryStorageService();
|
||||
});
|
||||
|
||||
teardown(done => {
|
||||
rimraf(parentDir, RimRafMode.MOVE).then(done, done);
|
||||
});
|
||||
|
||||
test.skip('default', async function () { // {{SQL CARBON EDIT}} skip test
|
||||
await mkdirp(parentDir);
|
||||
fs.writeFileSync(installSource, 'my.install.source');
|
||||
const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource);
|
||||
assert.ok('commitHash' in props);
|
||||
assert.ok('sessionID' in props);
|
||||
assert.ok('timestamp' in props);
|
||||
assert.ok('common.platform' in props);
|
||||
assert.ok('common.nodePlatform' in props);
|
||||
assert.ok('common.nodeArch' in props);
|
||||
assert.ok('common.timesincesessionstart' in props);
|
||||
assert.ok('common.sequence' in props);
|
||||
// assert.ok('common.version.shell' in first.data); // only when running on electron
|
||||
// assert.ok('common.version.renderer' in first.data);
|
||||
assert.ok('common.platformVersion' in props, 'platformVersion');
|
||||
assert.ok('version' in props);
|
||||
assert.equal(props['common.source'], 'my.install.source');
|
||||
assert.ok('common.firstSessionDate' in props, 'firstSessionDate');
|
||||
assert.ok('common.lastSessionDate' in props, 'lastSessionDate'); // conditional, see below, 'lastSessionDate'ow
|
||||
assert.ok('common.isNewSession' in props, 'isNewSession');
|
||||
// machine id et al
|
||||
assert.ok('common.instanceId' in props, 'instanceId');
|
||||
assert.ok('common.machineId' in props, 'machineId');
|
||||
fs.unlinkSync(installSource);
|
||||
const props_1 = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource);
|
||||
assert.ok(!('common.source' in props_1));
|
||||
});
|
||||
|
||||
test.skip('lastSessionDate when aviablale', async function () { // {{SQL CARBON EDIT}} skip test
|
||||
|
||||
testStorageService.store('telemetry.lastSessionDate', new Date().toUTCString(), StorageScope.GLOBAL);
|
||||
|
||||
const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource);
|
||||
assert.ok('common.lastSessionDate' in props); // conditional, see below
|
||||
assert.ok('common.isNewSession' in props);
|
||||
assert.equal(props['common.isNewSession'], 0);
|
||||
});
|
||||
|
||||
test.skip('values chance on ask', async function () { // {{SQL CARBON EDIT}} skip test
|
||||
const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', undefined, installSource);
|
||||
let value1 = props['common.sequence'];
|
||||
let value2 = props['common.sequence'];
|
||||
assert.ok(value1 !== value2, 'seq');
|
||||
|
||||
value1 = props['timestamp'];
|
||||
value2 = props['timestamp'];
|
||||
assert.ok(value1 !== value2, 'timestamp');
|
||||
|
||||
value1 = props['common.timesincesessionstart'];
|
||||
await timeout(10);
|
||||
value2 = props['common.timesincesessionstart'];
|
||||
assert.ok(value1 !== value2, 'timesincesessionstart');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user