Using the following tracing enabling script from OpenTelemetry docs:
const opentelemetry = require("@opentelemetry/sdk-node");
const { getNodeAutoInstrumentations } = require("@opentelemetry/auto-instrumentations-node");
const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
// For troubleshooting, set the log level to DiagLogLevel.DEBUG
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
const sdk = new opentelemetry.NodeSDK({
traceExporter: new opentelemetry.tracing.ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start()
running my Next.js server as I thought is required, I get an error:
$ node --require './tracing/opentelemetry.js' ./node_modules/next/dist/bin/next start -p 3000
No modules instrumentation has been defined, nothing will be patched
@opentelemetry/instrumentation-grpc Module @grpc/grpc-js has been loaded before @opentelemetry/instrumentation-grpc so it might not work, please initialize it before requiring @grpc/grpc-js
Exporter "otlp" requested through environment variable is unavailable.
/mnt/vol/.local/share/pnpm/global/5/.pnpm/next@12.1.5_zpnidt7m3osuk7shl3s4oenomq/node_modules/next/dist/lib/get-project-dir.js:40
const realDir = _fs.default.realpathSync.native(resolvedDir);
^
TypeError: _fs.default.realpathSync.native is not a function
at Object.getProjectDir (/mnt/vol/.local/share/pnpm/global/5/.pnpm/next@12.1.5_zpnidt7m3osuk7shl3s4oenomq/node_modules/next/dist/lib/get-project-dir.js:40:50)
at nextStart (/mnt/vol/.local/share/pnpm/global/5/.pnpm/next@12.1.5_zpnidt7m3osuk7shl3s4oenomq/node_modules/next/dist/cli/next-start.js:80:37)
at /mnt/vol/.local/share/pnpm/global/5/.pnpm/next@12.1.5_zpnidt7m3osuk7shl3s4oenomq/node_modules/next/dist/bin/next:141:34
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Node.js v17.8.0
Now this can be simplified to a minimal reproduction as follows. This has the fs.realpathSync.native
function:
$ node -e 'console.log(require("fs").realpathSync)'
[Function: realpathSync] { native: [Function (anonymous)] }
This doesn't have fs.realpathSync.native
:
$ node --require ./tracing/opentelemetry.js -e 'console.log(require("fs").realpathSync)'
No modules instrumentation has been defined, nothing will be patched
@opentelemetry/instrumentation-grpc Module @grpc/grpc-js has been loaded before @opentelemetry/instrumentation-grpc so it might not work, please initialize it before requiring @grpc/grpc-js
[Function (anonymous)]
Exporter "otlp" requested through environment variable is unavailable.
My Node's --require
is working correctly (noop.js
is an empty file):
$ node --require ./tracing/noop.js -e 'console.log(require("fs").realpathSync)'
[Function: realpathSync] { native: [Function (anonymous)] }
Why would the OpenTelemetry setup script break the fs
module?
$ node --version
v17.8.0
//package.json dependencies
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/auto-instrumentations-node": "^0.35.0",
"@opentelemetry/sdk-node": "^0.34.0",
$ uname -a
Linux code-server 5.15.0-1025-oracle #31~20.04.2-Ubuntu SMP Tue Nov 29 13:01:56 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux
Does my ARM machine have something to do with it?
I can reproduce the same on x86_64 on https://replit.com/@JakubKoralewski/opentelemetry-repro with the same behavior.
The reason this error occurs is due to a bug in @opentelemetry/instrumentation-fs
introduced as a new dependency to @opentelemetry/auto-instrumentations-node
in PR #981 which got released with version 0.34.0
. The issue was reported but at the time of writing is still open. However, as also already linked above a PR to address the issue is being reviewed.
Fow now, I see three ways to address the problem:
@opentelemetry/auto-instrumentations-node
to next lower version 0.33.1
.getNodeAutoInstrumentations()
with getNodeAutoInstrumentations({ '@opentelemetry/instrumentation-fs': { enabled: false } })
in your code. Given that your project is in Next.js and you likely have little file system activity aside from maybe public files this is likely the best option for now.@opentelemetry/auto-instrumentations-node
altogether and simply instrument the libraries you actually use. Using the auto instrumentation for Node.js pulls in a lot of transitive dependencies. Say you have a Next.js app, connect to a Postgres database and use winston for logging your instrumentation setup could look something like this:const sdk = new opentelemetry.NodeSDK({
traceExporter: new opentelemetry.tracing.ConsoleSpanExporter(),
instrumentations: [
// new FsInstrumentation(), TODO: re-enable once bug is fixed
new HttpInstrumentation(),
new PgInstrumentation(),
new WinstonInstrumentation(),
]
});