From 723f246467e21af853e346fdeba4ea3b3c50d4f7 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 15 May 2026 21:42:26 +0200 Subject: [PATCH 1/4] ref(node): Vendor generic-pool instrumentation Closes https://github.com/getsentry/sentry-javascript/issues/20145 Co-Authored-By: Claude Opus 4.6 (1M context) --- .oxlintrc.base.json | 6 + packages/node/package.json | 1 - .../{genericPool.ts => genericPool/index.ts} | 2 +- .../genericPool/vendored/instrumentation.ts | 187 ++++++++++++++++++ yarn.lock | 7 - 5 files changed, 194 insertions(+), 9 deletions(-) rename packages/node/src/integrations/tracing/{genericPool.ts => genericPool/index.ts} (95%) create mode 100644 packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts diff --git a/.oxlintrc.base.json b/.oxlintrc.base.json index da50021f4431..6b2763a699f1 100644 --- a/.oxlintrc.base.json +++ b/.oxlintrc.base.json @@ -140,6 +140,12 @@ "no-bitwise": "off" } }, + { + "files": ["**/integrations/tracing/genericPool/vendored/**/*.ts"], + "rules": { + "typescript/no-explicit-any": "off" + } + }, { "files": ["**/scenarios/**", "**/rollup-utils/**"], "rules": { diff --git a/packages/node/package.json b/packages/node/package.json index 5e74867a0a88..1e3335826147 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -72,7 +72,6 @@ "@opentelemetry/instrumentation-connect": "0.57.0", "@opentelemetry/instrumentation-dataloader": "0.31.0", "@opentelemetry/instrumentation-fs": "0.33.0", - "@opentelemetry/instrumentation-generic-pool": "0.57.0", "@opentelemetry/instrumentation-graphql": "0.62.0", "@opentelemetry/instrumentation-hapi": "0.60.0", "@opentelemetry/instrumentation-http": "0.214.0", diff --git a/packages/node/src/integrations/tracing/genericPool.ts b/packages/node/src/integrations/tracing/genericPool/index.ts similarity index 95% rename from packages/node/src/integrations/tracing/genericPool.ts rename to packages/node/src/integrations/tracing/genericPool/index.ts index 811913f31587..a9b7e94d56d9 100644 --- a/packages/node/src/integrations/tracing/genericPool.ts +++ b/packages/node/src/integrations/tracing/genericPool/index.ts @@ -1,4 +1,4 @@ -import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool'; +import { GenericPoolInstrumentation } from './vendored/instrumentation'; import type { IntegrationFn } from '@sentry/core'; import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON } from '@sentry/core'; import { generateInstrumentOnce, instrumentWhenWrapped } from '@sentry/node-core'; diff --git a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts new file mode 100644 index 000000000000..bb8399a22030 --- /dev/null +++ b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts @@ -0,0 +1,187 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NOTICE from the Sentry authors: + * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-generic-pool + * - Upstream version: @opentelemetry/instrumentation-generic-pool@0.61.0 + * - Minor TypeScript strictness adjustments for this repository's compiler settings + */ +/* eslint-disable */ + +import * as api from '@opentelemetry/api'; +import { + InstrumentationBase, + InstrumentationConfig, + InstrumentationNodeModuleDefinition, + isWrapped, +} from '@opentelemetry/instrumentation'; + +import type * as genericPool from 'generic-pool'; + +import { SDK_VERSION } from '@sentry/core'; + +const MODULE_NAME = 'generic-pool'; +const PACKAGE_NAME = '@sentry/instrumentation-generic-pool'; + +export class GenericPoolInstrumentation extends InstrumentationBase { + // only used for v2 - v2.3) + private _isDisabled = false; + + constructor(config: InstrumentationConfig = {}) { + super(PACKAGE_NAME, SDK_VERSION, config); + } + + init() { + return [ + new InstrumentationNodeModuleDefinition( + MODULE_NAME, + ['>=3.0.0 <4'], + moduleExports => { + const Pool: any = moduleExports.Pool; + if (isWrapped(Pool.prototype.acquire)) { + this._unwrap(Pool.prototype, 'acquire'); + } + this._wrap( + Pool.prototype, + 'acquire', + this._acquirePatcher.bind(this) + ); + return moduleExports; + }, + moduleExports => { + const Pool: any = moduleExports.Pool; + this._unwrap(Pool.prototype, 'acquire'); + return moduleExports; + } + ), + new InstrumentationNodeModuleDefinition( + MODULE_NAME, + ['>=2.4.0 <3'], + moduleExports => { + const Pool: any = moduleExports.Pool; + if (isWrapped(Pool.prototype.acquire)) { + this._unwrap(Pool.prototype, 'acquire'); + } + this._wrap( + Pool.prototype, + 'acquire', + this._acquireWithCallbacksPatcher.bind(this) + ); + return moduleExports; + }, + moduleExports => { + const Pool: any = moduleExports.Pool; + this._unwrap(Pool.prototype, 'acquire'); + return moduleExports; + } + ), + new InstrumentationNodeModuleDefinition( + MODULE_NAME, + ['>=2.0.0 <2.4'], + moduleExports => { + this._isDisabled = false; + if (isWrapped(moduleExports.Pool)) { + this._unwrap(moduleExports, 'Pool'); + } + this._wrap(moduleExports, 'Pool', this._poolWrapper.bind(this)); + return moduleExports; + }, + moduleExports => { + // since the object is created on the fly every time, we need to use + // a boolean switch here to disable the instrumentation + this._isDisabled = true; + return moduleExports; + } + ), + ]; + } + + private _acquirePatcher(original: genericPool.Pool['acquire']) { + const instrumentation = this; + return function wrapped_acquire( + this: genericPool.Pool, + ...args: any[] + ) { + const parent = api.context.active(); + const span = instrumentation.tracer.startSpan( + 'generic-pool.acquire', + {}, + parent + ); + + return api.context.with(api.trace.setSpan(parent, span), () => { + return original.call(this, ...args).then( + (value: unknown) => { + span.end(); + return value; + }, + (err: unknown) => { + span.recordException(err as Error); + span.end(); + throw err; + } + ); + }); + }; + } + + private _poolWrapper(original: any) { + const instrumentation = this; + return function wrapped_pool(this: any) { + const pool = original.apply(this, arguments); + instrumentation._wrap( + pool, + 'acquire', + instrumentation._acquireWithCallbacksPatcher.bind(instrumentation) + ); + return pool; + }; + } + + private _acquireWithCallbacksPatcher(original: any) { + const instrumentation = this; + return function wrapped_acquire( + this: genericPool.Pool, + cb: Function, + priority: number + ) { + // only used for v2 - v2.3 + if (instrumentation._isDisabled) { + return original.call(this, cb, priority); + } + const parent = api.context.active(); + const span = instrumentation.tracer.startSpan( + 'generic-pool.acquire', + {}, + parent + ); + + return api.context.with(api.trace.setSpan(parent, span), () => { + original.call( + this, + (err: unknown, client: unknown) => { + span.end(); + // Not checking whether cb is a function because + // the original code doesn't do that either. + if (cb) { + return cb(err, client); + } + }, + priority + ); + }); + }; + } +} diff --git a/yarn.lock b/yarn.lock index 08c5b05e7a86..92d3342eeab4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6231,13 +6231,6 @@ "@opentelemetry/core" "^2.0.0" "@opentelemetry/instrumentation" "^0.214.0" -"@opentelemetry/instrumentation-generic-pool@0.57.0": - version "0.57.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.57.0.tgz#4220a2fc1974b40a989171a9b5f3d1eeab92683f" - integrity sha512-orhmlaK+ZIW9hKU+nHTbXrCSXZcH83AescTqmpamHRobRmYSQwRbD0a1odc0yAzuzOtxYiHiXAnpnIpaSSY7Ow== - dependencies: - "@opentelemetry/instrumentation" "^0.214.0" - "@opentelemetry/instrumentation-graphql@0.62.0": version "0.62.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.62.0.tgz#dc2fc92c6be331c4f95b62a40983c8aedb8f9bf9" From 617f19dd0d747ec28c1b72c8ef5581c3c46ddb4c Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 15 May 2026 21:44:46 +0200 Subject: [PATCH 2/4] yarn fix --- .../genericPool/vendored/instrumentation.ts | 51 +++++-------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts index bb8399a22030..230933eee91d 100644 --- a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts +++ b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts @@ -53,18 +53,14 @@ export class GenericPoolInstrumentation extends InstrumentationBase { if (isWrapped(Pool.prototype.acquire)) { this._unwrap(Pool.prototype, 'acquire'); } - this._wrap( - Pool.prototype, - 'acquire', - this._acquirePatcher.bind(this) - ); + this._wrap(Pool.prototype, 'acquire', this._acquirePatcher.bind(this)); return moduleExports; }, moduleExports => { const Pool: any = moduleExports.Pool; this._unwrap(Pool.prototype, 'acquire'); return moduleExports; - } + }, ), new InstrumentationNodeModuleDefinition( MODULE_NAME, @@ -74,18 +70,14 @@ export class GenericPoolInstrumentation extends InstrumentationBase { if (isWrapped(Pool.prototype.acquire)) { this._unwrap(Pool.prototype, 'acquire'); } - this._wrap( - Pool.prototype, - 'acquire', - this._acquireWithCallbacksPatcher.bind(this) - ); + this._wrap(Pool.prototype, 'acquire', this._acquireWithCallbacksPatcher.bind(this)); return moduleExports; }, moduleExports => { const Pool: any = moduleExports.Pool; this._unwrap(Pool.prototype, 'acquire'); return moduleExports; - } + }, ), new InstrumentationNodeModuleDefinition( MODULE_NAME, @@ -103,23 +95,16 @@ export class GenericPoolInstrumentation extends InstrumentationBase { // a boolean switch here to disable the instrumentation this._isDisabled = true; return moduleExports; - } + }, ), ]; } private _acquirePatcher(original: genericPool.Pool['acquire']) { const instrumentation = this; - return function wrapped_acquire( - this: genericPool.Pool, - ...args: any[] - ) { + return function wrapped_acquire(this: genericPool.Pool, ...args: any[]) { const parent = api.context.active(); - const span = instrumentation.tracer.startSpan( - 'generic-pool.acquire', - {}, - parent - ); + const span = instrumentation.tracer.startSpan('generic-pool.acquire', {}, parent); return api.context.with(api.trace.setSpan(parent, span), () => { return original.call(this, ...args).then( @@ -131,7 +116,7 @@ export class GenericPoolInstrumentation extends InstrumentationBase { span.recordException(err as Error); span.end(); throw err; - } + }, ); }); }; @@ -141,32 +126,20 @@ export class GenericPoolInstrumentation extends InstrumentationBase { const instrumentation = this; return function wrapped_pool(this: any) { const pool = original.apply(this, arguments); - instrumentation._wrap( - pool, - 'acquire', - instrumentation._acquireWithCallbacksPatcher.bind(instrumentation) - ); + instrumentation._wrap(pool, 'acquire', instrumentation._acquireWithCallbacksPatcher.bind(instrumentation)); return pool; }; } private _acquireWithCallbacksPatcher(original: any) { const instrumentation = this; - return function wrapped_acquire( - this: genericPool.Pool, - cb: Function, - priority: number - ) { + return function wrapped_acquire(this: genericPool.Pool, cb: Function, priority: number) { // only used for v2 - v2.3 if (instrumentation._isDisabled) { return original.call(this, cb, priority); } const parent = api.context.active(); - const span = instrumentation.tracer.startSpan( - 'generic-pool.acquire', - {}, - parent - ); + const span = instrumentation.tracer.startSpan('generic-pool.acquire', {}, parent); return api.context.with(api.trace.setSpan(parent, span), () => { original.call( @@ -179,7 +152,7 @@ export class GenericPoolInstrumentation extends InstrumentationBase { return cb(err, client); } }, - priority + priority, ); }); }; From d1fc636712be00a957a833f7ecf737b32b5356f1 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 15 May 2026 21:48:55 +0200 Subject: [PATCH 3/4] ref: Remove unused eslint-disable comment from vendored code Co-Authored-By: Claude Opus 4.6 (1M context) --- .../integrations/tracing/genericPool/vendored/instrumentation.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts index 230933eee91d..7bb15476b21d 100644 --- a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts +++ b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts @@ -18,7 +18,6 @@ * - Upstream version: @opentelemetry/instrumentation-generic-pool@0.61.0 * - Minor TypeScript strictness adjustments for this repository's compiler settings */ -/* eslint-disable */ import * as api from '@opentelemetry/api'; import { From bc7605483e14d287802b9408226910d4830eba19 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Sat, 16 May 2026 11:07:07 +0200 Subject: [PATCH 4/4] ref: Restore eslint-disable comment in vendored code Co-Authored-By: Claude Opus 4.6 (1M context) --- .../integrations/tracing/genericPool/vendored/instrumentation.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts index 7bb15476b21d..230933eee91d 100644 --- a/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts +++ b/packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts @@ -18,6 +18,7 @@ * - Upstream version: @opentelemetry/instrumentation-generic-pool@0.61.0 * - Minor TypeScript strictness adjustments for this repository's compiler settings */ +/* eslint-disable */ import * as api from '@opentelemetry/api'; import {