mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-14 03:58:33 -05:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
@@ -5,25 +5,20 @@
|
||||
|
||||
import { binarySearch } from 'vs/base/common/arrays';
|
||||
import * as Errors from 'vs/base/common/errors';
|
||||
import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { safeStringify } from 'vs/base/common/objects';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"ErrorEvent" : {
|
||||
"stack": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
|
||||
"message" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
|
||||
"filename" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
|
||||
"callstack": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
|
||||
"msg" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
|
||||
"file" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
|
||||
"line": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true },
|
||||
"column": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true },
|
||||
"uncaught_error_name": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
|
||||
"uncaught_error_msg": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
|
||||
"count": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
type ErrorEventFragment = {
|
||||
callstack: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' };
|
||||
msg?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' };
|
||||
file?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' };
|
||||
line?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
column?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
uncaught_error_name?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' };
|
||||
uncaught_error_msg?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' };
|
||||
count?: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
};
|
||||
export interface ErrorEvent {
|
||||
callstack: string;
|
||||
msg?: string;
|
||||
@@ -54,7 +49,7 @@ export default abstract class BaseErrorTelemetry {
|
||||
private _flushDelay: number;
|
||||
private _flushHandle: any = -1;
|
||||
private _buffer: ErrorEvent[] = [];
|
||||
protected _disposables: IDisposable[] = [];
|
||||
protected readonly _disposables = new DisposableStore();
|
||||
|
||||
constructor(telemetryService: ITelemetryService, flushDelay = BaseErrorTelemetry.ERROR_FLUSH_TIMEOUT) {
|
||||
this._telemetryService = telemetryService;
|
||||
@@ -62,7 +57,7 @@ export default abstract class BaseErrorTelemetry {
|
||||
|
||||
// (1) check for unexpected but handled errors
|
||||
const unbind = Errors.errorHandler.addListener((err) => this._onErrorEvent(err));
|
||||
this._disposables.push(toDisposable(unbind));
|
||||
this._disposables.add(toDisposable(unbind));
|
||||
|
||||
// (2) install implementation-specific error listeners
|
||||
this.installErrorListeners();
|
||||
@@ -71,7 +66,7 @@ export default abstract class BaseErrorTelemetry {
|
||||
dispose() {
|
||||
clearTimeout(this._flushHandle);
|
||||
this._flushBuffer();
|
||||
this._disposables = dispose(this._disposables);
|
||||
this._disposables.dispose();
|
||||
}
|
||||
|
||||
protected installErrorListeners(): void {
|
||||
@@ -124,13 +119,8 @@ export default abstract class BaseErrorTelemetry {
|
||||
|
||||
private _flushBuffer(): void {
|
||||
for (let error of this._buffer) {
|
||||
/* __GDPR__
|
||||
"UnhandledError" : {
|
||||
"${include}": [ "${ErrorEvent}" ]
|
||||
}
|
||||
*/
|
||||
// {{SQL CARBON EDIT}}
|
||||
// this._telemetryService.publicLog('UnhandledError', error, true);
|
||||
type UnhandledErrorClassification = {} & ErrorEventFragment;
|
||||
// this._telemetryService.publicLog2<ErrorEvent, UnhandledErrorClassification>('UnhandledError', error, true); {{SQL CARBON EDIT}} comment out log
|
||||
}
|
||||
this._buffer.length = 0;
|
||||
}
|
||||
|
||||
26
src/vs/platform/telemetry/common/gdprTypings.ts
Normal file
26
src/vs/platform/telemetry/common/gdprTypings.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export interface IPropertyData {
|
||||
classification: 'SystemMetaData' | 'CallstackOrException' | 'CustomerContent' | 'PublicNonPersonalData';
|
||||
purpose: 'PerformanceAndHealth' | 'FeatureInsight' | 'BusinessInsight';
|
||||
endpoint?: string;
|
||||
isMeasurement?: boolean;
|
||||
}
|
||||
|
||||
export interface IGDPRProperty {
|
||||
readonly [name: string]: IPropertyData | undefined | IGDPRProperty;
|
||||
}
|
||||
|
||||
export type ClassifiedEvent<T extends IGDPRProperty> = {
|
||||
[k in keyof T]: any
|
||||
};
|
||||
|
||||
export type StrictPropertyChecker<TEvent, TClassifiedEvent, TError> = keyof TEvent extends keyof TClassifiedEvent ? keyof TClassifiedEvent extends keyof TEvent ? TEvent : TError : TError;
|
||||
|
||||
export type StrictPropertyCheckError = 'Type of classified event does not match event properties';
|
||||
|
||||
export type StrictPropertyCheck<T extends IGDPRProperty, E> = StrictPropertyChecker<E, ClassifiedEvent<T>, StrictPropertyCheckError>;
|
||||
|
||||
export type GDPRClassification<T> = { [_ in keyof T]: IPropertyData | IGDPRProperty | undefined };
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
|
||||
export const ITelemetryService = createDecorator<ITelemetryService>('telemetryService');
|
||||
|
||||
@@ -29,9 +30,17 @@ export interface ITelemetryService {
|
||||
*/
|
||||
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void>;
|
||||
|
||||
publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>, anonymizeFilePaths?: boolean): Promise<void>;
|
||||
|
||||
setEnabled(value: boolean): void;
|
||||
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo>;
|
||||
|
||||
isOptedIn: boolean;
|
||||
}
|
||||
|
||||
// Keys
|
||||
export const instanceStorageKey = 'telemetry.instanceId';
|
||||
export const currentSessionDateStorageKey = 'telemetry.currentSessionDate';
|
||||
export const firstSessionDateStorageKey = 'telemetry.firstSessionDate';
|
||||
export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
|
||||
@@ -13,11 +13,13 @@ import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/co
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { cloneAndChange, mixin } from 'vs/base/common/objects';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
|
||||
export interface ITelemetryServiceConfig {
|
||||
appender: ITelemetryAppender;
|
||||
commonProperties?: Promise<{ [name: string]: any }>;
|
||||
piiPaths?: string[];
|
||||
trueMachineId?: string;
|
||||
}
|
||||
|
||||
export class TelemetryService implements ITelemetryService {
|
||||
@@ -56,12 +58,13 @@ export class TelemetryService implements ITelemetryService {
|
||||
if (this._configurationService) {
|
||||
this._updateUserOptIn();
|
||||
this._configurationService.onDidChangeConfiguration(this._updateUserOptIn, this, this._disposables);
|
||||
/* __GDPR__
|
||||
"optInStatus" : {
|
||||
"optIn" : { "classification": "SystemMetaData", "purpose": "BusinessInsight", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
this.publicLog('optInStatus', { optIn: this._userOptIn });
|
||||
type OptInClassification = {
|
||||
optIn: { classification: 'SystemMetaData', purpose: 'BusinessInsight', isMeasurement: true };
|
||||
};
|
||||
type OptInEvent = {
|
||||
optIn: boolean;
|
||||
};
|
||||
this.publicLog2<OptInEvent, OptInClassification>('optInStatus', { optIn: this._userOptIn });
|
||||
|
||||
this._commonProperties.then(values => {
|
||||
const isHashedId = /^[a-f0-9]+$/i.test(values['common.machineId']);
|
||||
@@ -72,6 +75,15 @@ export class TelemetryService implements ITelemetryService {
|
||||
}
|
||||
*/
|
||||
this.publicLog('machineIdFallback', { usingFallbackGuid: !isHashedId });
|
||||
|
||||
if (config.trueMachineId) {
|
||||
/* __GDPR__
|
||||
"machineIdDisambiguation" : {
|
||||
"correctedMachineId" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.publicLog('machineIdDisambiguation', { correctedMachineId: config.trueMachineId });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -131,6 +143,10 @@ export class TelemetryService implements ITelemetryService {
|
||||
});
|
||||
}
|
||||
|
||||
publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>, anonymizeFilePaths?: boolean): Promise<any> {
|
||||
return this.publicLog(eventName, data as ITelemetryData, anonymizeFilePaths);
|
||||
}
|
||||
|
||||
private _cleanupInfo(stack: string, anonymizeFilePaths?: boolean): string {
|
||||
let updatedStack = stack;
|
||||
|
||||
|
||||
@@ -8,12 +8,16 @@ import { IConfigurationService, ConfigurationTarget, ConfigurationTargetToString
|
||||
import { IKeybindingService, KeybindingSource } from 'vs/platform/keybinding/common/keybinding';
|
||||
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';
|
||||
|
||||
export const NullTelemetryService = new class implements ITelemetryService {
|
||||
_serviceBrand: undefined;
|
||||
publicLog(eventName: string, data?: ITelemetryData) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>) {
|
||||
return this.publicLog(eventName, data as ITelemetryData);
|
||||
}
|
||||
setEnabled() { }
|
||||
isOptedIn: true;
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo> {
|
||||
@@ -50,7 +54,7 @@ export class LogAppender implements ITelemetryAppender {
|
||||
}
|
||||
|
||||
log(eventName: string, data: any): void {
|
||||
const strippedData = {};
|
||||
const strippedData: { [key: string]: any } = {};
|
||||
Object.keys(data).forEach(key => {
|
||||
if (!this.commonPropertiesRegex.test(key)) {
|
||||
strippedData[key] = data[key];
|
||||
@@ -175,12 +179,12 @@ const configurationValueWhitelist = [
|
||||
'terminal.integrated.fontFamily',
|
||||
'window.openFilesInNewWindow',
|
||||
'window.restoreWindows',
|
||||
'window.nativeFullScreen',
|
||||
'window.zoomLevel',
|
||||
'workbench.editor.enablePreview',
|
||||
'workbench.editor.enablePreviewFromQuickOpen',
|
||||
'workbench.editor.showTabs',
|
||||
'workbench.editor.highlightModifiedTabs',
|
||||
'workbench.editor.swipeToNavigate',
|
||||
'workbench.sideBar.location',
|
||||
'workbench.startupEditor',
|
||||
'workbench.statusBar.visible',
|
||||
@@ -190,23 +194,27 @@ const configurationValueWhitelist = [
|
||||
export function configurationTelemetry(telemetryService: ITelemetryService, configurationService: IConfigurationService): IDisposable {
|
||||
return configurationService.onDidChangeConfiguration(event => {
|
||||
if (event.source !== ConfigurationTarget.DEFAULT) {
|
||||
/* __GDPR__
|
||||
"updateConfiguration" : {
|
||||
"configurationSource" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"configurationKeys": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
telemetryService.publicLog('updateConfiguration', {
|
||||
type UpdateConfigurationClassification = {
|
||||
configurationSource: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
configurationKeys: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
type UpdateConfigurationEvent = {
|
||||
configurationSource: string;
|
||||
configurationKeys: string[];
|
||||
};
|
||||
telemetryService.publicLog2<UpdateConfigurationEvent, UpdateConfigurationClassification>('updateConfiguration', {
|
||||
configurationSource: ConfigurationTargetToString(event.source),
|
||||
configurationKeys: flattenKeys(event.sourceConfig)
|
||||
});
|
||||
/* __GDPR__
|
||||
"updateConfigurationValues" : {
|
||||
"configurationSource" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"configurationValues": { "classification": "CustomerContent", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
telemetryService.publicLog('updateConfigurationValues', {
|
||||
type UpdateConfigurationValuesClassification = {
|
||||
configurationSource: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
configurationValues: { classification: 'CustomerContent', purpose: 'FeatureInsight' };
|
||||
};
|
||||
type UpdateConfigurationValuesEvent = {
|
||||
configurationSource: string;
|
||||
configurationValues: { [key: string]: any }[];
|
||||
};
|
||||
telemetryService.publicLog2<UpdateConfigurationValuesEvent, UpdateConfigurationValuesClassification>('updateConfigurationValues', {
|
||||
configurationSource: ConfigurationTargetToString(event.source),
|
||||
configurationValues: flattenValues(event.sourceConfig, configurationValueWhitelist)
|
||||
});
|
||||
@@ -217,12 +225,13 @@ export function configurationTelemetry(telemetryService: ITelemetryService, conf
|
||||
export function keybindingsTelemetry(telemetryService: ITelemetryService, keybindingService: IKeybindingService): IDisposable {
|
||||
return keybindingService.onDidUpdateKeybindings(event => {
|
||||
if (event.source === KeybindingSource.User && event.keybindings) {
|
||||
/* __GDPR__
|
||||
"updateKeybindings" : {
|
||||
"bindings": { "classification": "CustomerContent", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
telemetryService.publicLog('updateKeybindings', {
|
||||
type UpdateKeybindingsClassification = {
|
||||
bindings: { classification: 'CustomerContent', purpose: 'FeatureInsight' };
|
||||
};
|
||||
type UpdateKeybindingsEvents = {
|
||||
bindings: { key: string, command: string, when: string | undefined, args: boolean | undefined }[];
|
||||
};
|
||||
telemetryService.publicLog2<UpdateKeybindingsEvents, UpdateKeybindingsClassification>('updateKeybindings', {
|
||||
bindings: event.keybindings.map(binding => ({
|
||||
key: binding.key,
|
||||
command: binding.command,
|
||||
@@ -234,7 +243,7 @@ export function keybindingsTelemetry(telemetryService: ITelemetryService, keybin
|
||||
});
|
||||
}
|
||||
|
||||
function flattenKeys(value: Object): string[] {
|
||||
function flattenKeys(value: Object | undefined): string[] {
|
||||
if (!value) {
|
||||
return [];
|
||||
}
|
||||
@@ -243,7 +252,7 @@ function flattenKeys(value: Object): string[] {
|
||||
return result;
|
||||
}
|
||||
|
||||
function flatKeys(result: string[], prefix: string, value: Object): void {
|
||||
function flatKeys(result: string[], prefix: string, value: { [key: string]: any } | undefined): void {
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
Object.keys(value)
|
||||
.forEach(key => flatKeys(result, prefix ? `${prefix}.${key}` : key, value[key]));
|
||||
@@ -252,7 +261,7 @@ function flatKeys(result: string[], prefix: string, value: Object): void {
|
||||
}
|
||||
}
|
||||
|
||||
function flattenValues(value: Object, keys: string[]): { [key: string]: any }[] {
|
||||
function flattenValues(value: { [key: string]: any } | undefined, keys: string[]): { [key: string]: any }[] {
|
||||
if (!value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user