Skip to content

Commit

Permalink
Track the LSP request data from syntax server (#3278)
Browse files Browse the repository at this point in the history
- Track the LSP request data from syntax server
- Move registerCodeCompletionTelemetryListener just before language
  client is initialized

Co-authored-by: Jinbo Wang <[email protected]>
Co-authored-by: Roland Grunberg <[email protected]>
  • Loading branch information
testforstephen and rgrunber authored Oct 4, 2023
1 parent 2e38c4e commit fa82082
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 24 deletions.
4 changes: 4 additions & 0 deletions src/TracingLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ export const onDidRequestEnd: Event<TraceEvent> = requestEndEventEmitter.event;

export class TracingLanguageClient extends LanguageClient {
private isStarted: boolean = false;
private isSyntaxServer: boolean = false;

constructor(id: string, name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean) {
super(id, name, serverOptions, clientOptions, forceDebug);
this.isSyntaxServer = name?.includes("Syntax Server");
}

start(): Promise<void> {
Expand Down Expand Up @@ -118,6 +120,7 @@ export class TracingLanguageClient extends LanguageClient {
duration,
resultLength,
data,
fromSyntaxServer: !!this.isSyntaxServer,
});
}

Expand All @@ -128,6 +131,7 @@ export class TracingLanguageClient extends LanguageClient {
duration,
error,
data,
fromSyntaxServer: !!this.isSyntaxServer,
});
}

Expand Down
4 changes: 4 additions & 0 deletions src/extension.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ export interface TraceEvent {
* Additional data properties, such as the completion trigger context.
*/
data?: any;
/**
* Whether the response is from the syntax server.
*/
fromSyntaxServer?: boolean;
}

export interface SourceInvalidatedEvent {
Expand Down
23 changes: 21 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import * as fse from 'fs-extra';
import * as os from 'os';
import * as path from 'path';
import { CodeActionContext, commands, ConfigurationTarget, Diagnostic, env, EventEmitter, ExtensionContext, extensions, IndentAction, InputBoxOptions, languages, RelativePattern, TextDocument, UIKind, Uri, ViewColumn, window, workspace, WorkspaceConfiguration, ProgressLocation, Position, Selection, Range } from 'vscode';
import { CancellationToken, CodeActionParams, CodeActionRequest, Command, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient';
import { CancellationToken, CodeActionParams, CodeActionRequest, Command, CompletionRequest, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient';
import { LanguageClient } from 'vscode-languageclient/node';
import { apiManager } from './apiManager';
import { ClientErrorHandler } from './clientErrorHandler';
import { Commands } from './commands';
import { ClientStatus, ExtensionAPI } from './extension.api';
import { ClientStatus, ExtensionAPI, TraceEvent } from './extension.api';
import * as fileEventHandler from './fileEventHandler';
import { getSharedIndexCache, HEAP_DUMP_LOCATION, prepareExecutable } from './javaServerStarter';
import { initializeLogFile, logger } from './log';
Expand Down Expand Up @@ -273,6 +273,7 @@ export async function activate(context: ExtensionContext): Promise<ExtensionAPI>
};

apiManager.initialize(requirements, serverMode);
registerCodeCompletionTelemetryListener();
resolve(apiManager.getApiInstance());
// the promise is resolved
// no need to pass `resolve` into any code past this point,
Expand Down Expand Up @@ -983,6 +984,24 @@ async function cleanJavaWorkspaceStorage() {
}
}

export function registerCodeCompletionTelemetryListener() {
apiManager.getApiInstance().onDidRequestEnd((traceEvent: TraceEvent) => {
if (traceEvent.type === CompletionRequest.method) {
// Exclude the invalid completion requests.
if (!traceEvent.resultLength) {
return;
}
const props = {
duration: Math.round(traceEvent.duration * 100) / 100,
resultLength: traceEvent.resultLength || 0,
error: !!traceEvent.error,
fromSyntaxServer: !!traceEvent.fromSyntaxServer,
};
return Telemetry.sendTelemetry(Telemetry.COMPLETION_EVENT, props);
}
});
}

function registerOutOfMemoryDetection(storagePath: string) {
const heapDumpFolder = getHeapDumpFolderFromSettings() || storagePath;
chokidar.watch(`${heapDumpFolder}/java_*.hprof`, { ignoreInitial: true }).on('add', path => {
Expand Down
24 changes: 3 additions & 21 deletions src/standardLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import * as net from 'net';
import * as path from 'path';
import { CancellationToken, CodeActionKind, commands, ConfigurationTarget, DocumentSelector, EventEmitter, ExtensionContext, extensions, languages, Location, ProgressLocation, TextEditor, Uri, ViewColumn, window, workspace } from "vscode";
import { ConfigurationParams, ConfigurationRequest, LanguageClientOptions, Location as LSLocation, MessageType, Position as LSPosition, TextDocumentPositionParams, WorkspaceEdit, CompletionRequest } from "vscode-languageclient";
import { ConfigurationParams, ConfigurationRequest, LanguageClientOptions, Location as LSLocation, MessageType, Position as LSPosition, TextDocumentPositionParams, WorkspaceEdit } from "vscode-languageclient";
import { LanguageClient, StreamInfo } from "vscode-languageclient/node";
import { apiManager } from "./apiManager";
import * as buildPath from './buildpath';
import { javaRefactorKinds, RefactorDocumentProvider } from "./codeActionProvider";
import { Commands } from "./commands";
import { ClientStatus, TraceEvent } from "./extension.api";
import { ClientStatus } from "./extension.api";
import * as fileEventHandler from './fileEventHandler';
import { gradleCodeActionMetadata, GradleCodeActionProvider } from "./gradle/gradleCodeActionProvider";
import { awaitServerConnection, prepareExecutable, DEBUG } from "./javaServerStarter";
Expand All @@ -34,7 +34,7 @@ import { askForProjects, projectConfigurationUpdate, upgradeGradle } from "./sta
import { TracingLanguageClient } from './TracingLanguageClient';
import { TypeHierarchyDirection, TypeHierarchyItem } from "./typeHierarchy/protocol";
import { typeHierarchyTree } from "./typeHierarchy/typeHierarchyTree";
import { getAllJavaProjects, getJavaConfig, getJavaConfiguration } from "./utils";
import { getAllJavaProjects, getJavaConfiguration } from "./utils";
import { Telemetry } from "./telemetry";
import { TelemetryEvent } from "@redhat-developer/vscode-redhat-telemetry/lib";
import { registerDocumentValidationListener } from './diagnostic';
Expand Down Expand Up @@ -147,7 +147,6 @@ export class StandardLanguageClient {
// Disable the client-side snippet provider since LS is ready.
snippetCompletionProvider.dispose();
registerDocumentValidationListener(context, this.languageClient);
registerCodeCompletionTelemetryListener();
commands.executeCommand('setContext', 'javaLSReady', true);
break;
case 'Started':
Expand Down Expand Up @@ -814,21 +813,4 @@ export async function applyWorkspaceEdit(workspaceEdit: WorkspaceEdit, languageC
} else {
return Promise.resolve(true);
}
}

export function registerCodeCompletionTelemetryListener() {
apiManager.getApiInstance().onDidRequestEnd((traceEvent: TraceEvent) => {
if (traceEvent.type === CompletionRequest.method) {
// Exclude the invalid completion requests.
if (!traceEvent.resultLength) {
return;
}
const props = {
duration: Math.round(traceEvent.duration * 100) / 100,
resultLength: traceEvent.resultLength || 0,
error: !!traceEvent.error,
};
return Telemetry.sendTelemetry(Telemetry.COMPLETION_EVENT, props);
}
});
}
3 changes: 2 additions & 1 deletion src/syntaxLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ServerMode } from "./settings";
import { snippetCompletionProvider } from "./snippetCompletionProvider";
import { getJavaConfig } from "./utils";
import { DEBUG } from "./javaServerStarter";
import { TracingLanguageClient } from "./TracingLanguageClient";

const extensionName = "Language Support for Java (Syntax Server)";

Expand Down Expand Up @@ -60,7 +61,7 @@ export class SyntaxLanguageClient {
}

if (serverOptions) {
this.languageClient = new LanguageClient('java', extensionName, serverOptions, newClientOptions, DEBUG);
this.languageClient = new TracingLanguageClient('java', extensionName, serverOptions, newClientOptions, DEBUG);
}

this.status = ClientStatus.initialized;
Expand Down

0 comments on commit fa82082

Please sign in to comment.