diff --git a/experimental/packages/opentelemetry-instrumentation/package.json b/experimental/packages/opentelemetry-instrumentation/package.json index 5128a556f5c..3e93f74af2a 100644 --- a/experimental/packages/opentelemetry-instrumentation/package.json +++ b/experimental/packages/opentelemetry-instrumentation/package.json @@ -71,7 +71,7 @@ }, "dependencies": { "@opentelemetry/api-logs": "0.210.0", - "import-in-the-middle": "^2.0.0", + "import-in-the-middle": "^2.0.1", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { diff --git a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts index 9633aa9dde7..0f6bcbf4ac7 100644 --- a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts +++ b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts @@ -220,12 +220,13 @@ export abstract class InstrumentationBase< } return exports; } - // internal file + // internal file or submodule export const files = module.files ?? []; const normalizedName = path.normalize(name); + const normalizedModuleName = path.normalize(module.name); const supportedFileInstrumentations = files.filter( f => - f.name === normalizedName && + (f.name === normalizedName || f.name === normalizedModuleName) && isSupported(f.supportedVersions, version, module.includePrerelease) ); return supportedFileInstrumentations.reduce((patchedExports, file) => { diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/EsmSubmoduleInstrumentation.test.mjs b/experimental/packages/opentelemetry-instrumentation/test/node/EsmSubmoduleInstrumentation.test.mjs new file mode 100644 index 00000000000..21a29d5bd34 --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation/test/node/EsmSubmoduleInstrumentation.test.mjs @@ -0,0 +1,110 @@ +/* + * 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. + */ + +import * as assert from 'assert'; + +import { + InstrumentationBase, + InstrumentationNodeModuleDefinition, + InstrumentationNodeModuleFile, +} from '../../build/src/index.js'; + +class TestInstrumentationSimple extends InstrumentationBase { + constructor(config) { + super('test-esm-submodule-exports', '0.0.1', config); + } + init() { + return [ + new InstrumentationNodeModuleDefinition( + '@opentelemetry/esm-submodule-exports', + ['*'], + moduleExports => { + moduleExports.propertyOnMainModule = 'modified string in main module'; + return moduleExports; + }, + moduleExports => { + return moduleExports; + }, + [ + new InstrumentationNodeModuleFile( + '@opentelemetry/esm-submodule-exports/src/index.js', + ['*'], + moduleExports => { + moduleExports.propertyOnMainModule = 'modified string in main module'; + return moduleExports; + + }, + moduleExports => { + return moduleExports; + } + ), + ] + ), + new InstrumentationNodeModuleDefinition( + '@opentelemetry/esm-submodule-exports/sub', + ['*'], + moduleExports => { + moduleExports.propertyOnSubModule = 'modified string in sub module'; + return moduleExports; + }, + moduleExports => { + return moduleExports; + }, + [ + new InstrumentationNodeModuleFile( + '@opentelemetry/esm-submodule-exports/sub', + ['*'], + moduleExports => { + moduleExports.propertyOnSubModule = 'modified string in sub module'; + return moduleExports; + }, + moduleExports => { + return moduleExports; + } + ), + ] + ) + ]; + } +} + +describe('instrumenting an esm scoped submodule package', function () { + it('should patch main module', async function () { + const instrumentation = new TestInstrumentationSimple({ + enabled: false, + }); + instrumentation.enable(); + + const { + propertyOnMainModule, + } = await import('@opentelemetry/esm-submodule-exports'); + + assert.strictEqual(propertyOnMainModule, 'modified string in main module'); + }); + + it('should patch sub module', async function () { + const instrumentation = new TestInstrumentationSimple({ + enabled: false, + }); + instrumentation.enable(); + + const { + propertyOnSubModule, + } = await import('@opentelemetry/esm-submodule-exports/sub'); + + assert.strictEqual(propertyOnSubModule, 'modified string in sub module'); + }); +}); diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/package.json b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/package.json new file mode 100644 index 00000000000..b570aec5672 --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/package.json @@ -0,0 +1,9 @@ +{ + "name": "@opentelemetry/esm-submodule-exports", + "version": "0.1.0", + "type": "module", + "exports": { + ".": "./src/index.js", + "./sub": "./src/sub.js" + } +} diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/index.js b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/index.js new file mode 100644 index 00000000000..230ebee1c5a --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/index.js @@ -0,0 +1,5 @@ +import { testString } from './internal.js' + +export const getString = () => "from index.js: " + testString; + +export const propertyOnMainModule = 'string in main module'; diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/internal.js b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/internal.js new file mode 100644 index 00000000000..98760d4e99f --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/internal.js @@ -0,0 +1 @@ +export const testString = "internal string"; diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/sub.js b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/sub.js new file mode 100644 index 00000000000..e7f301efe17 --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation/test/node/node_modules/@opentelemetry/esm-submodule-exports/src/sub.js @@ -0,0 +1,5 @@ +import { testString } from "./internal.js"; + +export const getString = () => `from /sub: ${testString}`; + +export const propertyOnSubModule = 'string in sub module'; diff --git a/package-lock.json b/package-lock.json index 02b9a97ab16..9a42de4ac80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -867,7 +867,7 @@ "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.210.0", - "import-in-the-middle": "^2.0.0", + "import-in-the-middle": "^2.0.1", "require-in-the-middle": "^8.0.0" }, "devDependencies": {