Skip to content

Commit 8dd2aa5

Browse files
authored
Add more telemetry for project import & workspaces hash (#4177)
1 parent 25370d7 commit 8dd2aa5

File tree

3 files changed

+74
-52
lines changed

3 files changed

+74
-52
lines changed

src/standardLanguageClient.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import * as net from 'net';
44
import * as path from 'path';
5-
import { CancellationToken, CodeActionKind, commands, ConfigurationTarget, DocumentSelector, EventEmitter, ExtensionContext, extensions, languages, Location, ProgressLocation, TextEditor, Uri, ViewColumn, window, workspace } from "vscode";
6-
import { ConfigurationParams, ConfigurationRequest, LanguageClientOptions, Location as LSLocation, MessageType, Position as LSPosition, TextDocumentPositionParams, WorkspaceEdit, StaticFeature, ClientCapabilities, FeatureState } from "vscode-languageclient";
5+
import { CancellationToken, CodeActionKind, commands, ConfigurationTarget, DocumentSelector, EventEmitter, ExtensionContext, extensions, languages, Location, ProgressLocation, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceConfiguration } from "vscode";
6+
import { ConfigurationParams, ConfigurationRequest, LanguageClientOptions, Location as LSLocation, MessageType, Position as LSPosition, TextDocumentPositionParams, WorkspaceEdit, StaticFeature, ClientCapabilities, FeatureState, TelemetryEventNotification } from "vscode-languageclient";
77
import { LanguageClient, StreamInfo } from "vscode-languageclient/node";
88
import { apiManager } from "./apiManager";
99
import * as buildPath from './buildpath';
@@ -336,10 +336,49 @@ export class StandardLanguageClient {
336336
return result;
337337
});
338338

339+
function getJavaSettingsForTelemetry(config: WorkspaceConfiguration) {
340+
// settings whose values we can record
341+
const SETTINGS_BASIC = [
342+
"java.quickfix.showAt", "java.symbols.includeSourceMethodDeclarations",
343+
"java.completion.collapseCompletionItems", "java.completion.guessMethodArguments",
344+
"java.cleanup.actionsOnSave", "java.completion.postfix.enabled",
345+
"java.sharedIndexes.enabled", "java.inlayHints.parameterNames.enabled",
346+
"java.inlayHints.parameterNames.suppressWhenSameNameNumbered",
347+
"java.inlayHints.variableTypes.enabled",
348+
"java.inlayHints.parameterTypes.enabled",
349+
"java.server.launchMode", "java.autobuild.enabled"
350+
];
351+
352+
// settings where we only record their existence
353+
const SETTINGS_CUSTOM = [
354+
"java.settings.url", "java.format.settings.url"
355+
];
356+
357+
let value: any;
358+
const properties = {};
359+
360+
for (const key of SETTINGS_CUSTOM) {
361+
if (config.get(key)) {
362+
properties[key] = true;
363+
}
364+
}
365+
for (const key of SETTINGS_BASIC) {
366+
value = config.get(key);
367+
if (value !== undefined) {
368+
properties[key] = value;
369+
}
370+
}
371+
372+
return properties;
373+
}
374+
339375
this.languageClient.onTelemetry(async (e: TelemetryEvent) => {
340376
apiManager.fireTraceEvent(e);
341377
if (e.name === Telemetry.SERVER_INITIALIZED_EVT) {
342-
return Telemetry.sendTelemetry(Telemetry.STARTUP_EVT, e.properties);
378+
const javaSettings = getJavaSettingsForTelemetry(workspace.getConfiguration());
379+
380+
const properties= { ...e.properties, ...javaSettings };
381+
await Telemetry.sendTelemetry(Telemetry.STARTUP_EVT, properties);
343382
} else if (e.name === Telemetry.LS_ERROR) {
344383
const tags = [];
345384
const exception: string = e?.properties.exception;
@@ -357,7 +396,7 @@ export class StandardLanguageClient {
357396

358397
if (tags.length > 0 || DEBUG || isPrereleaseOrInsiderVersion(context)) {
359398
e.properties['tags'] = tags;
360-
return Telemetry.sendTelemetry(Telemetry.LS_ERROR, e.properties);
399+
await Telemetry.sendTelemetry(Telemetry.LS_ERROR, e.properties);
361400
}
362401
}
363402
});

src/telemetry.ts

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { TelemetryService, getRedHatService } from "@redhat-developer/vscode-redhat-telemetry";
22
import { ExtensionContext, workspace, WorkspaceConfiguration } from "vscode";
3+
import { cyrb53 } from "./utils";
34

45
/**
56
* Wrap vscode-redhat-telemetry to suit vscode-java
@@ -10,7 +11,9 @@ export namespace Telemetry {
1011
export const COMPLETION_EVENT = "textCompletion";
1112
export const SERVER_INITIALIZED_EVT = "java.workspace.initialized";
1213
export const LS_ERROR = "java.ls.error";
14+
1315
let telemetryManager: TelemetryService = null;
16+
let workspaceHash;
1417

1518
/**
1619
* Starts the telemetry service
@@ -22,6 +25,10 @@ export namespace Telemetry {
2225
if (!!telemetryManager) {
2326
throw new Error("The telemetry service for vscode-java has already been started");
2427
}
28+
workspaceHash = cyrb53(workspace.workspaceFolders.map(f => f.uri.toString()).join('|'));
29+
workspace.onDidChangeWorkspaceFolders(() => {
30+
workspaceHash = cyrb53(workspace.workspaceFolders.map(f => f.uri.toString()).join('|'));
31+
});
2532
const redhatService = await getRedHatService(context);
2633
const telemService = await redhatService.getTelemetryService();
2734
telemetryManager = telemService;
@@ -35,58 +42,15 @@ export namespace Telemetry {
3542
* @param data the telemetry data
3643
* @throws Error if the telemetry service has not been started yet
3744
*/
38-
export async function sendTelemetry(eventName: string, data?: any): Promise<void> {
45+
export async function sendTelemetry(eventName: string, data?: object): Promise<void> {
3946
if (!telemetryManager) {
4047
throw new Error("The telemetry service for vscode-java has not been started yet");
4148
}
42-
const javaSettings = getJavaSettingsForTelemetry(workspace.getConfiguration());
43-
44-
let properties: any;
45-
if (eventName === STARTUP_EVT) {
46-
properties= { ...data, ...javaSettings };
47-
} else {
48-
properties= { ...data};
49-
}
5049

51-
return telemetryManager.send({
50+
const event = {
5251
name: eventName,
53-
properties
54-
});
55-
}
56-
57-
function getJavaSettingsForTelemetry(config: WorkspaceConfiguration) {
58-
// settings whose values we can record
59-
const SETTINGS_BASIC = [
60-
"java.quickfix.showAt", "java.symbols.includeSourceMethodDeclarations",
61-
"java.completion.collapseCompletionItems", "java.completion.guessMethodArguments",
62-
"java.cleanup.actionsOnSave", "java.completion.postfix.enabled",
63-
"java.sharedIndexes.enabled", "java.inlayHints.parameterNames.enabled",
64-
"java.inlayHints.parameterNames.suppressWhenSameNameNumbered",
65-
"java.inlayHints.variableTypes.enabled",
66-
"java.inlayHints.parameterTypes.enabled",
67-
"java.server.launchMode", "java.autobuild.enabled"
68-
];
69-
70-
// settings where we only record their existence
71-
const SETTINGS_CUSTOM = [
72-
"java.settings.url", "java.format.settings.url"
73-
];
74-
75-
let value: any;
76-
const properties = {};
77-
78-
for (const key of SETTINGS_CUSTOM) {
79-
if (config.get(key)) {
80-
properties[key] = true;
81-
}
82-
}
83-
for (const key of SETTINGS_BASIC) {
84-
value = config.get(key);
85-
if (value !== undefined) {
86-
properties[key] = value;
87-
}
88-
}
89-
90-
return properties;
52+
properties: { workspaceHash, ...data}
53+
};
54+
return telemetryManager.send(event);
9155
}
9256
}

src/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,22 @@ export function isPreReleaseVersion(context: ExtensionContext | string): boolean
391391
export function isInsiderEditor(): boolean {
392392
return version.includes("insider");
393393
}
394+
/*
395+
* cyrb53 (c) 2018 bryc (github.com/bryc)
396+
* Public domain (or MIT if needed). Attribution appreciated.
397+
* A fast and simple 53-bit string hash function with decent collision resistance.
398+
* Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
399+
*/
400+
export function cyrb53 (str, seed = 0) {
401+
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
402+
for (let i = 0, ch; i < str.length; i++) {
403+
ch = str.charCodeAt(i);
404+
h1 = Math.imul(h1 ^ ch, 2654435761);
405+
h2 = Math.imul(h2 ^ ch, 1597334677);
406+
}
407+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
408+
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
409+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
410+
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
411+
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
412+
};

0 commit comments

Comments
 (0)