Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDK fails in ESM mode in combination with openai #12414

Open
3 tasks done
Tracked by #12485 ...
Xhale1 opened this issue Jun 7, 2024 · 36 comments
Open
3 tasks done
Tracked by #12485 ...

SDK fails in ESM mode in combination with openai #12414

Xhale1 opened this issue Jun 7, 2024 · 36 comments
Assignees
Labels

Comments

@Xhale1
Copy link

Xhale1 commented Jun 7, 2024

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/node

SDK Version

8.8.0

Framework Version

Node 20.14.0

Link to Sentry event

https://trainwell.sentry.io/issues/5463070600/?project=6067364&query=is%3Aunresolved+issue.priority%3A%5Bhigh%2C+medium%5D&referrer=issue-stream&statsPeriod=14d&stream_index=1

SDK Setup

Sentry.init({
  dsn: "[REDACTED]",
});

Steps to Reproduce

  1. Add openai package
  2. Instrument using instrumentation.js file
  3. Run with node --import ./dist/instrumentation.js dist/index.js

The addition of the following code is what triggers the issue:

import OpenAI from "openai";

const openAI = new OpenAI({
  apiKey: "[REDACTED]",
});

Expected Result

App builds with sentry instrumentation and no errors.

Actual Result

I receive the following error:

TypeError: API.Completions is not a constructor
    at new OpenAI (file:///[REDACTED]/node_modules/.pnpm/[email protected]/node_modules/openai/index.mjs:46:28)
    at file:///[REDACTED]
    at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:123:5)

This might be related to #12237 however it appears to be a unique issue unrelated to initialization.

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jun 7, 2024
@github-actions github-actions bot added the Package: node Issues related to the Sentry Node SDK label Jun 7, 2024
@Lms24
Copy link
Member

Lms24 commented Jun 10, 2024

Hey @Xhale1 thanks for reporting!

Just to rule something out: Which version of openai are you using? It seems there were related issues in an older version. Thanks!

@hudovisk
Copy link

Same issue here, using openai: 4.47.3

"openai": "^4.47.3",

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jun 10, 2024
@Xhale1
Copy link
Author

Xhale1 commented Jun 10, 2024

Thanks for checking in! Just confirmed that my issue exists with version 4.49.1 which appears to be the latest offered by openai.

Let me know if a reproduction repo would help

@Lms24
Copy link
Member

Lms24 commented Jun 10, 2024

A reproduction would be greatly appreciated, thanks :)

@Xhale1
Copy link
Author

Xhale1 commented Jun 10, 2024

This is my first time making an issue reproduction repo, let me know if it works for you: https://github.com/Xhale1/sentry-openai

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jun 10, 2024
@Lms24
Copy link
Member

Lms24 commented Jun 10, 2024

Hmm yeah, I can reproduce this myself, thanks for the excellent repro app!

I already tried switching the import style to namespace or named import but it doesn't matter. Looks like for some reason API.Completions within the OpenAI package is undefined rather than a class. My bet is that import-in-the-middle plays a role here. Also I wonder if IITM doesn't handle namespace imports within node_modules correctly. Not sure though.

Update: Narrowed it down to the import * as API from "./resources/index.mjs"
statement in /[email protected]/node_modules/openai/index.mjs. For some reason, this doesn't include Completions.

@timfish when you have a minute, would you mind taking a look?

@timfish
Copy link
Collaborator

timfish commented Jun 12, 2024

It looks like openai/resources/index.mjs exports two different Completions classes, one for /completions and one for /chat/completions.

For import-in-the-middle we deduced that for ESM, duplicate named exports were not exported at all but that doesn't appear to be the case here.

@NatoBoram
Copy link

I made a minimal reproduction here:

It shows that all you have to do to make your app crash is new OpenAI({ apiKey: OPENAI_API_KEY }) when both Sentry and OpenAI are installed and Sentry is preloaded with --import @sentry/node/preload.

@timfish
Copy link
Collaborator

timfish commented Aug 12, 2024

IIRC we couldn't come up with a solution for the export pattern that openai uses in their package right? Or did I miss something.

I seem to remember it being caused by this issue which is a fundamental problem with import-in-the-middle.

@timfish
Copy link
Collaborator

timfish commented Sep 9, 2024

v8.29.0 of the Node SDK adds the new onlyIncludeInstrumentedModules option to registerEsmLoaderHooks.

import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: '__PUBLIC_DSN__',
  registerEsmLoaderHooks: { onlyIncludeInstrumentedModules: true },
});

When set to true, import-in-the-middle will only wrap ESM modules that are specifically instrumented by OpenTelemetry plugins. This is useful to avoid issues where import-in-the-middle is not compatible with some of your dependencies.

This feature will only work if you Sentry.init() the SDK before the instrumented modules are loaded. This can be achieved via the Node --register and --import CLI flags or by loading your app code via async import() after calling Sentry.init().

Please let me know if this helps solve the import-in-the-middle incompatibility issues you are experiencing!

@torickjdavis
Copy link

torickjdavis commented Sep 9, 2024

@timfish, it seems that the option added in v8.29.0 is onlyIncludeInstrumentedModules:

onlyIncludeInstrumentedModules?: boolean;

For others: there's also relevant issue for the OpenAI package with some additional discussion: openai/openai-node#903. And a PR for import-in-the-middle to try and add tests for this case: nodejs/import-in-the-middle#113

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Sep 9, 2024
@timfish
Copy link
Collaborator

timfish commented Sep 9, 2024

Oh wow, thanks @torickjdavis, that means the release notes are wrong too. I'll correct these!

@Xhale1
Copy link
Author

Xhale1 commented Sep 9, 2024

Haha, I was a bit confused by the release notes too, thanks for the quick fix! (and thanks for your work here as always!)

Off topic so feel free to disregard: how confident do you and the team feel in the Sentry + ESM stability now that this new option is released? Seems #12806 might be pretty much squared away?

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Sep 9, 2024
@torickjdavis
Copy link

🚀 Awesome! I really should look, but haven't yet for Sentry's documentation process, but relevant documentation for onlyIncludeInstrumentedModules should probably be added as another option for skipping instrumentation across the different guides.

@timfish
Copy link
Collaborator

timfish commented Sep 9, 2024

how confident do you and the team feel in the Sentry + ESM stability now that this new option is released?

This new option negates all of the fundamental (and not-fixable) issues we've found with import-in-the-middle which have been the major pain points. If you use this option and ensure you init the SDK (and therefore the otel instrumentations) before you app code is loaded, import-in-the-middle should no longer cause problems.

There is a proposal for new loader hooks so this will likely continue to be a moving target.

relevant documentation for onlyIncludeInstrumentedModules should probably be added as another option

We plan to add this to the documentation, we're just trying it out in apps ourselves and waiting for confirmation from more users that it is in fact solving the issues it was suppoed to.

Sentry want it to be as simple and painless as possible to start using the SDKs so we are still left with things we want to improve here. This fix is currently opt-in which is far from ideal. It's not clear from the original error above that this new option will help here!

@getsantry getsantry bot removed the status in GitHub Issues with 👀 3 Sep 9, 2024
mydea pushed a commit that referenced this issue Sep 10, 2024
I failed to update the description in my PR when we improved the
property name after some discussion in the PR, so the wrong property
name was used in the changelog:


https://github.com/getsentry/sentry-javascript/blob/bcf571d9954094be76a99edbb12c23eff7f7b5dc/packages/node/src/types.ts#L20

Thanks to @torickjdavis for reporting this
[here](#12414 (comment))!
@Xhale1
Copy link
Author

Xhale1 commented Oct 17, 2024

Hello! I'm sorry for not closing the loop here earlier.

Using the onlyIncludeInstrumentedModules option is working great and has solved the original issue! I'm also happy to report my team has fully migrated to v8 thanks to this option 🎉

I'll leave this issue open on the oft chance @timfish wants to use it to track openai compatibility without this option, but feel free to close whenever you see fit :)

Thank you everyone for your dedication to this issue and to the larger open source community :)

@Ivan-juni
Copy link

How can i use onlyIncludeInstrumentedModules with the late initialization (preload)?

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Nov 15, 2024
@andreiborza
Copy link
Member

andreiborza commented Nov 18, 2024

@Ivan-juni you currently can't but we could provide that option via an env variable. I added this to our backlog: #14330

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: No status
Development

No branches or pull requests