Skip to content

Commit

Permalink
Merge pull request #649 from Shopify/vs/send_configuration_telemetry
Browse files Browse the repository at this point in the history
Send configuration telemetry
  • Loading branch information
vinistock authored Jun 30, 2023
2 parents 66ef5bb + 9089d0f commit 85e1048
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export async function activate(context: vscode.ExtensionContext) {
await ruby.activateRuby();

const telemetry = new Telemetry(context);
await telemetry.sendConfigurationEvents();

testController = new TestController(
context,
vscode.workspace.workspaceFolders![0].uri.fsPath,
Expand Down
66 changes: 64 additions & 2 deletions src/telemetry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as vscode from "vscode";

export interface TelemetryEvent {
interface RequestEvent {
request: string;
requestTime: number;
lspVersion: string;
Expand All @@ -13,6 +13,16 @@ export interface TelemetryEvent {
yjitEnabled: boolean;
}

export interface ConfigurationEvent {
namespace: string;
field: string;
value: string;
}

export type TelemetryEvent = RequestEvent | ConfigurationEvent;

const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;

export interface TelemetryApi {
sendEvent(event: TelemetryEvent): Promise<void>;
}
Expand All @@ -26,8 +36,11 @@ class DevelopmentApi implements TelemetryApi {

export class Telemetry {
private api?: TelemetryApi;
private context: vscode.ExtensionContext;

constructor(context: vscode.ExtensionContext, api?: TelemetryApi) {
this.context = context;

if (context.extensionMode === vscode.ExtensionMode.Development && !api) {
this.api = new DevelopmentApi();
} else {
Expand All @@ -37,8 +50,57 @@ export class Telemetry {

async sendEvent(event: TelemetryEvent) {
if (await this.initialize()) {
return this.api!.sendEvent(event);
this.api!.sendEvent(event);
}
}

async sendConfigurationEvents() {
const lastConfigurationTelemetry: number | undefined =
this.context.globalState.get("rubyLsp.lastConfigurationTelemetry");

if (
lastConfigurationTelemetry &&
Date.now() - lastConfigurationTelemetry <= ONE_DAY_IN_MS
) {
return;
}

const promises: Promise<void>[] = [
{ namespace: "workbench", field: "colorTheme" },
{ namespace: "rubyLsp", field: "enableExperimentalFeatures" },
{ namespace: "rubyLsp", field: "yjit" },
{ namespace: "rubyLsp", field: "rubyVersionManager" },
{ namespace: "rubyLsp", field: "formatter" },
].map(({ namespace, field }) => {
return this.sendEvent({
namespace,
field,
value: (
vscode.workspace.getConfiguration(namespace).get(field) ?? ""
).toString(),
});
});

const enabledFeatures = vscode.workspace
.getConfiguration("rubyLsp")
.get("enabledFeatures")!;

Object.entries(enabledFeatures).forEach(([field, value]) => {
promises.push(
this.sendEvent({
namespace: "rubyLsp.enabledFeatures",
field,
value: value.toString(),
})
);
});

await Promise.all(promises);

this.context.globalState.update(
"rubyLsp.lastConfigurationTelemetry",
Date.now()
);
}

private async initialize(): Promise<boolean> {
Expand Down
35 changes: 34 additions & 1 deletion src/test/suite/telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import * as assert from "assert";

import * as vscode from "vscode";

import { Telemetry, TelemetryApi, TelemetryEvent } from "../../telemetry";
import {
Telemetry,
TelemetryApi,
TelemetryEvent,
ConfigurationEvent,
} from "../../telemetry";

class FakeApi implements TelemetryApi {
public sentEvents: TelemetryEvent[];
Expand Down Expand Up @@ -65,4 +70,32 @@ suite("Telemetry", () => {
await telemetry.sendEvent(event);
assert.strictEqual(api.sentEvents[0], event);
});

test("Send configuration events emits telemetry for relevant configurations", async () => {
const api = new FakeApi();
const telemetry = new Telemetry(
{
extensionMode: vscode.ExtensionMode.Production,
globalState: {
get: () => undefined,
update: () => Promise.resolve(),
} as unknown,
} as vscode.ExtensionContext,
api
);

await telemetry.sendConfigurationEvents();
const featureConfigurations = vscode.workspace
.getConfiguration("rubyLsp")
.get("enabledFeatures")!;

const expectedNumberOfEvents =
5 + Object.keys(featureConfigurations).length;

assert.strictEqual(api.sentEvents.length, expectedNumberOfEvents);

api.sentEvents.forEach((event) => {
assert.strictEqual(typeof (event as ConfigurationEvent).value, "string");
});
});
});

0 comments on commit 85e1048

Please sign in to comment.