Skip to content

Commit 4940dd8

Browse files
authored
fix(node): Vendor InstrumentationNodeModuleFile to fix Bun --bytecode crash (#21262)
`InstrumentationNodeModuleFile` from `@opentelemetry/instrumentation` resolves `path.normalize`. When Bun's `--bytecode` compiler inlines the module tree into a single flat bundle, it renames `normalize` to `normalize4` and then loses the scope binding in bytecode compilation, producing a `ReferenceError` at runtime. Vendor a local `InstrumentationNodeModuleFile` class that calls `path.normalize()` directly, replacing the import from `@opentelemetry/instrumentation` in all vendored instrumentations within `@sentry/node`. Closes #21256
1 parent f1b3a7e commit 4940dd8

19 files changed

Lines changed: 141 additions & 28 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ jobs:
984984
node-version-file: 'dev-packages/e2e-tests/test-applications/${{ matrix.test-application }}/package.json'
985985
- name: Set up Bun
986986
if:
987-
contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "elysia-bun", "hono-4"]'),
987+
contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "elysia-bun", "hono-4", "bun-bytecode"]'),
988988
matrix.test-application)
989989
uses: oven-sh/setup-bun@v2
990990
with:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "bun-bytecode-test",
3+
"version": "1.0.0",
4+
"private": true,
5+
"scripts": {
6+
"clean": "npx rimraf node_modules pnpm-lock.yaml dist",
7+
"test:build": "pnpm install && bun build src/main.ts --compile --bytecode --format=esm --outfile dist/main",
8+
"test:assert": "dist/main"
9+
},
10+
"dependencies": {
11+
"@sentry/bun": "file:../../packed/sentry-bun-packed.tgz"
12+
},
13+
"devDependencies": {
14+
"bun-types": "^1.2.9"
15+
},
16+
"volta": {
17+
"extends": "../../package.json"
18+
}
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Verifies that @sentry/bun can be compiled with `bun build --compile --bytecode` without crashing at runtime.
3+
*/
4+
import * as Sentry from '@sentry/bun';
5+
6+
Sentry.init({
7+
dsn: 'https://username@domain/123',
8+
tracesSampleRate: 0,
9+
});
10+
11+
console.log('Bun bytecode compilation: OK');
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"types": ["bun-types"],
4+
"strict": true,
5+
"module": "ESNext",
6+
"moduleResolution": "bundler",
7+
"target": "ESNext"
8+
},
9+
"include": ["src"]
10+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* NOTICE from the Sentry authors:
17+
* - Vendored locally from @opentelemetry/instrumentation to work around a Bun
18+
* --bytecode bug (https://github.com/getsentry/sentry-javascript/issues/21256).
19+
* - The upstream class imports `normalize` via an indirect platform/index
20+
* re-export chain, which Bun's bytecode bundler renames and loses scope for.
21+
* - This copy imports `normalize` directly from 'path' to break that chain.
22+
*/
23+
/* oxlint-disable */
24+
25+
import { normalize } from 'path';
26+
import type { InstrumentationModuleFile } from '@opentelemetry/instrumentation';
27+
28+
export class InstrumentationNodeModuleFile implements InstrumentationModuleFile {
29+
public name: string;
30+
public supportedVersions: string[];
31+
public patch: (moduleExports: any, moduleVersion?: string) => any;
32+
public unpatch: (moduleExports?: any, moduleVersion?: string) => void;
33+
34+
constructor(
35+
name: string,
36+
supportedVersions: string[],
37+
patch: (moduleExports: any, moduleVersion?: string) => any,
38+
unpatch: (moduleExports?: any, moduleVersion?: string) => void,
39+
) {
40+
this.name = normalize(name);
41+
this.supportedVersions = supportedVersions;
42+
this.patch = patch;
43+
this.unpatch = unpatch;
44+
}
45+
}

packages/node/src/integrations/tracing/amqplib/vendored/amqplib.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ import { timestampInSeconds } from '@sentry/core';
3535
import {
3636
InstrumentationBase,
3737
InstrumentationNodeModuleDefinition,
38-
InstrumentationNodeModuleFile,
3938
isWrapped,
4039
safeExecuteInTheMiddle,
4140
SemconvStability,
4241
semconvStabilityFromStr,
4342
} from '@opentelemetry/instrumentation';
43+
import { InstrumentationNodeModuleFile } from '../../InstrumentationNodeModuleFile';
4444
import { ATTR_MESSAGING_OPERATION } from './semconv';
4545
import {
4646
ATTR_MESSAGING_DESTINATION,

packages/node/src/integrations/tracing/firebase/otel/patches/firestore.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import * as net from 'node:net';
22
import type { Span, Tracer } from '@opentelemetry/api';
33
import { context, diag, SpanKind, trace } from '@opentelemetry/api';
4-
import {
5-
InstrumentationNodeModuleDefinition,
6-
InstrumentationNodeModuleFile,
7-
isWrapped,
8-
safeExecuteInTheMiddle,
9-
} from '@opentelemetry/instrumentation';
4+
import { InstrumentationNodeModuleDefinition, isWrapped, safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';
5+
import { InstrumentationNodeModuleFile } from '../../../InstrumentationNodeModuleFile';
106
import {
117
ATTR_DB_COLLECTION_NAME,
128
ATTR_DB_NAMESPACE,

packages/node/src/integrations/tracing/firebase/otel/patches/functions.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import type { Span, Tracer } from '@opentelemetry/api';
22
import { context, diag, SpanKind, trace } from '@opentelemetry/api';
33
import type { InstrumentationBase } from '@opentelemetry/instrumentation';
4-
import {
5-
InstrumentationNodeModuleDefinition,
6-
InstrumentationNodeModuleFile,
7-
isWrapped,
8-
safeExecuteInTheMiddle,
9-
} from '@opentelemetry/instrumentation';
4+
import { InstrumentationNodeModuleDefinition, isWrapped, safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';
5+
import { InstrumentationNodeModuleFile } from '../../../InstrumentationNodeModuleFile';
106
import type { SpanAttributes } from '@sentry/core';
117
import type { FirebaseInstrumentation } from '../firebaseInstrumentation';
128
import type {

packages/node/src/integrations/tracing/google-genai/instrumentation.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation';
2-
import {
3-
InstrumentationBase,
4-
InstrumentationNodeModuleDefinition,
5-
InstrumentationNodeModuleFile,
6-
} from '@opentelemetry/instrumentation';
2+
import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
3+
import { InstrumentationNodeModuleFile } from '../InstrumentationNodeModuleFile';
74
import type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';
85
import {
96
_INTERNAL_shouldSkipAiProviderWrapping,

packages/node/src/integrations/tracing/graphql/vendored/instrumentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import {
2626
isWrapped,
2727
InstrumentationBase,
2828
InstrumentationNodeModuleDefinition,
29-
InstrumentationNodeModuleFile,
3029
safeExecuteInTheMiddle,
3130
} from '@opentelemetry/instrumentation';
31+
import { InstrumentationNodeModuleFile } from '../../InstrumentationNodeModuleFile';
3232
import type {
3333
DefinitionNode,
3434
DocumentNode,

0 commit comments

Comments
 (0)