豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 59cb55f

Browse files
committed
refactor: replace hardcoded gen_ai.* strings with OTel semantic convention constants
- Replace hardcoded gen_ai.* attribute strings in 9 test files with GenAiAttr/GenAiOperationName/OTelSemConv constants - Update genAiAttributes.ts: use new v1.40.0 standard constants for USAGE_CACHE_READ_INPUT_TOKENS, USAGE_CACHE_CREATION_INPUT_TOKENS, and AGENT_VERSION (previously custom) - Update @opentelemetry/semantic-conventions from 1.39.0 to 1.40.0 - Update all other @opentelemetry packages to latest versions
1 parent 35022f3 commit 59cb55f

File tree

12 files changed

+242
-260
lines changed

12 files changed

+242
-260
lines changed

package-lock.json

Lines changed: 178 additions & 201 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6353,19 +6353,19 @@
63536353
"@humanwhocodes/gitignore-to-minimatch": "1.0.2",
63546354
"@microsoft/tiktokenizer": "^1.0.10",
63556355
"@modelcontextprotocol/sdk": "^1.25.2",
6356-
"@opentelemetry/api": "^1.9.0",
6357-
"@opentelemetry/api-logs": "^0.212.0",
6358-
"@opentelemetry/exporter-logs-otlp-grpc": "^0.212.0",
6359-
"@opentelemetry/exporter-logs-otlp-http": "^0.212.0",
6360-
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.212.0",
6361-
"@opentelemetry/exporter-metrics-otlp-http": "^0.212.0",
6362-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.212.0",
6363-
"@opentelemetry/exporter-trace-otlp-http": "^0.212.0",
6364-
"@opentelemetry/resources": "^2.5.1",
6365-
"@opentelemetry/sdk-logs": "^0.212.0",
6366-
"@opentelemetry/sdk-metrics": "^2.5.1",
6367-
"@opentelemetry/sdk-trace-node": "^2.5.1",
6368-
"@opentelemetry/semantic-conventions": "^1.39.0",
6356+
"@opentelemetry/api": "^1.9.1",
6357+
"@opentelemetry/api-logs": "^0.214.0",
6358+
"@opentelemetry/exporter-logs-otlp-grpc": "^0.214.0",
6359+
"@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
6360+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.214.0",
6361+
"@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
6362+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.214.0",
6363+
"@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
6364+
"@opentelemetry/resources": "^2.6.1",
6365+
"@opentelemetry/sdk-logs": "^0.214.0",
6366+
"@opentelemetry/sdk-metrics": "^2.6.1",
6367+
"@opentelemetry/sdk-trace-node": "^2.6.1",
6368+
"@opentelemetry/semantic-conventions": "^1.40.0",
63696369
"@sinclair/typebox": "^0.34.41",
63706370
"@vscode/copilot-api": "^0.2.18",
63716371
"@vscode/extension-telemetry": "^1.5.1",

src/extension/chatSessions/claude/node/test/claudeCodeAgentOTel.spec.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type Anthropic from '@anthropic-ai/sdk';
88
import { randomUUID } from 'crypto';
99
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
1010
import type * as vscode from 'vscode';
11+
import { GenAiAttr, GenAiOperationName } from '../../../../../platform/otel/common/genAiAttributes';
1112
import { resolveOTelConfig } from '../../../../../platform/otel/common/index';
1213
import { ICompletedSpanData, IOTelService } from '../../../../../platform/otel/common/otelService';
1314
import { InMemoryOTelService } from '../../../../../platform/otel/node/inMemoryOTelService';
@@ -243,13 +244,13 @@ describe('Claude Session OTel Tool Spans', () => {
243244
// Should have a user_message span + an execute_tool span
244245
const toolSpan = spans.find(s => s.name === 'execute_tool Read');
245246
expect(toolSpan).toBeDefined();
246-
expect(toolSpan!.attributes['gen_ai.operation.name']).toBe('execute_tool');
247-
expect(toolSpan!.attributes['gen_ai.tool.name']).toBe('Read');
248-
expect(toolSpan!.attributes['gen_ai.tool.call.id']).toBe('tu-1');
247+
expect(toolSpan!.attributes[GenAiAttr.OPERATION_NAME]).toBe(GenAiOperationName.EXECUTE_TOOL);
248+
expect(toolSpan!.attributes[GenAiAttr.TOOL_NAME]).toBe('Read');
249+
expect(toolSpan!.attributes[GenAiAttr.TOOL_CALL_ID]).toBe('tu-1');
249250
expect(toolSpan!.attributes['copilot_chat.chat_session_id']).toBe(sessionId);
250251
expect(toolSpan!.status.code).toBe(1); // SpanStatusCode.OK
251-
expect(toolSpan!.attributes['gen_ai.tool.call.arguments']).toContain('file_path');
252-
expect(toolSpan!.attributes['gen_ai.tool.call.result']).toContain('file contents here');
252+
expect(toolSpan!.attributes[GenAiAttr.TOOL_CALL_ARGUMENTS]).toContain('file_path');
253+
expect(toolSpan!.attributes[GenAiAttr.TOOL_CALL_RESULT]).toContain('file contents here');
253254
});
254255

255256
it('emits an execute_tool span with ERROR status for a failed tool call', async () => {
@@ -287,7 +288,7 @@ describe('Claude Session OTel Tool Spans', () => {
287288
expect(toolSpan).toBeDefined();
288289
expect(toolSpan!.status.code).toBe(2); // SpanStatusCode.ERROR
289290
expect(toolSpan!.status.message).toContain('Permission denied');
290-
expect(toolSpan!.attributes['gen_ai.tool.call.result']).toContain('ERROR');
291+
expect(toolSpan!.attributes[GenAiAttr.TOOL_CALL_RESULT]).toContain('ERROR');
291292
});
292293

293294
it('correctly correlates multiple concurrent tool calls', async () => {
@@ -329,8 +330,8 @@ describe('Claude Session OTel Tool Spans', () => {
329330
const globSpan = spans.find(s => s.name === 'execute_tool Glob');
330331
expect(readSpan).toBeDefined();
331332
expect(globSpan).toBeDefined();
332-
expect(readSpan!.attributes['gen_ai.tool.call.result']).toContain('read result');
333-
expect(globSpan!.attributes['gen_ai.tool.call.result']).toContain('glob result');
333+
expect(readSpan!.attributes[GenAiAttr.TOOL_CALL_RESULT]).toContain('read result');
334+
expect(globSpan!.attributes[GenAiAttr.TOOL_CALL_RESULT]).toContain('glob result');
334335
expect(readSpan!.status.code).toBe(1); // OK
335336
expect(globSpan!.status.code).toBe(1); // OK
336337
});
@@ -399,7 +400,7 @@ describe('Claude Session OTel Tool Spans', () => {
399400

400401
const toolSpan = spans.find(s => s.name === 'execute_tool Bash');
401402
expect(toolSpan).toBeDefined();
402-
expect(toolSpan!.attributes['gen_ai.tool.call.arguments']).toContain('ls -la');
403+
expect(toolSpan!.attributes[GenAiAttr.TOOL_CALL_ARGUMENTS]).toContain('ls -la');
403404
});
404405

405406
it('emits execute_hook span for a successful hook invocation', async () => {
@@ -433,7 +434,7 @@ describe('Claude Session OTel Tool Spans', () => {
433434

434435
const hookSpan = spans.find(s => s.name === 'execute_hook SessionStart');
435436
expect(hookSpan).toBeDefined();
436-
expect(hookSpan!.attributes['gen_ai.operation.name']).toBe('execute_hook');
437+
expect(hookSpan!.attributes[GenAiAttr.OPERATION_NAME]).toBe(GenAiOperationName.EXECUTE_HOOK);
437438
expect(hookSpan!.attributes['copilot_chat.hook_type']).toBe('SessionStart');
438439
expect(hookSpan!.attributes['copilot_chat.hook_command']).toBe('SessionStart');
439440
expect(hookSpan!.attributes['copilot_chat.chat_session_id']).toBe(sessionId);

src/extension/chatSessions/copilotcli/node/test/copilotCliBridgeSpanProcessor.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { beforeEach, describe, expect, it, vi } from 'vitest';
7+
import { GenAiAttr, GenAiOperationName } from '../../../../../platform/otel/common/genAiAttributes';
78
import { resolveOTelConfig } from '../../../../../platform/otel/common/otelConfig';
89
import type { ICompletedSpanData, IOTelService } from '../../../../../platform/otel/common/otelService';
910
import { Event } from '../../../../../util/vs/base/common/event';
@@ -225,7 +226,7 @@ describe('CopilotCliBridgeSpanProcessor', () => {
225226
expect(otelService.injectedSpans).toHaveLength(1);
226227
const span = otelService.injectedSpans[0];
227228
expect(span.name).toBe('execute_hook sessionEnd');
228-
expect(span.attributes['gen_ai.operation.name']).toBe('execute_hook');
229+
expect(span.attributes[GenAiAttr.OPERATION_NAME]).toBe(GenAiOperationName.EXECUTE_HOOK);
229230
expect(span.attributes['copilot_chat.hook_type']).toBe('sessionEnd');
230231
expect(span.attributes['copilot_chat.hook_input']).toBe('{"reason":"complete"}');
231232
expect(span.attributes['copilot_chat.hook_result_kind']).toBe('success');

src/extension/trajectory/vscode-node/test/otlpFormatConversion.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function makeSpan(overrides: Partial<ICompletedSpanData> = {}): ICompletedSpanDa
3030
describe('OTLP Format Conversion', () => {
3131
describe('completedSpanToOtlpSpan', () => {
3232
it('converts basic span', () => {
33-
const span = makeSpan({ name: 'chat gpt-4o', attributes: { 'gen_ai.request.model': 'gpt-4o' } });
33+
const span = makeSpan({ name: 'chat gpt-4o', attributes: { [GenAiAttr.REQUEST_MODEL]: 'gpt-4o' } });
3434
const otlp = completedSpanToOtlpSpan(span);
3535

3636
expect(otlp.name).toBe('chat gpt-4o');
@@ -39,7 +39,7 @@ describe('OTLP Format Conversion', () => {
3939
expect(otlp.startTimeUnixNano).toBe(String(1709472000000 * 1_000_000));
4040
expect(otlp.endTimeUnixNano).toBe(String(1709472001000 * 1_000_000));
4141
expect(otlp.attributes).toEqual([
42-
{ key: 'gen_ai.request.model', value: { stringValue: 'gpt-4o' } },
42+
{ key: GenAiAttr.REQUEST_MODEL, value: { stringValue: 'gpt-4o' } },
4343
]);
4444
});
4545

src/platform/otel/common/genAiAttributes.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,8 @@ export const GenAiAttr = {
6767
// Usage
6868
USAGE_INPUT_TOKENS: OTelSemConv.ATTR_GEN_AI_USAGE_INPUT_TOKENS,
6969
USAGE_OUTPUT_TOKENS: OTelSemConv.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
70-
/** Custom: not yet standardized in OTel GenAI conventions */
71-
USAGE_CACHE_READ_INPUT_TOKENS: 'gen_ai.usage.cache_read.input_tokens',
72-
/** Custom: not yet standardized in OTel GenAI conventions */
73-
USAGE_CACHE_CREATION_INPUT_TOKENS: 'gen_ai.usage.cache_creation.input_tokens',
70+
USAGE_CACHE_READ_INPUT_TOKENS: OTelSemConv.ATTR_GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS,
71+
USAGE_CACHE_CREATION_INPUT_TOKENS: OTelSemConv.ATTR_GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS,
7472
/** Custom: reasoning/thinking token count (not yet standardized in GenAI conventions) */
7573
USAGE_REASONING_TOKENS: 'gen_ai.usage.reasoning_tokens',
7674

@@ -84,8 +82,7 @@ export const GenAiAttr = {
8482
// Agent
8583
AGENT_NAME: OTelSemConv.ATTR_GEN_AI_AGENT_NAME,
8684
AGENT_ID: OTelSemConv.ATTR_GEN_AI_AGENT_ID,
87-
/** Custom: not yet standardized in OTel GenAI conventions */
88-
AGENT_VERSION: 'gen_ai.agent.version',
85+
AGENT_VERSION: OTelSemConv.ATTR_GEN_AI_AGENT_VERSION,
8986
AGENT_DESCRIPTION: OTelSemConv.ATTR_GEN_AI_AGENT_DESCRIPTION,
9087

9188
// Tool

src/platform/otel/common/test/agentTraceHierarchy.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as OTelSemConv from '@opentelemetry/semantic-conventions/incubating';
67
import { describe, expect, it } from 'vitest';
78
import { GenAiAttr, GenAiOperationName, GenAiProviderName } from '../genAiAttributes';
89
import { emitAgentTurnEvent, emitSessionStartEvent } from '../genAiEvents';
@@ -216,11 +217,11 @@ describe('Agent Trace Hierarchy', () => {
216217
});
217218

218219
expect(otel.metrics).toHaveLength(3);
219-
expect(otel.metrics[0].name).toBe('gen_ai.client.operation.duration');
220+
expect(otel.metrics[0].name).toBe(OTelSemConv.METRIC_GEN_AI_CLIENT_OPERATION_DURATION);
220221
expect(otel.metrics[0].value).toBe(3.5);
221-
expect(otel.metrics[1].name).toBe('gen_ai.client.token.usage');
222+
expect(otel.metrics[1].name).toBe(OTelSemConv.METRIC_GEN_AI_CLIENT_TOKEN_USAGE);
222223
expect(otel.metrics[1].value).toBe(1500);
223-
expect(otel.metrics[2].name).toBe('gen_ai.client.token.usage');
224+
expect(otel.metrics[2].name).toBe(OTelSemConv.METRIC_GEN_AI_CLIENT_TOKEN_USAGE);
224225
expect(otel.metrics[2].value).toBe(250);
225226
});
226227
});

src/platform/otel/common/test/byokProviderSpans.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as OTelSemConv from '@opentelemetry/semantic-conventions/incubating';
67
import { describe, expect, it } from 'vitest';
78
import { GenAiAttr, GenAiOperationName } from '../genAiAttributes';
89
import { emitInferenceDetailsEvent } from '../genAiEvents';
@@ -111,7 +112,7 @@ describe('BYOK Provider Span Emission', () => {
111112

112113
expect(otel.logRecords).toHaveLength(1);
113114
const attrs = otel.logRecords[0].attributes!;
114-
expect(attrs['event.name']).toBe('gen_ai.client.inference.operation.details');
115+
expect(attrs['event.name']).toBe(OTelSemConv.EVENT_GEN_AI_CLIENT_INFERENCE_OPERATION_DETAILS);
115116
expect(attrs[GenAiAttr.REQUEST_MODEL]).toBe('claude-sonnet-4-20250514');
116117
expect(attrs[GenAiAttr.USAGE_INPUT_TOKENS]).toBe(2000);
117118
expect(attrs[GenAiAttr.USAGE_OUTPUT_TOKENS]).toBe(500);

src/platform/otel/common/test/chatMLFetcherSpanLifecycle.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as OTelSemConv from '@opentelemetry/semantic-conventions/incubating';
67
import { describe, expect, it } from 'vitest';
78
import { CopilotChatAttr, GenAiAttr, GenAiOperationName, GenAiProviderName } from '../genAiAttributes';
89
import { SpanKind, SpanStatusCode } from '../otelService';
@@ -84,14 +85,14 @@ describe('chatMLFetcher Span Lifecycle', () => {
8485

8586
// Simulate the finally block in _doFetch
8687
const durationSec = 3.5;
87-
otel.recordMetric('gen_ai.client.operation.duration', durationSec, {
88+
otel.recordMetric(OTelSemConv.METRIC_GEN_AI_CLIENT_OPERATION_DURATION, durationSec, {
8889
[GenAiAttr.OPERATION_NAME]: GenAiOperationName.CHAT,
8990
[GenAiAttr.PROVIDER_NAME]: GenAiProviderName.GITHUB,
9091
[GenAiAttr.REQUEST_MODEL]: 'gpt-4o',
9192
});
9293

9394
expect(otel.metrics).toHaveLength(1);
94-
expect(otel.metrics[0].name).toBe('gen_ai.client.operation.duration');
95+
expect(otel.metrics[0].name).toBe(OTelSemConv.METRIC_GEN_AI_CLIENT_OPERATION_DURATION);
9596
expect(otel.metrics[0].value).toBe(3.5);
9697
});
9798

src/platform/otel/common/test/genAiEvents.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as OTelSemConv from '@opentelemetry/semantic-conventions/incubating';
67
import { describe, expect, it, vi } from 'vitest';
78
import { Event } from '../../../../util/vs/base/common/event';
89
import { GenAiAttr, GenAiOperationName, StdAttr } from '../genAiAttributes';
@@ -47,7 +48,7 @@ describe('emitInferenceDetailsEvent', () => {
4748
expect(otel.emitLogRecord).toHaveBeenCalledOnce();
4849
const [body, attrs] = otel.emitLogRecord.mock.calls[0];
4950
expect(body).toContain('gpt-4o');
50-
expect(attrs['event.name']).toBe('gen_ai.client.inference.operation.details');
51+
expect(attrs['event.name']).toBe(OTelSemConv.EVENT_GEN_AI_CLIENT_INFERENCE_OPERATION_DETAILS);
5152
expect(attrs[GenAiAttr.OPERATION_NAME]).toBe(GenAiOperationName.CHAT);
5253
expect(attrs[GenAiAttr.REQUEST_MODEL]).toBe('gpt-4o');
5354
expect(attrs[GenAiAttr.RESPONSE_MODEL]).toBe('gpt-4o');

0 commit comments

Comments
 (0)