Skip to content

Add telemetry for Language Server download, extraction, and analysis (startup) time. #2593

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

Closed
wants to merge 7 commits into from

Conversation

d3r3kk
Copy link

@d3r3kk d3r3kk commented Sep 14, 2018

Completes #2461

Note: I had to add telemetry to the ProgressReporting class to figure out when the LS reports that it is completed the analysis for the workspace. If there is a better way for me to do this, let me know! I believe that once the analysis reporting that the LS is doing today is fixed up, the two telemetry measurements I am sending (PYTHON_LANGUAGE_SERVER_ANALYSISTIME and PYTHON_LANGUAGE_SERVER_STARTUP) should be pretty much equal.

  • Pull request represents a single change (i.e. not fixing disparate/unrelated things in a single PR)

  • Title summarizes what is changing

  • Has a news entry file (remember to thank yourself!)

  • Has unit tests & system/integration tests (Telemetry isn't really testable yet)

  • Any new/changed dependencies in package.json are pinned (e.g. "1.2.3", not "^1.2.3" for the specified version)

  • package-lock.json has been regenerated by running npm install (if dependencies have changed)

  • Remove .then from await code that was altered in my prior change and not updated with a later change.

  • Change from default values for download/extract being false to being undefined and nullable.

  • Change the download/extract time records to defaulting to undefined instead of -1.

  • Investigate (and use) decorators over return values in the capturing of the downloader telemetry.

  • Do not send error messages into telemetry without sanitizing them first (or just sending a meaningful telemetry string for the failure that avoids PII issues).

  • Don't bother giving argument lists to anonymous functions that never make use of those arguments.

  • Create a separate method to deal with the analysis time measurement instead of just duplicating code in anonymous functions.

- Simple fix to add telemetry in the existing manner
- Testing will have to be done a different way
- versus hard-coding the string in multiple places.
- Move telemetry into the languageServer class and out of downloader.
- Add telemetry properties.
- Add telemetry for languageServer startup time.
- last change introduced a bug to do with async/await order
- moved sendTelemetryWhenDone up a level to compensate
- Telemetry will show success/fail on the analysis time this way.
- Alphabetize PYTHON_LANGUAGE_SERVER_... constants
@d3r3kk d3r3kk requested a review from DonJayamanne September 14, 2018 19:29
throw new Error(err);
try {
await this.downloadFile(downloadUri, 'Downloading Microsoft Python Language Server... ')
.then((tmpFilePath: string) => {

Choose a reason for hiding this comment

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

You don't need the .then. Just use the await, and next line initialize stats.
I.e. you can revert the change.

timer.reset();
try {
await this.unpackArchive(context.extensionPath, localTempFilePath)
.then(() => {

Choose a reason for hiding this comment

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

no need of .then.
Just initialize the stats immediately after await line

@@ -57,6 +57,20 @@ export type DebuggerPerformanceTelemetry = {
duration: number;
action: 'stepIn' | 'stepOut' | 'continue' | 'next' | 'launch';
};
export type LanguageServerInstallTelemetry = {
downloadSuccess: boolean;

Choose a reason for hiding this comment

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

all of these properties should be nullable.
Default values cannot be false. Cuz its misleading to have downloadSuccess = false and extractSuccess = false. Cuz if download fails, then extraction was never attempted. Hence it should not be false, else we end up with skewed data.

public async downloadLanguageServer(context: IExtensionContext): Promise<void> {
public async downloadLanguageServer(context: IExtensionContext): Promise<LanguageServerInstallTelemetry> {
const stats: LanguageServerInstallTelemetry = {
downloadMs: -1,

Choose a reason for hiding this comment

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

Please remove the time = -1.
Default should be undefined

@@ -41,22 +43,48 @@ export class LanguageServerDownloader {
return DownloadLinks[platformString];
}

public async downloadLanguageServer(context: IExtensionContext): Promise<void> {
public async downloadLanguageServer(context: IExtensionContext): Promise<LanguageServerInstallTelemetry> {

Choose a reason for hiding this comment

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

You should be able to revert the changes to this method and use captureTelemetry decorator in telemetry/index.ts

Choose a reason for hiding this comment

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

All you'll need to do is add the decorator the to downloadFile and unpackArchieve methods.
You might want to tweak the captureTelemetry function to capture failures (minor tweak).

Choose a reason for hiding this comment

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

With that you'll be able to reduce the changes to the code, with the power of decorators :)

};
sendTelemetryWhenDone(
PYTHON_LANGUAGE_SERVER_STARTUP,
this.startLanguageClient()

Choose a reason for hiding this comment

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

Again, you should be able to use the decorator here.
Please note, you cannot just send the entire error object via telemetry.
We need to be aware of GDPR, sending error object could contain stack traces, that could contain PII (user name, etc).


export class ProgressReporting {
private statusBarMessage: Disposable | undefined;
private progress: Progress<{ message?: string; increment?: number }> | undefined;
private progressDeferred: Deferred<void> | undefined;
private progressTimer: StopWatch | undefined;

Choose a reason for hiding this comment

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

Or a more simpler way is private progressTimer?: StopWatch;
No changes necessary here, just letting you know there's a shorter syntax for nullable.

this.progressTimer = new StopWatch();
this.progressTimeout = setTimeout(
// tslint:disable-next-line:no-any
(...args: any[]) => {

Choose a reason for hiding this comment

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

please change to argumentless anonymous func as follows:

this.progressTimeout = setTimeout(()=> {
...
});

Choose a reason for hiding this comment

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

I.e. you do not need (...args: any[]) = >

Choose a reason for hiding this comment

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

Can we move this callback into a separate function, e.g.
this.progressTimeOut = setTimeout(()=> this.handleProgressTimeout());

@@ -6,6 +6,8 @@ export const PYTHON = [
{ scheme: 'untitled', language: PYTHON_LANGUAGE }
];

export const PVSC_EXTENSION_ID = 'ms-python.python';

Choose a reason for hiding this comment

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

👍

d3r3kk added a commit to d3r3kk/vscode-python that referenced this pull request Sep 15, 2018
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`
@d3r3kk
Copy link
Author

d3r3kk commented Sep 15, 2018

Closing in favour of #2597.

@d3r3kk d3r3kk closed this Sep 15, 2018
d3r3kk added a commit to d3r3kk/vscode-python that referenced this pull request Sep 17, 2018
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`
d3r3kk added a commit that referenced this pull request Sep 18, 2018
@d3r3kk d3r3kk deleted the telemetry_ext branch December 19, 2018 18:04
@lock lock bot locked as resolved and limited conversation to collaborators Jul 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants