Skip to content

Commit

Permalink
Add telemetry for download, extract, and analyze.
Browse files Browse the repository at this point in the history
Fixes microsoft#2461 (alternate fix to PR microsoft#2593)

- Capture telemetry surrounds methods, minimizing change
- Telemetry type can be altered with less code later.
- Add success/fail props modifyer func to `captureTelemetry`
  • Loading branch information
d3r3kk committed Sep 15, 2018
1 parent 59e79a3 commit 8dc42ab
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
23 changes: 23 additions & 0 deletions src/client/activation/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import { ProgressLocation, window } from 'vscode';
import { createDeferred } from '../../utils/async';
import { IFileSystem } from '../common/platform/types';
import { IExtensionContext, IOutputChannel } from '../common/types';
import { captureTelemetry } from '../telemetry';
import {
PYTHON_LANGUAGE_SERVER_DOWNLOADED,
PYTHON_LANGUAGE_SERVER_EXTRACTED
} from '../telemetry/constants';
import { LanguageServerInstallOpTelemetry } from '../telemetry/types';
import { PlatformData, PlatformName } from './platformData';
import { IDownloadFileService } from './types';

Expand All @@ -28,6 +34,11 @@ export const DownloadLinks = {
};

export class LanguageServerDownloader {
//tslint:disable-next-line:no-unused-variable
private lsDownloadTelemetry: LanguageServerInstallOpTelemetry = {};
//tslint:disable-next-line:no-unused-variable
private lsExtractTelemetry: LanguageServerInstallOpTelemetry = {};

constructor(
private readonly output: IOutputChannel,
private readonly fs: IFileSystem,
Expand Down Expand Up @@ -59,6 +70,12 @@ export class LanguageServerDownloader {
}
}

@captureTelemetry(
PYTHON_LANGUAGE_SERVER_DOWNLOADED,
{},
true,
(props?: LanguageServerInstallOpTelemetry) => props ? props.success = true : undefined
)
private async downloadFile(uri: string, title: string): Promise<string> {
this.output.append(`Downloading ${uri}... `);
const tempFile = await this.fs.createTemporaryFile(downloadFileExtension);
Expand Down Expand Up @@ -101,6 +118,12 @@ export class LanguageServerDownloader {
return tempFile.filePath;
}

@captureTelemetry(
PYTHON_LANGUAGE_SERVER_EXTRACTED,
this.languageServerStartupTelemetry,
true,
(props?: LanguageServerInstallOpTelemetry) => props ? props.success = true : undefined
)
private async unpackArchive(extensionPath: string, tempFilePath: string): Promise<void> {
this.output.append('Unpacking archive... ');

Expand Down
15 changes: 14 additions & 1 deletion src/client/activation/languageServer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

'use strict';

import { inject, injectable } from 'inversify';
import * as path from 'path';
import {
Expand All @@ -27,12 +29,15 @@ import {
} from '../common/types';
import { IServiceContainer } from '../ioc/types';
import { LanguageServerSymbolProvider } from '../providers/symbolProvider';
import { captureTelemetry } from '../telemetry';
import {
PYTHON_LANGUAGE_SERVER_DOWNLOADED,
PYTHON_LANGUAGE_SERVER_ENABLED,
PYTHON_LANGUAGE_SERVER_ERROR
PYTHON_LANGUAGE_SERVER_ERROR,
PYTHON_LANGUAGE_SERVER_STARTUP
} from '../telemetry/constants';
import { getTelemetryReporter } from '../telemetry/telemetry';
import { LanguageServerInstallOpTelemetry } from '../telemetry/types';
import { IUnitTestManagementService } from '../unittests/types';
import { LanguageServerDownloader } from './downloader';
import { InterpreterData, InterpreterDataService } from './interpreterDataService';
Expand Down Expand Up @@ -75,6 +80,8 @@ export class LanguageServerExtensionActivator implements IExtensionActivator {
private surveyBanner: IPythonExtensionBanner;
// tslint:disable-next-line:no-unused-variable
private progressReporting: ProgressReporting | undefined;
//tslint:disable-next-line:no-unused-variable
private languageServerStartupTelemetry: LanguageServerInstallOpTelemetry = {};

constructor(@inject(IServiceContainer) private readonly services: IServiceContainer) {
this.context = this.services.get<IExtensionContext>(IExtensionContext);
Expand Down Expand Up @@ -140,6 +147,12 @@ export class LanguageServerExtensionActivator implements IExtensionActivator {
(this.configuration.getSettings() as PythonSettings).removeListener('change', this.onSettingsChanged.bind(this));
}

@captureTelemetry(
PYTHON_LANGUAGE_SERVER_STARTUP,
this.languageServerStartupTelemetry,
true,
(props?: LanguageServerInstallOpTelemetry) => props ? props.success = true : undefined
)
private async startLanguageServer(clientOptions: LanguageClientOptions): Promise<boolean> {
// Determine if we are running MSIL/Universal via dotnet or self-contained app.

Expand Down
1 change: 1 addition & 0 deletions src/client/telemetry/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const UNITTEST_RUN = 'UNITTEST.RUN';
export const UNITTEST_DISCOVER = 'UNITTEST.DISCOVER';
export const UNITTEST_VIEW_OUTPUT = 'UNITTEST.VIEW_OUTPUT';
export const PYTHON_LANGUAGE_SERVER_ENABLED = 'PYTHON_LANGUAGE_SERVER.ENABLED';
export const PYTHON_LANGUAGE_SERVER_EXTRACTED = 'PYTHON_LANGUAGE_SERVER.EXTRACTED';
export const PYTHON_LANGUAGE_SERVER_DOWNLOADED = 'PYTHON_LANGUAGE_SERVER.DOWNLOADED';
export const PYTHON_LANGUAGE_SERVER_ERROR = 'PYTHON_LANGUAGE_SERVER.ERROR';
export const PYTHON_LANGUAGE_SERVER_STARTUP = 'PYTHON_LANGUAGE_SERVER.STARTUP';
Expand Down
16 changes: 15 additions & 1 deletion src/client/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ export function sendTelemetryEvent(eventName: string, durationMs?: number, prope
}

// tslint:disable-next-line:no-any function-name
export function captureTelemetry(eventName: string, properties?: TelemetryProperties, captureDuration: boolean = true) {
export function captureTelemetry(
eventName: string,
properties?: TelemetryProperties,
captureDuration: boolean = true,
// tslint:disable-next-line:no-any
beforeSuccessEmit?: (props?: any) => void,
// tslint:disable-next-line:no-any
beforeFailEmit?: (props?: any) => void
) {
// tslint:disable-next-line:no-function-expression no-any
return function (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
const originalMethod = descriptor.value;
Expand All @@ -48,11 +56,17 @@ export function captureTelemetry(eventName: string, properties?: TelemetryProper
// tslint:disable-next-line:prefer-type-cast
(result as Promise<void>)
.then(data => {
if (beforeSuccessEmit) {
beforeSuccessEmit(properties);
}
sendTelemetryEvent(eventName, stopWatch.elapsedTime, properties);
return data;
})
// tslint:disable-next-line:promise-function-async
.catch(ex => {
if (beforeFailEmit) {
beforeFailEmit(properties);
}
sendTelemetryEvent(eventName, stopWatch.elapsedTime, properties);
return Promise.reject(ex);
});
Expand Down
17 changes: 16 additions & 1 deletion src/client/telemetry/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export type FormatTelemetry = {
formatSelection: boolean;
};

export type LanguageServerInstallOpTelemetry = {
success?: boolean;
};

export type LinterTrigger = 'auto' | 'save';

export type LintingTelemetry = {
Expand Down Expand Up @@ -81,4 +85,15 @@ export type TerminalTelemetry = {
pythonVersion?: string;
interpreterType?: InterpreterType;
};
export type TelemetryProperties = FormatTelemetry | LintingTelemetry | EditorLoadTelemetry | PythonInterpreterTelemetry | CodeExecutionTelemetry | TestRunTelemetry | TestDiscoverytTelemetry | FeedbackTelemetry | TerminalTelemetry | DebuggerTelemetryV2 | SettingsTelemetry;
export type TelemetryProperties = FormatTelemetry
| LanguageServerInstallOpTelemetry
| LintingTelemetry
| EditorLoadTelemetry
| PythonInterpreterTelemetry
| CodeExecutionTelemetry
| TestRunTelemetry
| TestDiscoverytTelemetry
| FeedbackTelemetry
| TerminalTelemetry
| DebuggerTelemetryV2
| SettingsTelemetry;

0 comments on commit 8dc42ab

Please sign in to comment.