|
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