Skip to content

Commit b2cb18e

Browse files
committed
refactor(telemetry): pull settings into src/settings, simplify sink and tests
Move readTelemetryLevel and readLocalJsonlConfig (with the setting key constants and defaults) into src/settings/telemetry.ts, matching the existing notifications and cli settings pattern. Both functions take a WorkspaceConfiguration argument so they are easy to test. LocalJsonlSink keeps its static start() factory but the constructor is now side-effect-free: it just assigns fields. start() is the single place that reads the config, subscribes the watcher, schedules the flush timer, and kicks off cleanup. The class implements vscode.Disposable explicitly. Tighten comments on the sink and on cleanupFiles. Inline #fileName into #doFlush since it had only one caller. Tests: per-test setup() harness instead of beforeEach-installed helpers. Module-level state is gone, all setup happens inside each test through setup(), and afterEach disposes any active sinks. The "warns once" log-side-effect assertion is dropped from the buffer overflow test (the file content already proves the behavior). fileCleanup tests use path.basename instead of split("/") for cross-platform safety.
1 parent 5e640dc commit b2cb18e

6 files changed

Lines changed: 272 additions & 282 deletions

File tree

src/settings/telemetry.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import type { WorkspaceConfiguration } from "vscode";
2+
3+
import type { TelemetryLevel } from "../telemetry/event";
4+
5+
export const TELEMETRY_LEVEL_SETTING = "coder.telemetry.level";
6+
export const LOCAL_JSONL_SETTING = "coder.telemetry.localJsonl";
7+
8+
/** Telemetry level. Falls back to `local` for any invalid value. */
9+
export function readTelemetryLevel(
10+
cfg: Pick<WorkspaceConfiguration, "get">,
11+
): TelemetryLevel {
12+
const value = cfg.get<string>(TELEMETRY_LEVEL_SETTING);
13+
return value === "off" || value === "local" ? value : "local";
14+
}
15+
16+
export interface LocalJsonlConfig {
17+
flushIntervalMs: number;
18+
flushBatchSize: number;
19+
bufferLimit: number;
20+
maxFileBytes: number;
21+
maxAgeDays: number;
22+
maxTotalBytes: number;
23+
}
24+
25+
export const LOCAL_JSONL_DEFAULTS: LocalJsonlConfig = {
26+
flushIntervalMs: 15_000,
27+
flushBatchSize: 100,
28+
bufferLimit: 500,
29+
maxFileBytes: 5 * 1024 * 1024,
30+
maxAgeDays: 30,
31+
maxTotalBytes: 100 * 1024 * 1024,
32+
};
33+
34+
/** Reads the local JSONL sink config, defaulting any missing or invalid
35+
* field. Each field must be a positive number to override the default. */
36+
export function readLocalJsonlConfig(
37+
cfg: Pick<WorkspaceConfiguration, "get">,
38+
): LocalJsonlConfig {
39+
const raw = cfg.get(LOCAL_JSONL_SETTING);
40+
const obj =
41+
raw && typeof raw === "object" ? (raw as Record<string, unknown>) : {};
42+
return {
43+
flushIntervalMs: positiveNumber(
44+
obj.flushIntervalMs,
45+
LOCAL_JSONL_DEFAULTS.flushIntervalMs,
46+
),
47+
flushBatchSize: positiveNumber(
48+
obj.flushBatchSize,
49+
LOCAL_JSONL_DEFAULTS.flushBatchSize,
50+
),
51+
bufferLimit: positiveNumber(
52+
obj.bufferLimit,
53+
LOCAL_JSONL_DEFAULTS.bufferLimit,
54+
),
55+
maxFileBytes: positiveNumber(
56+
obj.maxFileBytes,
57+
LOCAL_JSONL_DEFAULTS.maxFileBytes,
58+
),
59+
maxAgeDays: positiveNumber(obj.maxAgeDays, LOCAL_JSONL_DEFAULTS.maxAgeDays),
60+
maxTotalBytes: positiveNumber(
61+
obj.maxTotalBytes,
62+
LOCAL_JSONL_DEFAULTS.maxTotalBytes,
63+
),
64+
};
65+
}
66+
67+
function positiveNumber(value: unknown, fallback: number): number {
68+
return typeof value === "number" && value > 0 ? value : fallback;
69+
}

src/telemetry/service.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import * as vscode from "vscode";
22

33
import { watchConfigurationChanges } from "../configWatcher";
44
import { type Logger } from "../logging/logger";
5+
import {
6+
TELEMETRY_LEVEL_SETTING,
7+
readTelemetryLevel,
8+
} from "../settings/telemetry";
59

610
import {
711
buildSession,
@@ -15,13 +19,14 @@ import {
1519
} from "./event";
1620
import { NOOP_SPAN, type Span } from "./span";
1721

18-
const TELEMETRY_LEVEL_SETTING = "coder.telemetry.level";
19-
2022
const LEVEL_ORDER: Readonly<Record<TelemetryLevel, number>> = {
2123
off: 0,
2224
local: 1,
2325
};
2426

27+
const readLevel = (): TelemetryLevel =>
28+
readTelemetryLevel(vscode.workspace.getConfiguration());
29+
2530
/** Trace context shared by all events in one trace. */
2631
interface SpanOptions {
2732
traceId: string;
@@ -280,13 +285,3 @@ export class TelemetryService implements vscode.Disposable {
280285
}
281286
}
282287

283-
function readLevel(): TelemetryLevel {
284-
const value = vscode.workspace
285-
.getConfiguration()
286-
.get<string>(TELEMETRY_LEVEL_SETTING);
287-
return isTelemetryLevel(value) ? value : "local";
288-
}
289-
290-
function isTelemetryLevel(value: unknown): value is TelemetryLevel {
291-
return value === "off" || value === "local";
292-
}

0 commit comments

Comments
 (0)