Skip to content

Commit 5f43d5f

Browse files
author
Elaheh Rashedi
authored
add telemetry updates for openfile (#6257)
* copy ClientCollection.ts * copy extension.ts * copy client.ts * rename LS message * create new file * spath to path * remove uri with logged telemtery * fix linter errors * fix linter errors 2 * fix linter error 3 * change warm start collection * nit * bring setDidOpenTime to the beginnign of didOpen * reply to reviews
1 parent 444b3cc commit 5f43d5f

5 files changed

Lines changed: 112 additions & 1 deletion

File tree

Extension/src/LanguageServer/client.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ function publishDiagnostics(params: PublishDiagnosticsParams): void {
161161

162162
const realUri: vscode.Uri = vscode.Uri.parse(params.uri);
163163
diagnosticsCollection.set(realUri, diagnostics);
164+
165+
clientCollection.timeTelemetryCollector.setUpdateRangeTime(realUri);
164166
}
165167

166168
interface WorkspaceFolderParams {
@@ -424,6 +426,10 @@ enum SemanticTokenModifiers {
424426
local = (1 << 2)
425427
}
426428

429+
interface IntelliSenseSetup {
430+
uri: string;
431+
}
432+
427433
// Requests
428434
const QueryCompilerDefaultsRequest: RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void> = new RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void>('cpptools/queryCompilerDefaults');
429435
const QueryTranslationUnitSourceRequest: RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void, void> = new RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void, void>('cpptools/queryTranslationUnitSource');
@@ -482,6 +488,7 @@ const ShowMessageWindowNotification: NotificationType<ShowMessageWindowParams, v
482488
const ShowWarningNotification: NotificationType<ShowWarningParams, void> = new NotificationType<ShowWarningParams, void>('cpptools/showWarning');
483489
const ReportTextDocumentLanguage: NotificationType<string, void> = new NotificationType<string, void>('cpptools/reportTextDocumentLanguage');
484490
const SemanticTokensChanged: NotificationType<string, void> = new NotificationType<string, void>('cpptools/semanticTokensChanged');
491+
const IntelliSenseSetupNotification: NotificationType<IntelliSenseSetup, void> = new NotificationType<IntelliSenseSetup, void>('cpptools/IntelliSenseSetup');
485492

486493
let failureMessageShown: boolean = false;
487494

@@ -1892,6 +1899,7 @@ export class DefaultClient implements Client {
18921899
this.languageClient.onNotification(ShowWarningNotification, showWarning);
18931900
this.languageClient.onNotification(ReportTextDocumentLanguage, (e) => this.setTextDocumentLanguage(e));
18941901
this.languageClient.onNotification(SemanticTokensChanged, (e) => this.semanticTokensProvider?.invalidateFile(e));
1902+
this.languageClient.onNotification(IntelliSenseSetupNotification, (e) => this.logIntellisenseSetupTime(e));
18951903
setupOutputHandlers();
18961904
}
18971905

@@ -2154,6 +2162,10 @@ export class DefaultClient implements Client {
21542162
}
21552163
}
21562164

2165+
public logIntellisenseSetupTime(notification: IntelliSenseSetup): void {
2166+
clientCollection.timeTelemetryCollector.setSetupTime(vscode.Uri.parse(notification.uri));
2167+
}
2168+
21572169
private promptCompileCommands(params: CompileCommandsPaths): void {
21582170
if (!params.workspaceFolderUri) {
21592171
return;

Extension/src/LanguageServer/clientCollection.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66

77
import * as vscode from 'vscode';
88
import * as util from '../common';
9-
import * as telemetry from '../telemetry';
109
import * as cpptools from './client';
10+
import * as telemetry from '../telemetry';
1111
import { getCustomConfigProviders } from './customProviders';
12+
import { TimeTelemetryCollector } from './timeTelemetryCollector';
1213

1314
const defaultClientKey: string = "@@default@@";
1415
export interface ClientKey {
@@ -22,6 +23,7 @@ export class ClientCollection {
2223
private defaultClient: cpptools.Client;
2324
private activeClient: cpptools.Client;
2425
private activeDocument?: vscode.TextDocument;
26+
public timeTelemetryCollector: TimeTelemetryCollector;
2527

2628
public get ActiveClient(): cpptools.Client { return this.activeClient; }
2729
public get Names(): ClientKey[] {
@@ -60,6 +62,8 @@ export class ClientCollection {
6062

6163
this.disposables.push(vscode.workspace.onDidChangeWorkspaceFolders(e => this.onDidChangeWorkspaceFolders(e)));
6264
this.disposables.push(vscode.workspace.onDidCloseTextDocument(d => this.onDidCloseTextDocument(d)));
65+
66+
this.timeTelemetryCollector = new TimeTelemetryCollector();
6367
}
6468

6569
public activeDocumentChanged(document: vscode.TextDocument): void {

Extension/src/LanguageServer/extension.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ function realActivation(): void {
284284
clients = new ClientCollection();
285285
ui = getUI();
286286

287+
// Log cold start.
288+
const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
289+
if (activeEditor) {
290+
clients.timeTelemetryCollector.setFirstFile(activeEditor.document.uri);
291+
}
292+
287293
// There may have already been registered CustomConfigurationProviders.
288294
// Request for configurations from those providers.
289295
clients.forEach(client => {
@@ -405,6 +411,8 @@ function onDidChangeTextEditorSelection(event: vscode.TextEditorSelectionChangeE
405411
export function processDelayedDidOpen(document: vscode.TextDocument): void {
406412
const client: Client = clients.getClientFor(document.uri);
407413
if (client) {
414+
// Log warm start.
415+
clients.timeTelemetryCollector.setDidOpenTime(document.uri);
408416
if (clients.checkOwnership(client, document)) {
409417
if (!client.TrackedDocuments.has(document)) {
410418
// If not yet tracked, process as a newly opened file. (didOpen is sent to server in client.takeOwnership()).
@@ -1161,6 +1169,7 @@ function handleCrashFileRead(err: NodeJS.ErrnoException | undefined | null, data
11611169
}
11621170

11631171
export function deactivate(): Thenable<void> {
1172+
clients.timeTelemetryCollector.clear();
11641173
console.log("deactivating extension");
11651174
telemetry.logLanguageServerEvent("LanguageServerShutdown");
11661175
clearInterval(intervalTimer);

Extension/src/LanguageServer/protocolFilter.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export function createProtocolFilter(clients: ClientCollection): Middleware {
2626
didOpen: (document, sendMessage) => {
2727
const editor: vscode.TextEditor | undefined = vscode.window.visibleTextEditors.find(e => e.document === document);
2828
if (editor) {
29+
// Log warm start.
30+
clients.timeTelemetryCollector.setDidOpenTime(document.uri);
2931
// If the file was visible editor when we were activated, we will not get a call to
3032
// onDidChangeVisibleTextEditors, so immediately open any file that is visible when we receive didOpen.
3133
// Otherwise, we defer opening the file until it's actually visible.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* --------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All Rights Reserved.
3+
* See 'LICENSE' in the project root for license information.
4+
* ------------------------------------------------------------------------------------------ */
5+
import * as telemetry from '../telemetry';
6+
import * as util from '../common';
7+
import * as vscode from 'vscode';
8+
9+
interface TimeStampSequence {
10+
firstFile?: number; // when the extension is activated by realActivation. Defined only for "cold" start cases.
11+
didOpen: number; // when the file appears in the editor. Defined for "warm" start cases.
12+
setup: number; // when the Intellisense_client constructor is completed
13+
updateRange: number; // when publishDiagnostics & provideSemanticTokens is completed
14+
}
15+
16+
export class TimeTelemetryCollector {
17+
18+
private cachedTimeStamps: Map<string, any> = new Map<string, any>(); // a map of uri's string to TimeStampSequence
19+
20+
public setFirstFile(uri: vscode.Uri): void {
21+
if (util.fileIsCOrCppSource(uri.path)) {
22+
const curTimeStamps: TimeStampSequence = this.getTimeStamp(uri.path);
23+
curTimeStamps.firstFile = new Date().getTime();
24+
this.cachedTimeStamps.set(uri.path, curTimeStamps);
25+
}
26+
}
27+
28+
public setDidOpenTime(uri: vscode.Uri): void {
29+
const curTimeStamps: TimeStampSequence = this.getTimeStamp(uri.path);
30+
curTimeStamps.didOpen = new Date().getTime();
31+
this.cachedTimeStamps.set(uri.path, curTimeStamps);
32+
}
33+
34+
public setSetupTime(uri: vscode.Uri): void {
35+
const curTimeStamps: TimeStampSequence = this.getTimeStamp(uri.path);
36+
curTimeStamps.setup = new Date().getTime();
37+
this.cachedTimeStamps.set(uri.path, curTimeStamps);
38+
if (curTimeStamps.didOpen && curTimeStamps.updateRange) {
39+
this.logTelemetry(uri.path, curTimeStamps);
40+
}
41+
}
42+
43+
public setUpdateRangeTime(uri: vscode.Uri): void {
44+
const curTimeStamps: TimeStampSequence = this.getTimeStamp(uri.path);
45+
if (!curTimeStamps.updateRange) {
46+
curTimeStamps.updateRange = new Date().getTime();
47+
this.cachedTimeStamps.set(uri.path, curTimeStamps);
48+
}
49+
if (curTimeStamps.didOpen && curTimeStamps.setup) {
50+
this.logTelemetry(uri.path, curTimeStamps);
51+
}
52+
}
53+
54+
public clear(): void {
55+
console.log("clearing timestamp log");
56+
this.cachedTimeStamps.clear();
57+
}
58+
59+
private getTimeStamp(uri: string): TimeStampSequence {
60+
return this.cachedTimeStamps.get(uri) ? this.cachedTimeStamps.get(uri) :
61+
{ firstFile: 0, didOpen: 0, setup: 0, updateRange: 0 };
62+
}
63+
64+
private removeTimeStamp(uri: string): void {
65+
this.cachedTimeStamps.delete(uri);
66+
}
67+
68+
private logTelemetry(uri: string, timeStamps: TimeStampSequence): void {
69+
const startTime: number = timeStamps.firstFile ? timeStamps.firstFile : timeStamps.didOpen;
70+
let properties: any = {};
71+
let metrics: any = {
72+
"setupTime": (timeStamps.setup - startTime),
73+
"updateRangeTime": (timeStamps.updateRange - timeStamps.setup),
74+
"totalTime": (timeStamps.updateRange - startTime)
75+
};
76+
if (timeStamps.firstFile) {
77+
properties = { "coldstart": "true" };
78+
metrics = { "activationTime": (timeStamps.didOpen - startTime), ...metrics };
79+
}
80+
telemetry.logLanguageServerEvent("timeStamps", properties, metrics);
81+
82+
this.removeTimeStamp(uri);
83+
}
84+
}

0 commit comments

Comments
 (0)