Skip to content

Commit b8bd91c

Browse files
committed
manually end the span
1 parent 86f45af commit b8bd91c

File tree

2 files changed

+50
-26
lines changed

2 files changed

+50
-26
lines changed

packages/core/src/utils/openai/index.ts

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getCurrentScope } from '../../currentScopes';
22
import { captureException } from '../../exports';
3-
import { startSpan } from '../../tracing/trace';
3+
import { startSpan, startSpanManual } from '../../tracing/trace';
44
import type { Span, SpanAttributeValue } from '../../types-hoist/span';
55
import {
66
GEN_AI_OPERATION_NAME_ATTRIBUTE,
@@ -178,37 +178,55 @@ function instrumentMethod<T extends unknown[], R>(
178178
const model = (requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';
179179
const operationName = getOperationName(methodPath);
180180

181-
return startSpan(
182-
{
183-
name: `${operationName} ${model}`,
184-
op: getSpanOperation(methodPath),
185-
attributes: requestAttributes as Record<string, SpanAttributeValue>,
186-
},
187-
async (span: Span) => {
188-
try {
189-
if (finalOptions.recordInputs && args[0] && typeof args[0] === 'object') {
190-
addRequestAttributes(span, args[0] as Record<string, unknown>);
191-
}
181+
const result = await originalMethod.apply(context, args);
192182

193-
const result = await originalMethod.apply(context, args);
183+
if (isStream(result)) {
184+
return startSpanManual(
185+
{
186+
name: `${operationName} ${model}`,
187+
op: getSpanOperation(methodPath),
188+
attributes: requestAttributes as Record<string, SpanAttributeValue>,
189+
},
190+
(span: Span, finish: () => void) => {
191+
try {
192+
if (finalOptions.recordInputs && args[0] && typeof args[0] === 'object') {
193+
addRequestAttributes(span, args[0] as Record<string, unknown>);
194+
}
194195

195-
if (isStream(result)) {
196196
return instrumentStream(
197197
result as OpenAIStream<ChatCompletionChunk | ResponseStreamingEvent>,
198198
span,
199199
finalOptions.recordOutputs ?? false,
200+
finish,
200201
) as unknown as R;
202+
} catch (error) {
203+
captureException(error);
204+
finish();
205+
throw error;
201206
}
202-
203-
// Handle non-streaming responses
204-
addResponseAttributes(span, result, finalOptions.recordOutputs);
205-
return result;
206-
} catch (error) {
207-
captureException(error);
208-
throw error;
209-
}
210-
},
211-
);
207+
},
208+
);
209+
} else {
210+
return startSpan(
211+
{
212+
name: `${operationName} ${model}`,
213+
op: getSpanOperation(methodPath),
214+
attributes: requestAttributes as Record<string, SpanAttributeValue>,
215+
},
216+
async (span: Span) => {
217+
try {
218+
if (finalOptions.recordInputs && args[0] && typeof args[0] === 'object') {
219+
addRequestAttributes(span, args[0] as Record<string, unknown>);
220+
}
221+
addResponseAttributes(span, result, finalOptions.recordOutputs);
222+
return result;
223+
} catch (error) {
224+
captureException(error);
225+
throw error;
226+
}
227+
},
228+
);
229+
}
212230
};
213231
}
214232

packages/core/src/utils/openai/streaming.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,14 @@ function processResponsesApiEvent(
9595
* @param stream - The stream of events to instrument
9696
* @param span - The span to add attributes to
9797
* @param recordOutputs - Whether to record outputs
98+
* @param finishSpan - Optional function to finish the span manually
9899
* @returns A generator that yields the events
99100
*/
100101
export async function* instrumentStream<T>(
101102
stream: AsyncIterable<T>,
102103
span: Span,
103104
recordOutputs: boolean,
105+
finishSpan?: () => void,
104106
): AsyncGenerator<T, void, unknown> {
105107
const state: StreamingState = {
106108
eventTypes: [],
@@ -123,14 +125,18 @@ export async function* instrumentStream<T>(
123125

124126
if (state.finishReasons.length) {
125127
span.setAttributes({
126-
[GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify(state.finishReasons),
128+
[GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: state.finishReasons.join(','),
127129
});
128130
}
129131

130132
if (recordOutputs && state.responseTexts.length) {
131133
span.setAttributes({
132-
[GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: JSON.stringify(state.responseTexts),
134+
[GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: state.responseTexts.join(''),
133135
});
134136
}
135137
}
138+
139+
if (finishSpan) {
140+
finishSpan();
141+
}
136142
}

0 commit comments

Comments
 (0)