@@ -8,38 +8,37 @@ import {
88 GEN_AI_REQUEST_MESSAGES_ATTRIBUTE ,
99 GEN_AI_REQUEST_MODEL_ATTRIBUTE ,
1010 GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE ,
11+ GEN_AI_REQUEST_STREAM_ATTRIBUTE ,
1112 GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE ,
1213 GEN_AI_REQUEST_TOP_P_ATTRIBUTE ,
1314 GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE ,
14- GEN_AI_RESPONSE_ID_ATTRIBUTE ,
15- GEN_AI_RESPONSE_MODEL_ATTRIBUTE ,
1615 GEN_AI_RESPONSE_TEXT_ATTRIBUTE ,
1716 GEN_AI_SYSTEM_ATTRIBUTE ,
18- GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ,
19- GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ,
20- GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ,
21- OPENAI_RESPONSE_ID_ATTRIBUTE ,
22- OPENAI_RESPONSE_MODEL_ATTRIBUTE ,
23- OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE ,
24- OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE ,
25- OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE ,
17+ OPENAI_RESPONSE_STREAM_ATTRIBUTE ,
2618} from '../gen-ai-attributes' ;
2719import { OPENAI_INTEGRATION_NAME } from './constants' ;
20+ import { instrumentStream } from './streaming' ;
2821import type {
22+ ChatCompletionChunk ,
2923 InstrumentedMethod ,
3024 OpenAiChatCompletionObject ,
3125 OpenAiClient ,
3226 OpenAiIntegration ,
3327 OpenAiOptions ,
3428 OpenAiResponse ,
3529 OpenAIResponseObject ,
30+ OpenAIStream ,
31+ ResponseStreamingEvent ,
3632} from './types' ;
3733import {
3834 buildMethodPath ,
3935 getOperationName ,
4036 getSpanOperation ,
4137 isChatCompletionResponse ,
4238 isResponsesApiResponse ,
39+ isStream ,
40+ setCommonResponseAttributes ,
41+ setTokenUsageAttributes ,
4342 shouldInstrument ,
4443} from './utils' ;
4544
@@ -61,64 +60,14 @@ function extractRequestAttributes(args: unknown[], methodPath: string): Record<s
6160 if ( 'frequency_penalty' in params )
6261 attributes [ GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE ] = params . frequency_penalty ;
6362 if ( 'presence_penalty' in params ) attributes [ GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE ] = params . presence_penalty ;
63+ if ( 'stream' in params ) attributes [ GEN_AI_REQUEST_STREAM_ATTRIBUTE ] = params . stream ;
6464 } else {
6565 attributes [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] = 'unknown' ;
6666 }
6767
6868 return attributes ;
6969}
7070
71- /**
72- * Helper function to set token usage attributes
73- */
74- function setTokenUsageAttributes (
75- span : Span ,
76- promptTokens ?: number ,
77- completionTokens ?: number ,
78- totalTokens ?: number ,
79- ) : void {
80- if ( promptTokens !== undefined ) {
81- span . setAttributes ( {
82- [ OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE ] : promptTokens ,
83- [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] : promptTokens ,
84- } ) ;
85- }
86- if ( completionTokens !== undefined ) {
87- span . setAttributes ( {
88- [ OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE ] : completionTokens ,
89- [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] : completionTokens ,
90- } ) ;
91- }
92- if ( totalTokens !== undefined ) {
93- span . setAttributes ( {
94- [ GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE ] : totalTokens ,
95- } ) ;
96- }
97- }
98-
99- /**
100- * Helper function to set common response attributes (ID, model, timestamp)
101- */
102- function setCommonResponseAttributes ( span : Span , id ?: string , model ?: string , timestamp ?: number ) : void {
103- if ( id ) {
104- span . setAttributes ( {
105- [ OPENAI_RESPONSE_ID_ATTRIBUTE ] : id ,
106- [ GEN_AI_RESPONSE_ID_ATTRIBUTE ] : id ,
107- } ) ;
108- }
109- if ( model ) {
110- span . setAttributes ( {
111- [ OPENAI_RESPONSE_MODEL_ATTRIBUTE ] : model ,
112- [ GEN_AI_RESPONSE_MODEL_ATTRIBUTE ] : model ,
113- } ) ;
114- }
115- if ( timestamp ) {
116- span . setAttributes ( {
117- [ OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE ] : new Date ( timestamp * 1000 ) . toISOString ( ) ,
118- } ) ;
119- }
120- }
121-
12271/**
12372 * Add attributes for Chat Completion responses
12473 */
@@ -195,6 +144,9 @@ function addRequestAttributes(span: Span, params: Record<string, unknown>): void
195144 if ( 'input' in params ) {
196145 span . setAttributes ( { [ GEN_AI_REQUEST_MESSAGES_ATTRIBUTE ] : JSON . stringify ( params . input ) } ) ;
197146 }
147+ if ( 'stream' in params ) {
148+ span . setAttributes ( { [ OPENAI_RESPONSE_STREAM_ATTRIBUTE ] : Boolean ( params . stream ) } ) ;
149+ }
198150}
199151
200152function getOptionsFromIntegration ( ) : OpenAiOptions {
@@ -239,7 +191,16 @@ function instrumentMethod<T extends unknown[], R>(
239191 }
240192
241193 const result = await originalMethod . apply ( context , args ) ;
242- // TODO: Add streaming support
194+
195+ if ( isStream ( result ) ) {
196+ return instrumentStream (
197+ result as OpenAIStream < ChatCompletionChunk | ResponseStreamingEvent > ,
198+ span ,
199+ finalOptions . recordOutputs ?? false ,
200+ ) as unknown as R ;
201+ }
202+
203+ // Handle non-streaming responses
243204 addResponseAttributes ( span , result , finalOptions . recordOutputs ) ;
244205 return result ;
245206 } catch ( error ) {
0 commit comments