diff --git a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts index 2a414d1a500..54b1d830e74 100644 --- a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts +++ b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts @@ -35,8 +35,7 @@ export abstract class InstrumentationBase< { private _modules: InstrumentationModuleDefinition[]; private _hooks: (Hooked | HookRequire)[] = []; - private _requireInTheMiddleSingleton: RequireInTheMiddleSingleton = - RequireInTheMiddleSingleton.getInstance(); + private _requireInTheMiddleSingleton?: RequireInTheMiddleSingleton; private _enabled = false; constructor( @@ -166,6 +165,14 @@ export abstract class InstrumentationBase< return undefined; } + private _getRequireInTheMiddleSingleton(): RequireInTheMiddleSingleton { + return ( + this._requireInTheMiddleSingleton ?? + (this._requireInTheMiddleSingleton = + RequireInTheMiddleSingleton.getInstance()) + ); + } + private _onRequire( module: InstrumentationModuleDefinition, exports: T, @@ -276,6 +283,10 @@ export abstract class InstrumentationBase< return; } + if (this._modules.length === 0) { + return; + } + this._warnOnPreloadedModules(); for (const module of this._modules) { const hookFn: HookFn = (exports, name, baseDir) => { @@ -298,7 +309,9 @@ export abstract class InstrumentationBase< // require-in-the-middle `Hook`. const hook = path.isAbsolute(module.name) ? new HookRequire([module.name], { internals: true }, onRequire) - : this._requireInTheMiddleSingleton.register(module.name, onRequire); + : this + ._getRequireInTheMiddleSingleton() + .register(module.name, onRequire); this._hooks.push(hook); const esmHook = new HookImport( diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts b/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts index 616c078f36c..1df9617e7ed 100644 --- a/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts +++ b/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts @@ -8,6 +8,7 @@ import * as sinon from 'sinon'; import * as path from 'path'; import { InstrumentationBase } from '../../src'; import type { InstrumentationModuleDefinition } from '../../src/'; +import { RequireInTheMiddleSingleton } from '../../src/platform/node/RequireInTheMiddleSingleton'; import { InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, @@ -29,6 +30,37 @@ class TestInstrumentation extends InstrumentationBase { } describe('InstrumentationBase', function () { + describe('constructor/enable without module definitions', function () { + let getInstanceStub: sinon.SinonStub; + + class EmptyInstrumentation extends InstrumentationBase { + constructor(config = {}) { + super('@opentelemetry/instrumentation-empty-test', '0.0.0', config); + } + + init() {} + } + + beforeEach(() => { + getInstanceStub = sinon.stub(RequireInTheMiddleSingleton, 'getInstance'); + }); + + afterEach(() => { + getInstanceStub.restore(); + }); + + it('should not initialize require-in-the-middle in the constructor', function () { + new EmptyInstrumentation(); + sinon.assert.notCalled(getInstanceStub); + }); + + it('should not initialize require-in-the-middle on enable', function () { + const instrumentation = new EmptyInstrumentation({ enabled: false }); + instrumentation.enable(); + sinon.assert.notCalled(getInstanceStub); + }); + }); + describe('_onRequire - core module', function () { let instrumentation: TestInstrumentation; let modulePatchSpy: sinon.SinonSpy; diff --git a/package-lock.json b/package-lock.json index 03da8686d9c..106d0b8ecc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6304,6 +6304,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=14" }