|
1 | 1 | import { getCurrentScope } from '../../currentScopes';
|
2 | 2 | import { captureException } from '../../exports';
|
3 |
| -import { startSpan } from '../../tracing/trace'; |
| 3 | +import { startSpan, startSpanManual } from '../../tracing/trace'; |
4 | 4 | import type { Span, SpanAttributeValue } from '../../types-hoist/span';
|
5 | 5 | import {
|
6 | 6 | GEN_AI_OPERATION_NAME_ATTRIBUTE,
|
@@ -178,37 +178,55 @@ function instrumentMethod<T extends unknown[], R>(
|
178 | 178 | const model = (requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';
|
179 | 179 | const operationName = getOperationName(methodPath);
|
180 | 180 |
|
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); |
192 | 182 |
|
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 | + } |
194 | 195 |
|
195 |
| - if (isStream(result)) { |
196 | 196 | return instrumentStream(
|
197 | 197 | result as OpenAIStream<ChatCompletionChunk | ResponseStreamingEvent>,
|
198 | 198 | span,
|
199 | 199 | finalOptions.recordOutputs ?? false,
|
| 200 | + finish, |
200 | 201 | ) as unknown as R;
|
| 202 | + } catch (error) { |
| 203 | + captureException(error); |
| 204 | + finish(); |
| 205 | + throw error; |
201 | 206 | }
|
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 | + } |
212 | 230 | };
|
213 | 231 | }
|
214 | 232 |
|
|
0 commit comments