-
Notifications
You must be signed in to change notification settings - Fork 43
feat: add telemetry service infrastructure (Phase A core) #919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8a3c28d
feat: add telemetry service infrastructure (Phase A core)
EhabY 9926465
refactor(telemetry): tighten event/service/trace and tests
EhabY 73a5a3a
refactor(telemetry): split context, move emit utilities, tighten desc…
EhabY 79cd3f6
Address review comments
EhabY 3ab123c
refactor(telemetry): OTel-Traces shape and error isolation
EhabY 81ee22f
refactor(telemetry): hide setting, drop time() alias
EhabY 5b9184b
refactor(telemetry): reserve framework keys, await dispose
EhabY 9100773
fix(telemetry): freeze trace level, harden NOOP_SPAN, share span options
EhabY File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import * as os from "node:os"; | ||
| import * as vscode from "vscode"; | ||
|
|
||
| import { toError } from "../error/errorUtils"; | ||
|
|
||
| /** Telemetry level, mirrors `coder.telemetry.level`. Ordered: off < local. */ | ||
| export type TelemetryLevel = "off" | "local"; | ||
|
|
||
| /** Caller properties. `result` is framework-managed on traced events. */ | ||
| export type CallerProperties = Record<string, string> & { result?: never }; | ||
|
|
||
| /** Caller measurements. `durationMs` is framework-managed on traced events. */ | ||
| export type CallerMeasurements = Record<string, number> & { | ||
| durationMs?: never; | ||
| }; | ||
|
|
||
| /** Session-stable resource attributes. Field names are inspired by OTel | ||
| * resource attributes; they are camelCase TypeScript and not a 1:1 mapping. */ | ||
| export interface SessionContext { | ||
| readonly extensionVersion: string; | ||
| readonly machineId: string; | ||
| readonly sessionId: string; | ||
| readonly osType: string; | ||
| readonly osVersion: string; | ||
| readonly hostArch: string; | ||
| readonly platformName: string; | ||
| readonly platformVersion: string; | ||
| } | ||
|
|
||
| /** Per-event context: session attributes plus the current deployment URL. */ | ||
| export interface TelemetryContext extends SessionContext { | ||
| readonly deploymentUrl: string; | ||
| } | ||
|
|
||
| export interface TelemetryEvent { | ||
| readonly eventId: string; | ||
| readonly eventName: string; | ||
| readonly timestamp: string; | ||
| readonly eventSequence: number; | ||
|
|
||
| readonly context: TelemetryContext; | ||
|
|
||
| readonly properties: Readonly<Record<string, string>>; | ||
| readonly measurements: Readonly<Record<string, number>>; | ||
|
|
||
| /** Shared by all events in a trace. Maps to OTel `trace_id`. */ | ||
| readonly traceId?: string; | ||
| /** Set on phase children only. Equals the parent event's `eventId`. Maps to OTel `parent_span_id`. */ | ||
| readonly parentEventId?: string; | ||
|
|
||
| readonly error?: Readonly<{ | ||
| message: string; | ||
| type?: string; | ||
| code?: string; | ||
| }>; | ||
| } | ||
|
|
||
| /** | ||
| * Sink for telemetry events. `write` is sync and must buffer in memory; I/O | ||
| * happens in `flush`/`dispose`. The service filters by `minLevel`; sinks can | ||
| * still self-gate on other signals (e.g. deployment URL). | ||
| */ | ||
| export interface TelemetrySink { | ||
| readonly name: string; | ||
| readonly minLevel: TelemetryLevel; | ||
| write(event: TelemetryEvent): void; | ||
| flush(): Promise<void>; | ||
| dispose(): Promise<void>; | ||
| } | ||
|
|
||
| /** Build session attributes. `extensionVersion` falls back to `"unknown"`. */ | ||
| export function buildSession(ctx: vscode.ExtensionContext): SessionContext { | ||
| // "unknown" only for malformed package.json or test fixtures missing `version`. | ||
| const packageJson = ctx.extension.packageJSON as { version?: unknown }; | ||
| const extensionVersion = | ||
| typeof packageJson.version === "string" ? packageJson.version : "unknown"; | ||
|
EhabY marked this conversation as resolved.
|
||
|
|
||
| return { | ||
| extensionVersion, | ||
| machineId: vscode.env.machineId, | ||
| sessionId: vscode.env.sessionId, | ||
| osType: detectOsType(), | ||
| osVersion: os.release(), | ||
| hostArch: process.arch, | ||
| platformName: vscode.env.appName, | ||
| platformVersion: vscode.version, | ||
| }; | ||
| } | ||
|
|
||
| /** Normalize a thrown value into the event's `error` block. */ | ||
| export function buildErrorBlock( | ||
| value: unknown, | ||
| ): NonNullable<TelemetryEvent["error"]> { | ||
| const err = toError(value); | ||
| const rawCode = (value as { code?: unknown } | null | undefined)?.code; | ||
| const hasCode = typeof rawCode === "string" || typeof rawCode === "number"; | ||
| return { | ||
| message: err.message, | ||
| ...(err.name && err.name !== "Error" && { type: err.name }), | ||
| ...(hasCode && { code: String(rawCode) }), | ||
| }; | ||
| } | ||
|
|
||
| // Node uses "win32" on Windows; OTel's os.type is "windows". | ||
| function detectOsType(): string { | ||
| return process.platform === "win32" ? "windows" : process.platform; | ||
|
EhabY marked this conversation as resolved.
|
||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.