Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add telemetry #6

Merged
merged 88 commits into from
Nov 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
d7304ab
remove unwanted and unused deps and features
DonJayamanne Nov 2, 2017
0b5f90f
enable decorators
DonJayamanne Nov 2, 2017
4d93442
telemetry helper
DonJayamanne Nov 2, 2017
0742155
telemetry for activation of extension
DonJayamanne Nov 2, 2017
5c1995b
moved type declaration close to source
DonJayamanne Nov 2, 2017
ba24f1b
changes to how conda version is captured
DonJayamanne Nov 2, 2017
b9ae68f
telemetry for formatters
DonJayamanne Nov 2, 2017
731d374
telemetry added
DonJayamanne Nov 2, 2017
83c2733
capture telemetry when interpreter is set
DonJayamanne Nov 2, 2017
9c8ab22
resolved linter warning
DonJayamanne Nov 2, 2017
6d33aa7
added telemetry for workspace symbols
DonJayamanne Nov 2, 2017
2a53c3a
added telemetry for code execution
DonJayamanne Nov 2, 2017
b7ee666
refactorred telemetry code
DonJayamanne Nov 2, 2017
70c6054
added telemetry for unit tests
DonJayamanne Nov 2, 2017
c69ff4a
merged master
DonJayamanne Nov 2, 2017
2275821
added copyright header
DonJayamanne Nov 2, 2017
dfa30f7
fix test runner id
DonJayamanne Nov 3, 2017
ad3efb4
more strictness for later
DonJayamanne Nov 3, 2017
8ba7495
add copyright header
DonJayamanne Nov 3, 2017
c62743a
tests for interpreter and pip version
DonJayamanne Nov 3, 2017
27701cd
missed colon
DonJayamanne Nov 3, 2017
f40ce28
do not stop discovery when running tests
DonJayamanne Nov 3, 2017
de928ad
incorrect telemetry scope for running unittests
DonJayamanne Nov 3, 2017
92ec931
fixed unit tests
DonJayamanne Nov 3, 2017
8a06e98
fixed license headers
DonJayamanne Nov 3, 2017
167c781
Merge branch 'Telemetry' of https://github.com/Microsoft/vscode-pytho…
DonJayamanne Nov 3, 2017
4b570a5
use regex when extracting version info
DonJayamanne Nov 3, 2017
01562cb
removed license header
DonJayamanne Nov 3, 2017
be4f351
fixed test
DonJayamanne Nov 3, 2017
d62a8a2
fixed typo
DonJayamanne Nov 3, 2017
d57d9e9
removed unwanted props
DonJayamanne Nov 3, 2017
04ddb39
fixed typo
DonJayamanne Nov 3, 2017
d141205
Simplify copyright header
brettcannon Nov 3, 2017
906e43f
Simplify copyright header
brettcannon Nov 3, 2017
d222c44
Simplify copyright header
brettcannon Nov 3, 2017
bc321de
Simplify copyright header
brettcannon Nov 3, 2017
a3cff53
Simplify copyright header
brettcannon Nov 3, 2017
f447ef8
Remove copyright header
brettcannon Nov 3, 2017
612103f
Remove copyright header
brettcannon Nov 3, 2017
4c160ba
Remove copyright header
brettcannon Nov 3, 2017
50e3b65
Remove copyright header
brettcannon Nov 3, 2017
f2a806b
Remove copyright header
brettcannon Nov 3, 2017
d666edd
Remove copyright header
brettcannon Nov 3, 2017
3bb4d50
Remove copyright header
brettcannon Nov 3, 2017
164b27e
Remove copyright header
brettcannon Nov 3, 2017
a98b80e
Remove copyright header
brettcannon Nov 3, 2017
6d88c7b
Remove copyright header
brettcannon Nov 3, 2017
69ea92d
Remove copyright header
brettcannon Nov 3, 2017
a2b9292
Remove copyright header
brettcannon Nov 3, 2017
92671f8
Remove copyright header
brettcannon Nov 3, 2017
9e27b86
Remove copyright header
brettcannon Nov 3, 2017
c42d9c4
Remove copyright header
brettcannon Nov 3, 2017
b67f10b
Remove copyright header
brettcannon Nov 3, 2017
638407e
Remove copyright header
brettcannon Nov 3, 2017
d747a2d
Remove copyright header
brettcannon Nov 3, 2017
b110d7e
Remove copyright header
brettcannon Nov 3, 2017
0881e49
Remove copyright header
brettcannon Nov 3, 2017
0fe0b42
Remove copyright header
brettcannon Nov 3, 2017
3095f8b
Remove copyright header
brettcannon Nov 3, 2017
e750ff7
Remove copyright header
brettcannon Nov 3, 2017
31343c0
Remove copyright header
brettcannon Nov 3, 2017
75ec627
Remove copyright header
brettcannon Nov 3, 2017
bbd8915
Remove copyright header
brettcannon Nov 3, 2017
f36a1d5
Remove copyright header
brettcannon Nov 3, 2017
e114788
Remove copyright header
brettcannon Nov 3, 2017
a7f3e52
Remove copyright header
brettcannon Nov 3, 2017
21b924f
Remove copyright header
brettcannon Nov 3, 2017
da85710
Remove copyright header
brettcannon Nov 3, 2017
f2d31f6
Remove copyright header
brettcannon Nov 3, 2017
74ae430
Remove copyright header
brettcannon Nov 3, 2017
93600b7
Remove copyright header
brettcannon Nov 3, 2017
4e923af
Remove copyright header
brettcannon Nov 3, 2017
a89fd8e
Remove copyright header
brettcannon Nov 3, 2017
d6241ef
Remove copyright header
brettcannon Nov 3, 2017
f736006
Remove copyright header
brettcannon Nov 3, 2017
78c0d19
Remove copyright header
brettcannon Nov 3, 2017
e330ef0
Remove copyright header
brettcannon Nov 3, 2017
5168eb2
Remove copyright header
brettcannon Nov 3, 2017
258a381
Remove copyright header
brettcannon Nov 3, 2017
4247d9b
Remove copyright header
brettcannon Nov 3, 2017
bb2826e
Remove copyright header
brettcannon Nov 3, 2017
93c6561
Remove copyright header
brettcannon Nov 3, 2017
c653c06
Remove copyright header
brettcannon Nov 3, 2017
e55c15e
Remove copyright header
brettcannon Nov 3, 2017
a1b9b26
Remove copyright header
brettcannon Nov 3, 2017
7c56f5a
Remove copyright header
brettcannon Nov 3, 2017
ef467e2
Simplify copyright header
brettcannon Nov 3, 2017
b7100a7
Remove copyright header
brettcannon Nov 3, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 0 additions & 79 deletions src/client/common/telemetry.ts

This file was deleted.

28 changes: 28 additions & 0 deletions src/client/common/telemetry/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
export const COMPLETION = 'COMPLETION';
export const DEFINITION = 'DEFINITION';
export const HOVER_DEFINITION = 'HOVER_DEFINITION';
export const REFERENCE = 'REFERENCE';
export const SIGNATURE = 'SIGNATURE';
export const SYMBOL = 'SYMBOL';
export const FORMAT_SORT_IMPORTS = 'FORMAT.SORT_IMPORTS';
export const FORMAT = 'FORMAT.FORMAT';
export const EDITOR_LOAD = 'EDITOR.LOAD';
export const LINTING = 'LINTING';
export const GO_TO_OBJECT_DEFINITION = 'GO_TO_OBJECT_DEFINITION';
export const UPDATE_PYSPARK_LIBRARY = 'UPDATE_PYSPARK_LIBRARY';
export const REFACTOR_RENAME = 'REFACTOR_RENAME';
export const REFACTOR_EXTRACT_VAR = 'REFACTOR_EXTRACT_VAR';
export const REFACTOR_EXTRACT_FUNCTION = 'REFACTOR_EXTRACT_FUNCTION';
export const REPL = 'REPL';
export const PYTHON_INTERPRETER = 'PYTHON_INTERPRETER';
export const WORKSPACE_SYMBOLS_BUILD = 'WORKSPACE_SYMBOLS.BUILD';
export const WORKSPACE_SYMBOLS_GO_TO = 'WORKSPACE_SYMBOLS.GO_TO';
export const EXECUTION_CODE = 'EXECUTION_CODE';
export const EXECUTION_DJANGO = 'EXECUTION_DJANGO';
export const DEBUGGER = 'DEBUGGER';
export const UNITTEST_STOP = 'UNITTEST.STOP';
export const UNITTEST_RUN = 'UNITTEST.RUN';
export const UNITTEST_DISCOVER = 'UNITTEST.DISCOVER';
export const UNITTEST_VIEW_OUTPUT = 'UNITTEST.VIEW_OUTPUT';
82 changes: 82 additions & 0 deletions src/client/common/telemetry/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { StopWatch } from './stopWatch';
import { getTelemetryReporter } from './telemetry';
import { TelemetryProperties } from './types';

export function sendTelemetryEvent(eventName: string, durationMs?: number, properties?: TelemetryProperties) {
const reporter = getTelemetryReporter();
const measures = typeof durationMs === 'number' ? { duration: durationMs } : undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason we need to worry about the unit of measure changing? E.g. should as label the data as duration-ms?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we'll every want another unit (we can always do the math at the moment of reporting)


// tslint:disable-next-line:no-any
const customProperties: { [key: string]: string } = {};
if (properties) {
// tslint:disable-next-line:prefer-type-cast no-any
const data = properties as any;
Object.getOwnPropertyNames(data).forEach(prop => {
// tslint:disable-next-line:prefer-type-cast no-any no-unsafe-any
(customProperties as any)[prop] = typeof data[prop] === 'string' ? data[prop] : data[prop].toString();
});
}
//
reporter.sendTelemetryEvent(eventName, properties ? customProperties : undefined, measures);
}

// tslint:disable-next-line:no-any function-name
export function captureTelemetry(eventName: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I miss context managers from Python.

// tslint:disable-next-line:no-function-expression no-any
return function (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
const originalMethod = descriptor.value;
// tslint:disable-next-line:no-function-expression no-any
descriptor.value = function (...args: any[]) {
const stopWatch = new StopWatch();
// tslint:disable-next-line:no-invalid-this no-use-before-declare no-unsafe-any
const result = originalMethod.apply(this, args);

// If method being wrapped returns a promise then wait for it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth having two separate functions, e.g. captureAsyncTelemetry() and captureTelemetry() to simplify this logic at all?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, this is a decorator function (a decorator that can be applied to any method (sync or async).

e.g.

class Somethind {
    @captureTelemetry()
    public doSomethingSynchronously(){ }

    @captureTelemetry()
    public async doSomethingAsynchronously(){ }
}

// tslint:disable-next-line:no-unsafe-any
if (result && typeof result.then === 'function' && typeof result.catch === 'function') {
// tslint:disable-next-line:prefer-type-cast
(result as Promise<void>)
.then(data => {
sendTelemetryEvent(eventName, stopWatch.elapsedTime);
return data;
})
// tslint:disable-next-line:promise-function-async
.catch(ex => {
sendTelemetryEvent(eventName, stopWatch.elapsedTime);
return Promise.reject(ex);
});
} else {
sendTelemetryEvent(eventName, stopWatch.elapsedTime);
}

return result;
};

return descriptor;
};
}

// tslint:disable-next-line:no-any function-name
export function sendTelemetryWhenDone(eventName: string, promise: Promise<any> | Thenable<any>,
stopWatch?: StopWatch, properties?: TelemetryProperties) {
stopWatch = stopWatch ? stopWatch : new StopWatch();
if (typeof promise.then === 'function') {
// tslint:disable-next-line:prefer-type-cast no-any
(promise as Promise<any>)
.then(data => {
// tslint:disable-next-line:no-non-null-assertion
sendTelemetryEvent(eventName, stopWatch!.elapsedTime, properties);
return data;
// tslint:disable-next-line:promise-function-async
}, ex => {
// tslint:disable-next-line:no-non-null-assertion
sendTelemetryEvent(eventName, stopWatch!.elapsedTime, properties);
return Promise.reject(ex);
});
} else {
throw new Error('Method is neither a Promise nor a Theneable');
}
}
13 changes: 13 additions & 0 deletions src/client/common/telemetry/stopWatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

export class StopWatch {
private started: number = Date.now();
private stopped?: number;
public get elapsedTime() {
return (this.stopped ? this.stopped : Date.now()) - this.started;
}
public stop() {
this.stopped = Date.now();
}
}
26 changes: 26 additions & 0 deletions src/client/common/telemetry/telemetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// tslint:disable-next-line:no-reference
/// <reference path="./vscode-extension-telemetry.d.ts" />
import { extensions } from 'vscode';
// tslint:disable-next-line:import-name
import TelemetryReporter from 'vscode-extension-telemetry';

// tslint:disable-next-line:no-any
let telemetryReporter: TelemetryReporter;
export function getTelemetryReporter() {
if (telemetryReporter) {
return telemetryReporter;
}
const extensionId = 'donjayamanne.python';
// tslint:disable-next-line:no-non-null-assertion
const extension = extensions.getExtension(extensionId)!;
// tslint:disable-next-line:no-unsafe-any
const extensionVersion = extension.packageJSON.version;
// tslint:disable-next-line:no-unsafe-any
const aiKey = extension.packageJSON.contributes.debuggers[0].aiKey;

// tslint:disable-next-line:no-unsafe-any
return telemetryReporter = new TelemetryReporter(extensionId, extensionVersion, aiKey);
}
45 changes: 45 additions & 0 deletions src/client/common/telemetry/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
export type EditorLoadTelemetry = {
condaVersion: string;
};
export type FormatTelemetry = {
tool: 'autoppep8' | 'yapf';
hasCustomArgs: boolean;
formatSelection: boolean;
};
export type LintingTelemetry = {
tool: 'flake8' | 'mypy' | 'pep8' | 'prospector' | 'pydocstyle' | 'pylama' | 'pylint';
hasCustomArgs: boolean;
trigger: 'save' | 'auto';
executableSpecified: boolean;
};
export type PythonInterpreterTelemetry = {
trigger: 'ui' | 'shebang' | 'load';
failed: boolean;
version: string;
pipVersion: string;
};
export type CodeExecutionTelemetry = {
scope: 'file' | 'selection';
};
export type DebuggerTelemetry = {
trigger: 'launch' | 'attach'
console?: 'none' | 'integratedTerminal' | 'externalTerminal';
debugOptions?: string;
pyspark?: boolean;
hasEnvVars?: boolean;
};
export type TestRunTelemetry = {
tool: 'nosetest' | 'pytest' | 'unittest'
scope: 'currentFile' | 'all' | 'file' | 'class' | 'function' | 'failed';
debugging: boolean;
trigger: 'ui' | 'codelens' | 'commandpalette' | 'auto';
failed: boolean;
};
export type TestDiscoverytTelemetry = {
tool: 'nosetest' | 'pytest' | 'unittest'
trigger: 'ui' | 'commandpalette';
failed: boolean;
};
export type TelemetryProperties = FormatTelemetry | LintingTelemetry | EditorLoadTelemetry | PythonInterpreterTelemetry | CodeExecutionTelemetry | TestRunTelemetry | TestDiscoverytTelemetry;
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
declare module "vscode-extension-telemetry" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there really no .d.ts file on npm for the package? If so, has that fact been reported upstream?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, everyone seems to be creating their own dts for this damn thing... can't understand why. plan was to create a dts a create PR (separate piece of work)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing to do here.

declare module 'vscode-extension-telemetry' {
export default class TelemetryReporter {
private extensionId;
private extensionVersion;
private appInsightsClient;
private commonProperties;
private static SQM_KEY;
private static REGISTRY_USERID_VALUE;
private static REGISTRY_MACHINEID_VALUE;

/**
* Constructs a new telemetry reporter
* @param {string} extensionId All events will be prefixed with this event name
* @param {string} extensionVersion Extension version to be reported with each event
* @param {string} key The application insights key
*/
// tslint:disable-next-line:no-empty
constructor(extensionId: string, extensionVersion: string, key: string);
private setupAIClient(client);
private loadVSCodeCommonProperties(machineId, sessionId, version);
private loadCommonProperties();
private addCommonProperties(properties);
private getWinRegKeyData(key, name, hive, callback);

/**
* Sends a telemetry event
* @param {string} eventName The event name
* @param {object} properties An associative array of strings
* @param {object} measures An associative array of numbers
*/
sendTelemetryEvent(eventName: string, properties?: {
// tslint:disable-next-line:member-access
public sendTelemetryEvent(eventName: string, properties?: {
[key: string]: string;
}, measures?: {
[key: string]: number;
// tslint:disable-next-line:no-empty
}): void;
}
}
}
31 changes: 0 additions & 31 deletions src/client/common/telemetryContracts.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/client/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ export function areBasePathsSame(path1: string, path2: string) {
path2 = IS_WINDOWS ? path2.replace(/\//g, "\\") : path2;
return path.dirname(path1).toUpperCase() === path.dirname(path2).toUpperCase();
}
export async function getInterpreterDisplayName(pythonPath: string) {
export async function getInterpreterVersion(pythonPath: string) {
return await new Promise<string>((resolve, reject) => {
child_process.execFile(pythonPath, ['--version'], (error, stdout, stdErr) => {
const out = (typeof stdErr === 'string' ? stdErr : '') + os.EOL + (typeof stdout === 'string' ? stdout : '');
Expand Down
Loading