fix(core): Preserve OpenAI APIPromise methods like withResponse()#18402
Closed
Sai-Tom wants to merge 5 commits intogetsentry:developfrom
Closed
fix(core): Preserve OpenAI APIPromise methods like withResponse()#18402Sai-Tom wants to merge 5 commits intogetsentry:developfrom
Sai-Tom wants to merge 5 commits intogetsentry:developfrom
Conversation
The OpenAI SDK returns APIPromise objects with additional methods like .withResponse(). The previous async/await instrumentation converted these to regular Promises, losing those methods. Use Proxy + handleCallbackErrors pattern (matching anthropic-ai) to preserve the original return type.
packages/core/test/tracing/openai-integration-functions.test.ts
Outdated
Show resolved
Hide resolved
- Use startInactiveSpan instead of startSpan/startSpanManual because they internally use handleCallbackErrors which calls .then() on Promises, creating a new instance and losing APIPromise methods - Add try-catch for synchronous exceptions - Add tests for error handling (sync throw + async reject) - Update tests to match real OpenAI SDK behavior"
- Use startInactiveSpan instead of startSpan/startSpanManual because they internally use handleCallbackErrors which calls .then() on Promises, creating a new instance and losing APIPromise methods - Add try-catch for synchronous exceptions - Use .finally() to ensure span always ends even if attribute processing throws - Add tests for error handling (sync throw + async reject) - Update tests to match real OpenAI SDK behavior
Comment on lines
202
to
210
| const span = startInactiveSpan({ | ||
| name: `${operationName} ${model}`, | ||
| op: getSpanOperation(methodPath), | ||
| attributes: requestAttributes as Record<string, SpanAttributeValue>, | ||
| }); | ||
|
|
||
| if (options.recordInputs && params) { | ||
| addRequestAttributes(span, params); | ||
| } |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
RulaKhaled
reviewed
Dec 9, 2025
Member
RulaKhaled
left a comment
There was a problem hiding this comment.
Thank you for contributing! I have a question
| // We use startInactiveSpan instead of startSpan/startSpanManual because those | ||
| // internally use handleCallbackErrors which calls .then() on Promises, creating | ||
| // a new Promise instance and losing APIPromise's custom methods like .withResponse(). | ||
| const span = startInactiveSpan({ |
Member
There was a problem hiding this comment.
Have you tried using start span here?
I understand that your purpose here is to use handleCallbackErrors and handle promises, you can still achieve this with start span, and as long as we didn't end the span in a different scope/context, it should work fine.
Member
|
Closing in favor of #19122 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The OpenAI SDK returns
APIPromiseobjects with additional methods like.withResponse().The previous
async/awaitinstrumentation converted these to regular Promises, losing those methods.This PR uses
Proxy+handleCallbackErrorspattern (matchinganthropic-ai) to preserve the original return type.Changes
Proxyinstead ofasync functionwrapperhandleCallbackErrorsfor non-streaming responses (preserves Promise subclass)handleStreamingErrorhelper for consistencyAPIPromise.withResponse()preservationTest Plan
yarn build:devpassesyarn testpassesyarn lintpasses