Skip to content

Commit 75f68c7

Browse files
authored
fix(core): Fix and add missing cache attributes in Vercel AI (#17982)
With the relay now handling cache token attributes (instead of scrubbing them), some Anthropic related token attributes were still missing. This PR adds the missing cache attributes and corrects the types in the Anthropic provider metadata used for extracting token data. Fixes: #17890
1 parent d551d23 commit 75f68c7

File tree

3 files changed

+52
-14
lines changed

3 files changed

+52
-14
lines changed

packages/core/src/utils/ai/gen-ai-attributes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ export const GEN_AI_RESPONSE_STREAMING_ATTRIBUTE = 'gen_ai.response.streaming';
129129
*/
130130
export const GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE = 'gen_ai.response.tool_calls';
131131

132+
/**
133+
* The number of cache write input tokens used
134+
*/
135+
export const GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE = 'gen_ai.usage.input_tokens.cache_write';
136+
137+
/**
138+
* The number of cached input tokens that were used
139+
*/
140+
export const GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE = 'gen_ai.usage.input_tokens.cached';
141+
132142
// =============================================================================
133143
// OPENAI-SPECIFIC ATTRIBUTES
134144
// =============================================================================

packages/core/src/utils/vercel-ai/index.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import type { Client } from '../../client';
22
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';
33
import type { Event } from '../../types-hoist/event';
44
import type { Span, SpanAttributes, SpanAttributeValue, SpanJSON, SpanOrigin } from '../../types-hoist/span';
5+
import {
6+
GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE,
7+
GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE,
8+
} from '../ai/gen-ai-attributes';
59
import { spanToJSON } from '../spanUtils';
610
import { toolCallSpanMap } from './constants';
711
import type { TokenSummary } from './types';
@@ -23,6 +27,7 @@ import {
2327
AI_TOOL_CALL_ID_ATTRIBUTE,
2428
AI_TOOL_CALL_NAME_ATTRIBUTE,
2529
AI_TOOL_CALL_RESULT_ATTRIBUTE,
30+
AI_USAGE_CACHED_INPUT_TOKENS_ATTRIBUTE,
2631
AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE,
2732
AI_USAGE_PROMPT_TOKENS_ATTRIBUTE,
2833
GEN_AI_RESPONSE_MODEL_ATTRIBUTE,
@@ -107,6 +112,7 @@ function processEndedVercelAiSpan(span: SpanJSON): void {
107112

108113
renameAttributeKey(attributes, AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE, GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE);
109114
renameAttributeKey(attributes, AI_USAGE_PROMPT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE);
115+
renameAttributeKey(attributes, AI_USAGE_CACHED_INPUT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE);
110116

111117
if (
112118
typeof attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] === 'number' &&
@@ -287,7 +293,7 @@ function addProviderMetadataToAttributes(attributes: SpanAttributes): void {
287293
if (providerMetadataObject.openai) {
288294
setAttributeIfDefined(
289295
attributes,
290-
'gen_ai.usage.input_tokens.cached',
296+
GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE,
291297
providerMetadataObject.openai.cachedPromptTokens,
292298
);
293299
setAttributeIfDefined(
@@ -309,35 +315,34 @@ function addProviderMetadataToAttributes(attributes: SpanAttributes): void {
309315
}
310316

311317
if (providerMetadataObject.anthropic) {
312-
setAttributeIfDefined(
313-
attributes,
314-
'gen_ai.usage.input_tokens.cached',
315-
providerMetadataObject.anthropic.cacheReadInputTokens,
316-
);
317-
setAttributeIfDefined(
318-
attributes,
319-
'gen_ai.usage.input_tokens.cache_write',
320-
providerMetadataObject.anthropic.cacheCreationInputTokens,
321-
);
318+
const cachedInputTokens =
319+
providerMetadataObject.anthropic.usage?.cache_read_input_tokens ??
320+
providerMetadataObject.anthropic.cacheReadInputTokens;
321+
setAttributeIfDefined(attributes, GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE, cachedInputTokens);
322+
323+
const cacheWriteInputTokens =
324+
providerMetadataObject.anthropic.usage?.cache_creation_input_tokens ??
325+
providerMetadataObject.anthropic.cacheCreationInputTokens;
326+
setAttributeIfDefined(attributes, GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE, cacheWriteInputTokens);
322327
}
323328

324329
if (providerMetadataObject.bedrock?.usage) {
325330
setAttributeIfDefined(
326331
attributes,
327-
'gen_ai.usage.input_tokens.cached',
332+
GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE,
328333
providerMetadataObject.bedrock.usage.cacheReadInputTokens,
329334
);
330335
setAttributeIfDefined(
331336
attributes,
332-
'gen_ai.usage.input_tokens.cache_write',
337+
GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE,
333338
providerMetadataObject.bedrock.usage.cacheWriteInputTokens,
334339
);
335340
}
336341

337342
if (providerMetadataObject.deepseek) {
338343
setAttributeIfDefined(
339344
attributes,
340-
'gen_ai.usage.input_tokens.cached',
345+
GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE,
341346
providerMetadataObject.deepseek.promptCacheHitTokens,
342347
);
343348
setAttributeIfDefined(

packages/core/src/utils/vercel-ai/vercel-ai-attributes.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,14 @@ export const AI_RESPONSE_PROVIDER_METADATA_ATTRIBUTE = 'ai.response.providerMeta
288288
*/
289289
export const AI_SETTINGS_MAX_RETRIES_ATTRIBUTE = 'ai.settings.maxRetries';
290290

291+
/**
292+
* Basic LLM span information
293+
* Multiple spans
294+
*
295+
* The number of cached input tokens that were used
296+
* @see https://ai-sdk.dev/docs/ai-sdk-core/telemetry#basic-llm-span-information
297+
*/
298+
export const AI_USAGE_CACHED_INPUT_TOKENS_ATTRIBUTE = 'ai.usage.cachedInputTokens';
291299
/**
292300
* Basic LLM span information
293301
* Multiple spans
@@ -863,6 +871,21 @@ interface AnthropicProviderMetadata {
863871
* @see https://ai-sdk.dev/providers/ai-sdk-providers/anthropic#cache-control
864872
*/
865873
cacheReadInputTokens?: number;
874+
875+
/**
876+
* Usage metrics for the Anthropic model.
877+
*/
878+
usage?: {
879+
input_tokens: number;
880+
cache_creation_input_tokens?: number;
881+
cache_read_input_tokens?: number;
882+
cache_creation?: {
883+
ephemeral_5m_input_tokens?: number;
884+
ephemeral_1h_input_tokens?: number;
885+
};
886+
output_tokens?: number;
887+
service_tier?: string;
888+
};
866889
}
867890

868891
/**

0 commit comments

Comments
 (0)