@@ -91,22 +91,26 @@ const INTERESTED_REQUESTS: Set<string> = new Set([
9191const CANCELLATION_CODE : number = - 32800 ; // report such error if the request is cancelled.
9292const CONTENT_MODIFIED_CODE : number = - 32801 ; // report such error if semantic token request is outdated while content modified.
9393const INTERNAL_ERROR_CODE : number = - 32603 ; // Internal Error.
94+ let lspUsageStats : LSPUsageStats ;
9495async function traceLSPPerformance ( javaExt : vscode . Extension < any > ) {
9596 const javaExtVersion = javaExt . packageJSON ?. version ;
9697 const isPreReleaseVersion = / ^ \d + \. \d + \. \d { 10 } / . test ( javaExtVersion ) ;
9798 const redHatTelemetryEnabled = workspace . getConfiguration ( 'redhat.telemetry' ) . get ( 'enabled' , false ) ;
9899 const isTreatment = ! isPreReleaseVersion &&
99100 ( redHatTelemetryEnabled || await getExpService ( ) ?. getTreatmentVariableAsync ( TreatmentVariables . VSCodeConfig , TreatmentVariables . JavaCompletionSampling , true /*checkCache*/ ) ) ;
100101 const sampling : string = isPreReleaseVersion ? "pre-release" : ( isTreatment ? "sampling" : "" ) ;
102+ if ( ! isPreReleaseVersion && ! isTreatment ) {
103+ return ;
104+ }
105+
106+ lspUsageStats = new LSPUsageStats ( javaExtVersion , sampling ) ;
101107 // Trace the interested LSP requests performance
102108 javaExt . exports ?. onDidRequestEnd ?.( ( traceEvent : any ) => {
103- if ( ! isPreReleaseVersion && ! isTreatment ) {
104- return ;
105- }
106-
109+ lspUsageStats . addRequest ( traceEvent . type ) ;
107110 // Trace the timeout requests
108111 if ( traceEvent . duration > 5000
109112 || ( traceEvent . duration > 1000 && RESPONSIVE_REQUESTS . has ( traceEvent . type ) ) ) {
113+ lspUsageStats . addTimeoutRequest ( traceEvent . type ) ;
110114 sendInfo ( "" , {
111115 name : "lsp.timeout" ,
112116 kind : escapeLspRequestName ( traceEvent . type ) ,
@@ -124,6 +128,7 @@ async function traceLSPPerformance(javaExt: vscode.Extension<any>) {
124128 return ;
125129 }
126130
131+ lspUsageStats . addErrorRequest ( traceEvent . type ) ;
127132 // See https://github.com/eclipse-lsp4j/lsp4j/commit/bf22871f4e669a2d7fd97ce046cb50903aa68120#diff-3b3e5d6517a47e0459195078645a0837aafa4d4520fe79b1cb1922a749074748
128133 // lsp4j will wrap the error message as "Internal error."
129134 // when it encounters an uncaught exception from jdt language server.
@@ -166,7 +171,10 @@ async function traceLSPPerformance(javaExt: vscode.Extension<any>) {
166171 remark : sampling ,
167172 data : redactDataProperties ( traceEvent . data ) ,
168173 } ) ;
169- return ;
174+ }
175+
176+ if ( traceEvent . resultLength === 0 ) {
177+ lspUsageStats . addNoResultRequest ( traceEvent . type ) ;
170178 }
171179 } ) ;
172180}
@@ -287,3 +295,64 @@ function resolveActualCause(callstack: any): Exception | undefined {
287295
288296 return ;
289297}
298+
299+ export function sendLSPUsageStats ( ) {
300+ if ( lspUsageStats ) {
301+ lspUsageStats . sendStats ( ) ;
302+ }
303+ }
304+
305+ class LSPUsageStats {
306+ private totalRequests : any = { } ;
307+ private timeoutRequests : any = { } ;
308+ private errorRequests : any = { } ;
309+ private noResultRequests : any = { } ;
310+
311+ public constructor ( readonly javaExtVersion : string , readonly sampling : string ) {
312+ }
313+
314+ public addRequest ( type : string ) {
315+ this . totalRequests [ type ] = ( this . totalRequests [ type ] || 0 ) + 1 ;
316+ }
317+
318+ public addTimeoutRequest ( type : string ) {
319+ this . timeoutRequests [ type ] = ( this . timeoutRequests [ type ] || 0 ) + 1 ;
320+ }
321+
322+ public addErrorRequest ( type : string ) {
323+ this . errorRequests [ type ] = ( this . errorRequests [ type ] || 0 ) + 1 ;
324+ }
325+
326+ public addNoResultRequest ( type : string ) {
327+ this . noResultRequests [ type ] = ( this . noResultRequests [ type ] || 0 ) + 1 ;
328+ }
329+
330+ public sendStats ( ) {
331+ if ( Object . keys ( this . totalRequests ) . length ) {
332+ const data : any = { } ;
333+ for ( const key of Object . keys ( this . totalRequests ) ) {
334+ const simpleKey = this . getSimpleKey ( key ) ;
335+ data [ simpleKey ] = [ this . totalRequests [ key ] ,
336+ this . timeoutRequests [ key ] || 0 ,
337+ this . errorRequests [ key ] || 0 ,
338+ this . noResultRequests [ key ] || 0 ] ;
339+ }
340+ sendInfo ( "" , {
341+ name : "lsp.aggregate" ,
342+ javaversion : this . javaExtVersion ,
343+ remark : this . sampling ,
344+ data : JSON . stringify ( data ) ,
345+ } ) ;
346+ }
347+ }
348+
349+ private getSimpleKey ( key : string ) : string {
350+ if ( key . startsWith ( "workspace/executeCommand/" ) ) {
351+ return key . replace ( "workspace/executeCommand/" , "we/" ) ;
352+ }
353+ if ( key . startsWith ( "textDocument/" ) ) {
354+ return key . replace ( "textDocument/" , "td/" ) ;
355+ }
356+ return key ;
357+ }
358+ }
0 commit comments