@@ -3,9 +3,14 @@ import { SPAN_STATUS_ERROR } from '../../tracing';
33import type { Span } from '../../types-hoist/span' ;
44import {
55 GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE ,
6+ GEN_AI_RESPONSE_ID_ATTRIBUTE ,
7+ GEN_AI_RESPONSE_MODEL_ATTRIBUTE ,
68 GEN_AI_RESPONSE_STREAMING_ATTRIBUTE ,
79 GEN_AI_RESPONSE_TEXT_ATTRIBUTE ,
810 GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE ,
11+ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ,
12+ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ,
13+ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ,
914} from '../ai/gen-ai-attributes' ;
1015import { RESPONSE_EVENT_TYPES } from './constants' ;
1116import type {
@@ -15,12 +20,7 @@ import type {
1520 ResponseFunctionCall ,
1621 ResponseStreamingEvent ,
1722} from './types' ;
18- import {
19- isChatCompletionChunk ,
20- isResponsesApiStreamEvent ,
21- setCommonResponseAttributes ,
22- setTokenUsageAttributes ,
23- } from './utils' ;
23+ import { isChatCompletionChunk , isResponsesApiStreamEvent } from './utils' ;
2424
2525/**
2626 * State object used to accumulate information from a stream of OpenAI events/chunks.
@@ -36,8 +36,6 @@ interface StreamingState {
3636 responseId : string ;
3737 /** The model name. */
3838 responseModel : string ;
39- /** The timestamp of the response. */
40- responseTimestamp : number ;
4139 /** Number of prompt/input tokens used. */
4240 promptTokens : number | undefined ;
4341 /** Number of completion/output tokens used. */
@@ -99,7 +97,6 @@ function processChatCompletionToolCalls(toolCalls: ChatCompletionToolCall[], sta
9997function processChatCompletionChunk ( chunk : ChatCompletionChunk , state : StreamingState , recordOutputs : boolean ) : void {
10098 state . responseId = chunk . id ?? state . responseId ;
10199 state . responseModel = chunk . model ?? state . responseModel ;
102- state . responseTimestamp = chunk . created ?? state . responseTimestamp ;
103100
104101 if ( chunk . usage ) {
105102 // For stream responses, the input tokens remain constant across all events in the stream.
@@ -183,7 +180,6 @@ function processResponsesApiEvent(
183180 const { response } = event as { response : OpenAIResponseObject } ;
184181 state . responseId = response . id ?? state . responseId ;
185182 state . responseModel = response . model ?? state . responseModel ;
186- state . responseTimestamp = response . created_at ?? state . responseTimestamp ;
187183
188184 if ( response . usage ) {
189185 // For stream responses, the input tokens remain constant across all events in the stream.
@@ -227,7 +223,6 @@ export async function* instrumentStream<T>(
227223 finishReasons : [ ] ,
228224 responseId : '' ,
229225 responseModel : '' ,
230- responseTimestamp : 0 ,
231226 promptTokens : undefined ,
232227 completionTokens : undefined ,
233228 totalTokens : undefined ,
@@ -245,35 +240,31 @@ export async function* instrumentStream<T>(
245240 yield event ;
246241 }
247242 } finally {
248- setCommonResponseAttributes ( span , state . responseId , state . responseModel ) ;
249- setTokenUsageAttributes ( span , state . promptTokens , state . completionTokens , state . totalTokens ) ;
250-
251- span . setAttributes ( {
243+ const attrs : Record < string , string | number | boolean > = {
244+ [ GEN_AI_RESPONSE_ID_ATTRIBUTE ] : state . responseId ,
245+ [ GEN_AI_RESPONSE_MODEL_ATTRIBUTE ] : state . responseModel ,
252246 [ GEN_AI_RESPONSE_STREAMING_ATTRIBUTE ] : true ,
253- } ) ;
247+ } ;
248+
249+ if ( state . promptTokens !== undefined ) attrs [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] = state . promptTokens ;
250+ if ( state . completionTokens !== undefined ) attrs [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] = state . completionTokens ;
251+ if ( state . totalTokens !== undefined ) attrs [ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ] = state . totalTokens ;
254252
255253 if ( state . finishReasons . length ) {
256- span . setAttributes ( {
257- [ GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE ] : JSON . stringify ( state . finishReasons ) ,
258- } ) ;
254+ attrs [ GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE ] = JSON . stringify ( state . finishReasons ) ;
259255 }
260256
261257 if ( recordOutputs && state . responseTexts . length ) {
262- span . setAttributes ( {
263- [ GEN_AI_RESPONSE_TEXT_ATTRIBUTE ] : state . responseTexts . join ( '' ) ,
264- } ) ;
258+ attrs [ GEN_AI_RESPONSE_TEXT_ATTRIBUTE ] = state . responseTexts . join ( '' ) ;
265259 }
266260
267- // Set tool calls attribute if any were accumulated
268261 const chatCompletionToolCallsArray = Object . values ( state . chatCompletionToolCalls ) ;
269262 const allToolCalls = [ ...chatCompletionToolCallsArray , ...state . responsesApiToolCalls ] ;
270-
271263 if ( allToolCalls . length > 0 ) {
272- span . setAttributes ( {
273- [ GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE ] : JSON . stringify ( allToolCalls ) ,
274- } ) ;
264+ attrs [ GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE ] = JSON . stringify ( allToolCalls ) ;
275265 }
276266
267+ span . setAttributes ( attrs ) ;
277268 span . end ( ) ;
278269 }
279270}
0 commit comments