Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/otel/common/otelService.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { createServiceIdentifier } from '../../../util/common/services';
7
import type { Event } from '../../../util/vs/base/common/event';
8
import type { OTelConfig } from './otelConfig';
9
10
export const IOTelService = createServiceIdentifier<IOTelService>('IOTelService');
11
12
/**
13
* Serializable trace context for cross-boundary span propagation.
14
*/
15
export interface TraceContext {
16
readonly traceId: string;
17
readonly spanId: string;
18
/**
19
* W3C trace flags from the source span context (e.g. `0x01` for sampled). Optional
20
* because not all impls preserve it; consumers that build a W3C `traceparent` should
21
* fall back to a sampled value when unset.
22
*/
23
readonly traceFlags?: number;
24
/** W3C tracestate serialized as a comma-separated key=value list, when present. */
25
readonly traceState?: string;
26
}
27
28
/**
29
* Abstracts the OpenTelemetry SDK so consumers don't import OTel directly.
30
* When disabled, all methods are no-ops with zero overhead.
31
*/
32
export interface IOTelService {
33
readonly _serviceBrand: undefined;
34
readonly config: OTelConfig;
35
36
/**
37
* Start a new span. Returns a handle to set attributes and end the span.
38
* If OTel is disabled, returns a no-op handle.
39
*/
40
startSpan(name: string, options?: SpanOptions): ISpanHandle;
41
42
/**
43
* Start a span and set it as active context so child spans are parented.
44
* Calls `fn` within the active span context.
45
*/
46
startActiveSpan<T>(name: string, options: SpanOptions, fn: (span: ISpanHandle) => Promise<T>): Promise<T>;
47
48
/**
49
* Get the trace context (traceId + spanId) of the currently active span.
50
* Returns undefined if no span is active or OTel is disabled.
51
*/
52
getActiveTraceContext(): TraceContext | undefined;
53
54
/**
55
* Store a trace context for later retrieval, keyed by a string ID.
56
* Used to propagate context across async boundaries (e.g., subagent invocations).
57
*/
58
storeTraceContext(key: string, context: TraceContext): void;
59
60
/**
61
* Retrieve and remove a previously stored trace context by key.
62
*/
63
getStoredTraceContext(key: string): TraceContext | undefined;
64
65
/**
66
* Run a function with a remote trace context set as active, without creating a span.
67
* Child spans created inside `fn` will be parented to the given trace context.
68
*/
69
runWithTraceContext<T>(traceContext: TraceContext, fn: () => Promise<T>): Promise<T>;
70
71
/**
72
* Record a histogram metric value.
73
*/
74
recordMetric(name: string, value: number, attributes?: Record<string, string | number | boolean>): void;
75
76
/**
77
* Increment a counter metric.
78
*/
79
incrementCounter(name: string, value?: number, attributes?: Record<string, string | number | boolean>): void;
80
81
/**
82
* Emit an OTel log record / event.
83
*/
84
emitLogRecord(body: string, attributes?: Record<string, unknown>): void;
85
86
/**
87
* Force flush all pending telemetry data.
88
*/
89
flush(): Promise<void>;
90
91
/**
92
* Gracefully shut down the OTel SDK.
93
*/
94
shutdown(): Promise<void>;
95
96
/**
97
* Inject an externally-created completed span into the OTel service's event stream.
98
* The span will fire `onDidCompleteSpan` (for the debug panel) but will NOT be
99
* exported via the OTLP exporter (the source system handles its own export).
100
*/
101
injectCompletedSpan(span: ICompletedSpanData): void;
102
103
/**
104
* Fires when any span ends, providing a serializable snapshot of the span's data.
105
* Used by the debug panel to react to completed spans without depending on the OTel SDK.
106
*/
107
readonly onDidCompleteSpan: Event<ICompletedSpanData>;
108
109
/**
110
* Fires synchronously when a span event is emitted via `ISpanHandle.addEvent()`.
111
* Enables real-time streaming of in-flight span events (e.g., user messages)
112
* without waiting for the span to complete.
113
*/
114
readonly onDidEmitSpanEvent: Event<ISpanEventData>;
115
}
116
117
export const enum SpanKind {
118
INTERNAL = 0,
119
CLIENT = 2,
120
}
121
122
export const enum SpanStatusCode {
123
UNSET = 0,
124
OK = 1,
125
ERROR = 2,
126
}
127
128
export interface SpanOptions {
129
kind?: SpanKind;
130
attributes?: Record<string, string | number | boolean | string[]>;
131
/** When set, the span will be created as a child of this remote trace context. */
132
parentTraceContext?: TraceContext;
133
}
134
135
/**
136
* Lightweight handle for a span, independent of the OTel SDK types.
137
*/
138
export interface ISpanHandle {
139
setAttribute(key: string, value: string | number | boolean | string[]): void;
140
setAttributes(attrs: Record<string, string | number | boolean | string[] | undefined>): void;
141
setStatus(code: SpanStatusCode, message?: string): void;
142
recordException(error: unknown): void;
143
/**
144
* Add a named event to this span with optional attributes.
145
* This fires `IOTelService.onDidEmitSpanEvent` synchronously.
146
*/
147
addEvent(name: string, attributes?: Record<string, string | number | boolean | string[]>): void;
148
/**
149
* Get the trace context (traceId + spanId) of this span.
150
* Used for cross-boundary propagation (e.g., linking subagent spans to their parent tool call).
151
*/
152
getSpanContext(): TraceContext | undefined;
153
end(): void;
154
}
155
156
/**
157
* Shape of `modelOptions` passed through VS Code IPC for cross-process
158
* CapturingToken restoration and OTel trace context propagation.
159
*/
160
export interface OTelModelOptions {
161
readonly _capturingTokenCorrelationId?: string;
162
readonly _otelTraceContext?: TraceContext | null;
163
}
164
165
/**
166
* Serializable snapshot of a completed span, fired via `IOTelService.onDidCompleteSpan`.
167
* Contains all in-memory attributes (including content attributes regardless of captureContent).
168
*/
169
export interface ICompletedSpanData {
170
readonly name: string;
171
readonly spanId: string;
172
readonly traceId: string;
173
readonly parentSpanId?: string;
174
readonly startTime: number; // milliseconds since epoch
175
readonly endTime: number; // milliseconds since epoch
176
readonly status: { readonly code: SpanStatusCode; readonly message?: string };
177
readonly attributes: Readonly<Record<string, string | number | boolean | string[]>>;
178
readonly events: readonly ISpanEventRecord[];
179
}
180
181
/**
182
* A single event on a span (recorded via `ISpanHandle.addEvent`).
183
*/
184
export interface ISpanEventRecord {
185
readonly name: string;
186
readonly timestamp: number; // milliseconds since epoch
187
readonly attributes?: Readonly<Record<string, string | number | boolean | string[]>>;
188
}
189
190
/**
191
* Data emitted via `IOTelService.onDidEmitSpanEvent` when a span event is added.
192
* Enables real-time streaming of in-flight span events to the debug panel.
193
*/
194
export interface ISpanEventData {
195
readonly spanId: string;
196
readonly traceId: string;
197
readonly parentSpanId?: string;
198
readonly eventName: string;
199
readonly attributes: Readonly<Record<string, string | number | boolean | string[]>>;
200
readonly timestamp: number; // milliseconds since epoch
201
}
202
203