-
Notifications
You must be signed in to change notification settings - Fork 838
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
[node-sdk] Missing @opentelemetry/exporter-jaeger raises an error on Next.js app #4297
Comments
Encountering the same issue with next.js app.
|
I am encountering this as well. I think the core issue is that the attempt to lazy load |
UPDATE: I was able to work around these issues for my server components in nextjs by adding this to my nextjs.config.js file: experimental: { In my case, all of the OpenTelemetry stuff was already isolated in an NPM package, so I just added that to the stanza above. If you are directly importing the OTel libraries, you may need to specify multiple modules here. My understanding is that this directive tells Next not to bundle the given library, avoiding webpack and avoiding all of the errors from dynamic loading. |
I forgot to update:
What happened on my side is that I've put register function in a condition based on NEXT_RUNTIME and one other var we care about but... not the import. It's actually important to import conditionally as well, as some OTel stuff will initialize in the background the moment it's require'd, We've moved our OTel registration stuff to a separate file that we import conditionally based on runtime and it works fine now. Spans from next.js are really weird and I'm to this day not sure if I can get any useful info from them on my own but it does work. |
I tried @djboulia's approach, but it didn't work for me, unfortunately. However, since I submitted this issue, Vercel has updated their @vercel/otel library to allow for more configuration. This is what I needed to configure a Honeycomb.io exporter. So I ended up with an hybrid of @lewinskimaciej's solution and Next's automated setup. It looks something like this: In import { settings } from '@/config'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import { registerOTel } from '@vercel/otel'
export async function register() {
if (settings.DISABLE_OTEL) {
console.info('OpenTelemetry is disabled')
return
}
if (process.env.NEXT_RUNTIME === 'nodejs') {
const { getProcessor } = await import('./instrumentation.node')
registerOTel({
serviceName: settings.SERVICE_NAME,
attributes: {
[SemanticResourceAttributes.SERVICE_NAMESPACE]: settings.PROJECT_NAME
},
spanProcessors: [getProcessor()]
})
}
} And in import { settings } from '@/config'
import * as grpc from '@grpc/grpc-js'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
import {
BatchSpanProcessor,
ConsoleSpanExporter,
SimpleSpanProcessor,
type SpanProcessor
} from '@opentelemetry/sdk-trace-base'
export function getProcessor(): SpanProcessor {
if (settings.HONEYCOMB_API_KEY) {
const metadata = new grpc.Metadata()
metadata.set('x-honeycomb-team', settings.HONEYCOMB_API_KEY)
const exporter = new OTLPTraceExporter({
url: 'grpc://api.honeycomb.io:443/',
credentials: grpc.credentials.createSsl(),
metadata
})
// Values from https://github.com/honeycombio/intro-to-o11y-nodejs/blob/main/src/tracing.js
return new BatchSpanProcessor(exporter, {
maxQueueSize: 16000,
maxExportBatchSize: 1000,
scheduledDelayMillis: 500
})
}
console.info('Using console exporter')
return new SimpleSpanProcessor(new ConsoleSpanExporter())
} I still need to Node-only conditional import, because Hope that can help folks navigate this issue. |
This saved me! Thank you so much 🚀 |
alternative solution, you might find it useful -
export async function register() {
console.log('registering instrumentation');
const { NodeSDK } = await import('@opentelemetry/sdk-node');
const { ConsoleSpanExporter } = await import('@opentelemetry/sdk-trace-node');
const { getNodeAutoInstrumentations } = await import(
'@opentelemetry/auto-instrumentations-node'
);
const { PeriodicExportingMetricReader, ConsoleMetricExporter } = await import(
'@opentelemetry/sdk-metrics'
);
const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-grpc': { enabled: false },
}),
],
metricReader: new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
}),
});
sdk.start();
}
const { NormalModuleReplacementPlugin } = require('webpack');
const path = require('path');
const nextConfig = {
experimental: {
instrumentationHook: true,
},
webpack: (config, options) => {
return {
...config,
plugins: [
...config.plugins,
new NormalModuleReplacementPlugin(
/@opentelemetry\/exporter-jaeger/,
path.resolve(path.join(__dirname, './polyfills.js'))
),
],
resolve: {
...config.resolve,
fallback: {
...config.resolve.fallback,
stream: false,
zlib: false,
http: false,
tls: false,
net: false,
http2: false,
dns: false,
os: false,
fs: false,
path: false,
https: false,
},
},
};
},
};
module.exports = () => {}; |
I'm not using vercel otel configuration but manual config. Is there a fix for this? |
This is how I fixed it. I just had to prevent auto-instrumentation and sdk-node from server components. /** @type {import("next").NextConfig} */
const config = {
reactStrictMode: true,
experimental: {
instrumentationHook: true,
serverComponentsExternalPackages: [
"@opentelemetry/auto-instrumentations-node",
"@opentelemetry/sdk-node",
],
},
} |
1 similar comment
This is how I fixed it. I just had to prevent auto-instrumentation and sdk-node from server components. /** @type {import("next").NextConfig} */
const config = {
reactStrictMode: true,
experimental: {
instrumentationHook: true,
serverComponentsExternalPackages: [
"@opentelemetry/auto-instrumentations-node",
"@opentelemetry/sdk-node",
],
},
} |
Does anyone know why this works? They have a default list here: https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/server-external-packages.json Should this be included there to prevent further issues for those who are rolling their own without vercel/otel? |
The experimental.serverComponentsExternalPackages has been deprecated and replaced by: |
@aurorascharff have you gotten next 15 to work? What's in your array? I'm getting this error but I don't see anyone talking about it:
|
@shawnmclean This is in my array, it's working now in Next.js 15. serverExternalPackages: [ |
@aurorascharff Thank you! My missing one was instrumentation. So it seems if that is missing, I get the error above and also there will be some HMR issues when recovering from a server crash. Mine: serverExternalPackages: [
"@opentelemetry/sdk-node",
"@opentelemetry/instrumentation",
"pino",
], I didn't want to put things in there thats not needed, I'm not sure what the downside of that will be. |
What happened?
Steps to Reproduce
Create a basic Next.js app and follow the steps to manually add OpenTelemetry to the application.
Use the OpenTelemetry setup code below. Don't set any environment variables, so that a
ConsoleSpanExporter
gets configured.Start the dev server (
npm run dev
) and launch the app.Expected Result
I see the default OpenTelemetry spans from my request in the console.
Actual Result
I get an error message from a failed import:
Can't resolve '@opentelemetry/exporter-jaeger'
. See the full trace below.Additional Details
It looks like
node-sdk
importsTracerProviderWithEnvExporters
. As a side effect of which, aMap
of registered providers is built that assumes Jaeger is available and throws an error if it isn't. Since the dependency was removed in v0.44, the error gets thrown.Edit:
Note that I'm not using Jaeger.
I'll add the dependency to solve the error, but I would rather not have to include it at all.I can't include@opentelemetry/exporter-jaeger
in my project because #3759 happens.OpenTelemetry Setup Code
package.json
Relevant log output
The text was updated successfully, but these errors were encountered: