1
- import type { Client } from '../client' ;
2
- import { SEMANTIC_ATTRIBUTE_SENTRY_OP , SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes' ;
3
- import type { Event } from '../types-hoist/event' ;
4
- import type { Span , SpanAttributes , SpanAttributeValue , SpanJSON , SpanOrigin } from '../types-hoist/span' ;
5
- import { spanToJSON } from './spanUtils' ;
1
+ import type { Client } from '../../client' ;
2
+ import { SEMANTIC_ATTRIBUTE_SENTRY_OP , SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes' ;
3
+ import type { Event } from '../../types-hoist/event' ;
4
+ import type { Span , SpanAttributes , SpanAttributeValue , SpanJSON , SpanOrigin } from '../../types-hoist/span' ;
5
+ import { spanToJSON } from '../spanUtils' ;
6
+ import type { TokenSummary } from './types' ;
7
+ import { accumulateTokensForParent , applyAccumulatedTokens } from './utils' ;
6
8
import type { ProviderMetadata } from './vercel-ai-attributes' ;
7
9
import {
8
10
AI_MODEL_ID_ATTRIBUTE ,
@@ -60,11 +62,6 @@ function onVercelAiSpanStart(span: Span): void {
60
62
processGenerateSpan ( span , name , attributes ) ;
61
63
}
62
64
63
- interface TokenSummary {
64
- inputTokens : number ;
65
- outputTokens : number ;
66
- }
67
-
68
65
function vercelAiEventProcessor ( event : Event ) : Event {
69
66
if ( event . type === 'transaction' && event . spans ) {
70
67
// Map to accumulate token data by parent span ID
@@ -86,6 +83,12 @@ function vercelAiEventProcessor(event: Event): Event {
86
83
87
84
applyAccumulatedTokens ( span , tokenAccumulator ) ;
88
85
}
86
+
87
+ // Also apply to root when it is the invoke_agent pipeline
88
+ const trace = event . contexts ?. trace ;
89
+ if ( trace && trace . op === 'gen_ai.invoke_agent' ) {
90
+ applyAccumulatedTokens ( trace , tokenAccumulator ) ;
91
+ }
89
92
}
90
93
91
94
return event ;
@@ -262,56 +265,6 @@ export function addVercelAiProcessors(client: Client): void {
262
265
client . addEventProcessor ( Object . assign ( vercelAiEventProcessor , { id : 'VercelAiEventProcessor' } ) ) ;
263
266
}
264
267
265
- /**
266
- * Accumulates token data from a span to its parent in the token accumulator map.
267
- * This function extracts token usage from the current span and adds it to the
268
- * accumulated totals for its parent span.
269
- */
270
- function accumulateTokensForParent ( span : SpanJSON , tokenAccumulator : Map < string , TokenSummary > ) : void {
271
- const parentSpanId = span . parent_span_id ;
272
- if ( ! parentSpanId ) {
273
- return ;
274
- }
275
-
276
- const inputTokens = span . data [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] ;
277
- const outputTokens = span . data [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] ;
278
-
279
- if ( typeof inputTokens === 'number' || typeof outputTokens === 'number' ) {
280
- const existing = tokenAccumulator . get ( parentSpanId ) || { inputTokens : 0 , outputTokens : 0 } ;
281
-
282
- if ( typeof inputTokens === 'number' ) {
283
- existing . inputTokens += inputTokens ;
284
- }
285
- if ( typeof outputTokens === 'number' ) {
286
- existing . outputTokens += outputTokens ;
287
- }
288
-
289
- tokenAccumulator . set ( parentSpanId , existing ) ;
290
- }
291
- }
292
-
293
- /**
294
- * Applies accumulated token data to the `gen_ai.invoke_agent` span.
295
- * Only immediate children of the `gen_ai.invoke_agent` span are considered,
296
- * since aggregation will automatically occur for each parent span.
297
- */
298
- function applyAccumulatedTokens ( span : SpanJSON , tokenAccumulator : Map < string , TokenSummary > ) : void {
299
- const accumulated = tokenAccumulator . get ( span . span_id ) ;
300
- if ( ! accumulated ) {
301
- return ;
302
- }
303
-
304
- if ( accumulated . inputTokens > 0 ) {
305
- span . data [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] = accumulated . inputTokens ;
306
- }
307
- if ( accumulated . outputTokens > 0 ) {
308
- span . data [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] = accumulated . outputTokens ;
309
- }
310
- if ( accumulated . inputTokens > 0 || accumulated . outputTokens > 0 ) {
311
- span . data [ 'gen_ai.usage.total_tokens' ] = accumulated . inputTokens + accumulated . outputTokens ;
312
- }
313
- }
314
-
315
268
function addProviderMetadataToAttributes ( attributes : SpanAttributes ) : void {
316
269
const providerMetadata = attributes [ AI_RESPONSE_PROVIDER_METADATA_ATTRIBUTE ] as string | undefined ;
317
270
if ( providerMetadata ) {
0 commit comments