From c08ea8325e3fbd552887b96bb34b2821e6d74893 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 30 Jan 2026 19:28:34 +0530 Subject: [PATCH 01/20] fix: preload OpenTelemetry instrumentations in AWS Lambda --- packages/aws-lambda/src/wrapper.js | 8 ++++- packages/core/src/config/index.js | 4 ++- .../opentelemetry-instrumentations/preload.js | 29 +++++++++++++++++++ .../opentelemetry-instrumentations/wrap.js | 12 ++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 packages/core/src/tracing/opentelemetry-instrumentations/preload.js diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 8a7abe37d3..984dde9939 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -21,7 +21,12 @@ const { tracing, coreConfig } = instanaCore; const { tracingHeaders, constants, spanBuffer } = tracing; const lambdaConfigDefaults = { - tracing: { forceTransmissionStartingAt: 25, transmissionDelay: 100, initialTransmissionDelay: 100 } + tracing: { + forceTransmissionStartingAt: 25, + transmissionDelay: 100, + initialTransmissionDelay: 100, + isAwsLambda: true + } }; // Node.js 24+ removed support for callback-based handlers (3 parameters). @@ -279,6 +284,7 @@ function init(event, arnInfo, _config) { // - late env variables (less likely) // - custom logger // - we always renormalize unconditionally to ensure safety. + // The isAwsLambda flag is set in lambdaConfigDefaults and will be merged during normalization config = coreConfig.normalize(userConfig, lambdaConfigDefaults); if (!config.tracing.enabled) { diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index bbc2a7fcd4..6c891f38c4 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -36,6 +36,7 @@ const { validateStackTraceMode, validateStackTraceLength } = require('./configVa * @property {boolean} [ignoreEndpointsDisableSuppression] * @property {boolean} [disableEOLEvents] * @property {globalStackTraceConfig} [global] + * @property {boolean} [isAwsLambda] */ /** @@ -120,7 +121,8 @@ let defaults = { }, ignoreEndpoints: {}, ignoreEndpointsDisableSuppression: false, - disableEOLEvents: false + disableEOLEvents: false, + isAwsLambda: false }, secrets: { matcherMode: 'contains-ignore-case', diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/preload.js b/packages/core/src/tracing/opentelemetry-instrumentations/preload.js new file mode 100644 index 0000000000..4dddca5dee --- /dev/null +++ b/packages/core/src/tracing/opentelemetry-instrumentations/preload.js @@ -0,0 +1,29 @@ +/* + * (c) Copyright IBM Corp. 2026 + */ + +'use strict'; + +/** + * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. + * This is particularly useful in AWS Lambda environments where cold start performance is critical. + * + * @param {string[]} packageNames + */ +function preloadOtelInstrumentations(packageNames) { + if (!packageNames || !Array.isArray(packageNames)) { + return; + } + + packageNames.forEach(packageName => { + try { + require(packageName); + } catch (e) { + // @ts-ignore + } + }); +} + +module.exports = { + preloadOtelInstrumentations +}; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index a6c2b18715..7b31268fcb 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -12,6 +12,7 @@ const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base'); const utils = require('./utils'); const constants = require('../constants'); const supportedVersion = require('../supportedVersion'); +const { preloadOtelInstrumentations } = require('./preload'); // NOTE: Please refrain from utilizing third-party instrumentations. // Instead, opt for officially released instrumentations available in the OpenTelemetry @@ -27,6 +28,10 @@ const instrumentations = { '@instana/instrumentation-confluent-kafka-javascript': { name: 'confluent-kafka' } }; +function getInstrumentationPackageNames() { + return Object.keys(instrumentations); +} + // NOTE: using a logger might create a recursive execution // logger.debug -> creates fs call -> calls transformToInstanaSpan -> calls logger.debug // use uninstrumented logger, but useless for production @@ -35,6 +40,13 @@ module.exports.init = (_config, cls) => { return; } + // Preload OpenTelemetry instrumentation packages in AWS Lambda environment + // to avoid lazy loading overhead during cold starts + if (_config && _config.tracing && _config.tracing.isAwsLambda) { + const packageNames = getInstrumentationPackageNames(); + preloadOtelInstrumentations(packageNames); + } + Object.keys(instrumentations).forEach(k => { const value = instrumentations[k]; const instrumentation = require(`./${value.name}`); From a4ba7dccb225dc2029d64dca33dc9100ef2291a5 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 30 Jan 2026 23:12:42 +0530 Subject: [PATCH 02/20] chore: updated --- packages/aws-lambda/src/wrapper.js | 8 +++ packages/core/src/tracing/index.js | 1 + .../opentelemetry-instrumentations/index.js | 6 ++ .../instrumentations.js | 56 +++++++++++++++++++ .../opentelemetry-instrumentations/wrap.js | 27 +-------- 5 files changed, 73 insertions(+), 25 deletions(-) create mode 100644 packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 984dde9939..893f7d922b 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -37,6 +37,10 @@ coreConfig.init(logger); let config = coreConfig.normalize({}, lambdaConfigDefaults); let coldStart = true; +// Preload OpenTelemetry instrumentations before core init to avoid lazy loading overhead +// This improves Lambda cold start performance +instanaCore.tracing.otelInstrumentations.preloadOtelInstrumentations(); + // Initialize instrumentations early to allow for require statements after our // package has been required but before the actual instana.wrap(...) call. instanaCore.preInit(config); @@ -314,6 +318,10 @@ function init(event, arnInfo, _config) { retries: !!useLambdaExtension }); + // Preload OpenTelemetry instrumentations before core init to avoid lazy loading overhead + // Package names are retrieved from the instrumentations registry + instanaCore.tracing.otelInstrumentations.preloadOtelInstrumentations(); + instanaCore.init(config, backendConnector, identityProvider); // After core init, because ssm requires require('@aws-sdk/client-ssm'), which triggers diff --git a/packages/core/src/tracing/index.js b/packages/core/src/tracing/index.js index 9b470f467c..914c3331f1 100644 --- a/packages/core/src/tracing/index.js +++ b/packages/core/src/tracing/index.js @@ -353,3 +353,4 @@ exports._debugCurrentSpanName = function _debugCurrentSpanName() { }; exports.shimmer = require('./shimmer'); +exports.otelInstrumentations = require('./opentelemetry-instrumentations'); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/index.js b/packages/core/src/tracing/opentelemetry-instrumentations/index.js index fb758fe550..7d7060cd51 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/index.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/index.js @@ -7,5 +7,11 @@ module.exports = { get otelInstrumentations() { return require('./wrap'); + }, + get preloadOtelInstrumentations() { + return require('./instrumentations').preloadOtelInstrumentations; + }, + get getInstrumentationPackageNames() { + return require('./instrumentations').getInstrumentationPackageNames; } }; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js new file mode 100644 index 0000000000..bc9c4fd6bf --- /dev/null +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -0,0 +1,56 @@ +/* + * (c) Copyright IBM Corp. 2025 + */ + +'use strict'; + +/** + * Registry of supported OpenTelemetry instrumentations. + * Maps instrumentation package names to their internal module names. + * + * NOTE: Please refrain from utilizing third-party instrumentations. + * Instead, opt for officially released instrumentations available in the OpenTelemetry + * repository at https://github.com/open-telemetry/opentelemetry-js-contrib. + * Third-party instrumentations typically bypass a review process, + * resulting in suboptimal code coverage and potential vulnerabilities. + */ +const instrumentations = { + '@opentelemetry/instrumentation-fs': { name: 'fs' }, + '@opentelemetry/instrumentation-restify': { name: 'restify' }, + '@opentelemetry/instrumentation-socket.io': { name: 'socket.io' }, + '@opentelemetry/instrumentation-tedious': { name: 'tedious' }, + '@opentelemetry/instrumentation-oracledb': { name: 'oracle' }, + '@instana/instrumentation-confluent-kafka-javascript': { name: 'confluent-kafka' } +}; + +exports.getInstrumentations = () => { + return instrumentations; +}; + +exports.getInstrumentationPackageNames = () => { + return Object.keys(instrumentations); +}; + +/** + * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. + * This is particularly useful in AWS Lambda environments where cold start performance is critical. + * Uses the package names from the instrumentations registry defined in this file. + */ +exports.preloadOtelInstrumentations = () => { + const packageNames = Object.keys(instrumentations); + + // eslint-disable-next-line no-console + console.log(`[Instana] Preloading ${packageNames.length} OpenTelemetry instrumentations...`); + + packageNames.forEach(packageName => { + const pkgStart = Date.now(); + try { + require(packageName); + // eslint-disable-next-line no-console + console.debug(`[PERF] [OTEL] [EARLY-PRELOAD] ${packageName} loaded in ${Date.now() - pkgStart}ms`); + } catch (e) { + // eslint-disable-next-line no-console + console.debug(`[PERF] [OTEL] [EARLY-PRELOAD] ${packageName} failed: ${e.message}`); + } + }); +}; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index 7b31268fcb..cbe1d794a8 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -12,25 +12,9 @@ const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base'); const utils = require('./utils'); const constants = require('../constants'); const supportedVersion = require('../supportedVersion'); -const { preloadOtelInstrumentations } = require('./preload'); - -// NOTE: Please refrain from utilizing third-party instrumentations. -// Instead, opt for officially released instrumentations available in the OpenTelemetry -// repository at https://github.com/open-telemetry/opentelemetry-js-contrib. -// Third-party instrumentations typically bypass a review process, -// resulting in suboptimal code coverage and potential vulnerabilities. -const instrumentations = { - '@opentelemetry/instrumentation-fs': { name: 'fs' }, - '@opentelemetry/instrumentation-restify': { name: 'restify' }, - '@opentelemetry/instrumentation-socket.io': { name: 'socket.io' }, - '@opentelemetry/instrumentation-tedious': { name: 'tedious' }, - '@opentelemetry/instrumentation-oracledb': { name: 'oracle' }, - '@instana/instrumentation-confluent-kafka-javascript': { name: 'confluent-kafka' } -}; +const { getInstrumentations } = require('./instrumentations'); -function getInstrumentationPackageNames() { - return Object.keys(instrumentations); -} +const instrumentations = getInstrumentations(); // NOTE: using a logger might create a recursive execution // logger.debug -> creates fs call -> calls transformToInstanaSpan -> calls logger.debug @@ -40,13 +24,6 @@ module.exports.init = (_config, cls) => { return; } - // Preload OpenTelemetry instrumentation packages in AWS Lambda environment - // to avoid lazy loading overhead during cold starts - if (_config && _config.tracing && _config.tracing.isAwsLambda) { - const packageNames = getInstrumentationPackageNames(); - preloadOtelInstrumentations(packageNames); - } - Object.keys(instrumentations).forEach(k => { const value = instrumentations[k]; const instrumentation = require(`./${value.name}`); From 6c94cf65eb9b787978c450a03c0b0cec440e8c30 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 30 Jan 2026 23:20:46 +0530 Subject: [PATCH 03/20] test: added --- .../instrumentations.js | 2 +- .../preload_test.js | 146 ++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js index bc9c4fd6bf..7a6a19f7be 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -1,5 +1,5 @@ /* - * (c) Copyright IBM Corp. 2025 + * (c) Copyright IBM Corp. 2026 */ 'use strict'; diff --git a/packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js b/packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js new file mode 100644 index 0000000000..726a992c13 --- /dev/null +++ b/packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js @@ -0,0 +1,146 @@ +/* + * (c) Copyright IBM Corp. 2026 + */ + +'use strict'; + +const expect = require('chai').expect; +const proxyquire = require('proxyquire'); +const sinon = require('sinon'); + +describe('OpenTelemetry instrumentations preloading', () => { + let preloadModule; + let consoleLogStub; + + beforeEach(() => { + consoleLogStub = sinon.stub(console, 'log'); + preloadModule = proxyquire('../../../src/tracing/opentelemetry-instrumentations/instrumentations', {}); + }); + + afterEach(() => { + consoleLogStub.restore(); + }); + + describe('getInstrumentations', () => { + it('should return the instrumentations registry object', () => { + const instrumentations = preloadModule.getInstrumentations(); + + expect(instrumentations).to.be.an('object'); + expect(instrumentations).to.have.property('@opentelemetry/instrumentation-fs'); + expect(instrumentations['@opentelemetry/instrumentation-fs']).to.deep.equal({ name: 'fs' }); + }); + + it('should include all expected instrumentations', () => { + const instrumentations = preloadModule.getInstrumentations(); + const expectedPackages = [ + '@opentelemetry/instrumentation-fs', + '@opentelemetry/instrumentation-restify', + '@opentelemetry/instrumentation-socket.io', + '@opentelemetry/instrumentation-tedious', + '@opentelemetry/instrumentation-oracledb', + '@instana/instrumentation-confluent-kafka-javascript' + ]; + + expectedPackages.forEach(pkg => { + expect(instrumentations).to.have.property(pkg); + }); + }); + }); + + describe('getInstrumentationPackageNames', () => { + it('should return an array of package names', () => { + const packageNames = preloadModule.getInstrumentationPackageNames(); + + expect(packageNames).to.be.an('array'); + expect(packageNames.length).to.be.greaterThan(0); + }); + + it('should include all expected package names', () => { + const packageNames = preloadModule.getInstrumentationPackageNames(); + + expect(packageNames).to.include('@opentelemetry/instrumentation-fs'); + expect(packageNames).to.include('@opentelemetry/instrumentation-restify'); + expect(packageNames).to.include('@opentelemetry/instrumentation-socket.io'); + expect(packageNames).to.include('@opentelemetry/instrumentation-tedious'); + expect(packageNames).to.include('@opentelemetry/instrumentation-oracledb'); + expect(packageNames).to.include('@instana/instrumentation-confluent-kafka-javascript'); + }); + + it('should return the same count as the instrumentations object', () => { + const instrumentations = preloadModule.getInstrumentations(); + const packageNames = preloadModule.getInstrumentationPackageNames(); + + expect(packageNames.length).to.equal(Object.keys(instrumentations).length); + }); + }); + + describe('preloadOtelInstrumentations', () => { + it('should be a function', () => { + expect(preloadModule.preloadOtelInstrumentations).to.be.a('function'); + }); + + it('should not throw when called', () => { + expect(() => { + preloadModule.preloadOtelInstrumentations(); + }).to.not.throw(); + }); + + it('should log preloading start message', () => { + preloadModule.preloadOtelInstrumentations(); + + const startMessage = consoleLogStub.args.find( + args => args[0].includes('Preloading') && args[0].includes('OpenTelemetry instrumentations') + ); + expect(startMessage).to.exist; + }); + + it('should use package names from instrumentations registry', () => { + const packageNames = preloadModule.getInstrumentationPackageNames(); + + expect(packageNames).to.be.an('array'); + expect(packageNames).to.include('@opentelemetry/instrumentation-fs'); + expect(packageNames).to.include('@opentelemetry/instrumentation-restify'); + expect(packageNames.length).to.be.greaterThan(0); + }); + }); +}); + +describe('Config integration', () => { + let configModule; + + beforeEach(() => { + delete require.cache[require.resolve('../../../src/config')]; + configModule = require('../../../src/config'); + }); + + it('should have isAwsLambda in default config', () => { + const config = configModule.normalize({}); + + expect(config.tracing).to.have.property('isAwsLambda'); + expect(config.tracing.isAwsLambda).to.be.false; + }); + + it('should allow setting isAwsLambda to true', () => { + const config = configModule.normalize({ + tracing: { + isAwsLambda: true + } + }); + + expect(config.tracing.isAwsLambda).to.be.true; + }); + + it('should preserve other tracing config when setting isAwsLambda', () => { + const config = configModule.normalize({ + tracing: { + enabled: true, + isAwsLambda: true, + useOpentelemetry: true + } + }); + + expect(config.tracing.enabled).to.be.true; + expect(config.tracing.isAwsLambda).to.be.true; + expect(config.tracing.useOpentelemetry).to.be.true; + }); +}); From 0de420702bc6d73387b2a9dbef9bf3a498ecbf7d Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 12:00:57 +0530 Subject: [PATCH 04/20] test: added --- packages/aws-lambda/src/wrapper.js | 4 - packages/core/src/config/index.js | 14 ++ .../instrumentations.js | 1 - .../opentelemetry-instrumentations/preload.js | 29 ---- .../core/test/config/normalizeConfig_test.js | 27 ++++ .../instrumentations_test.js | 115 ++++++++++++++ .../preload_test.js | 146 ------------------ 7 files changed, 156 insertions(+), 180 deletions(-) delete mode 100644 packages/core/src/tracing/opentelemetry-instrumentations/preload.js create mode 100644 packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js delete mode 100644 packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 893f7d922b..1d83530bae 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -38,7 +38,6 @@ let config = coreConfig.normalize({}, lambdaConfigDefaults); let coldStart = true; // Preload OpenTelemetry instrumentations before core init to avoid lazy loading overhead -// This improves Lambda cold start performance instanaCore.tracing.otelInstrumentations.preloadOtelInstrumentations(); // Initialize instrumentations early to allow for require statements after our @@ -288,7 +287,6 @@ function init(event, arnInfo, _config) { // - late env variables (less likely) // - custom logger // - we always renormalize unconditionally to ensure safety. - // The isAwsLambda flag is set in lambdaConfigDefaults and will be merged during normalization config = coreConfig.normalize(userConfig, lambdaConfigDefaults); if (!config.tracing.enabled) { @@ -318,8 +316,6 @@ function init(event, arnInfo, _config) { retries: !!useLambdaExtension }); - // Preload OpenTelemetry instrumentations before core init to avoid lazy loading overhead - // Package names are retrieved from the instrumentations registry instanaCore.tracing.otelInstrumentations.preloadOtelInstrumentations(); instanaCore.init(config, backendConnector, identityProvider); diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 6c891f38c4..3c8536e8eb 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -249,6 +249,7 @@ function normalizeTracingConfig(config) { normalizeIgnoreEndpoints(config); normalizeIgnoreEndpointsDisableSuppression(config); normalizeDisableEOLEvents(config); + normalizeIsAwsLambda(config); } /** @@ -817,3 +818,16 @@ function normalizeDisableEOLEvents(config) { config.tracing.disableEOLEvents = defaults.tracing.disableEOLEvents; } +/** + * @param {InstanaConfig} config + */ +function normalizeIsAwsLambda(config) { + if (config.tracing.isAwsLambda === false) { + return; + } + if (config.tracing.isAwsLambda === true) { + return; + } + + config.tracing.isAwsLambda = defaults.tracing.isAwsLambda; +} diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js index 7a6a19f7be..3ac0f17385 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -34,7 +34,6 @@ exports.getInstrumentationPackageNames = () => { /** * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. * This is particularly useful in AWS Lambda environments where cold start performance is critical. - * Uses the package names from the instrumentations registry defined in this file. */ exports.preloadOtelInstrumentations = () => { const packageNames = Object.keys(instrumentations); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/preload.js b/packages/core/src/tracing/opentelemetry-instrumentations/preload.js deleted file mode 100644 index 4dddca5dee..0000000000 --- a/packages/core/src/tracing/opentelemetry-instrumentations/preload.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * (c) Copyright IBM Corp. 2026 - */ - -'use strict'; - -/** - * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. - * This is particularly useful in AWS Lambda environments where cold start performance is critical. - * - * @param {string[]} packageNames - */ -function preloadOtelInstrumentations(packageNames) { - if (!packageNames || !Array.isArray(packageNames)) { - return; - } - - packageNames.forEach(packageName => { - try { - require(packageName); - } catch (e) { - // @ts-ignore - } - }); -} - -module.exports = { - preloadOtelInstrumentations -}; diff --git a/packages/core/test/config/normalizeConfig_test.js b/packages/core/test/config/normalizeConfig_test.js index 7c35400caf..45c3578f69 100644 --- a/packages/core/test/config/normalizeConfig_test.js +++ b/packages/core/test/config/normalizeConfig_test.js @@ -943,6 +943,32 @@ describe('config.normalizeConfig', () => { expect(config.tracing.ignoreEndpoints).to.deep.equal({}); }); + it('should default to false', () => { + const config = coreConfig.normalize({}); + expect(config.tracing.isAwsLambda).to.be.false; + }); + + it('should accept true value', () => { + const config = coreConfig.normalize({ + tracing: { + isAwsLambda: true + } + }); + expect(config.tracing.isAwsLambda).to.be.true; + }); + + it('should work with custom defaults', () => { + const customDefaults = { + tracing: { + isAwsLambda: true, + forceTransmissionStartingAt: 25 + } + }; + const config = coreConfig.normalize({}, customDefaults); + expect(config.tracing.isAwsLambda).to.be.true; + expect(config.tracing.forceTransmissionStartingAt).to.equal(25); + }); + describe('when testing ignore endpoints reading from INSTANA_IGNORE_ENDPOINTS_PATH env variable', () => { let filePaths; @@ -1047,6 +1073,7 @@ describe('config.normalizeConfig', () => { expect(config.tracing.kafka.traceCorrelation).to.be.true; expect(config.tracing.useOpentelemetry).to.equal(true); expect(config.tracing.allowRootExitSpan).to.equal(false); + expect(config.tracing.isAwsLambda).to.equal(false); expect(config.secrets).to.be.an('object'); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); diff --git a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js new file mode 100644 index 0000000000..8948847c68 --- /dev/null +++ b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js @@ -0,0 +1,115 @@ +/* + * (c) Copyright IBM Corp. 2026 + */ + +'use strict'; + +const expect = require('chai').expect; +const sinon = require('sinon'); + +describe('OpenTelemetry instrumentations registry', () => { + let instrumentationsModule; + + beforeEach(() => { + delete require.cache[require.resolve('../../../src/tracing/opentelemetry-instrumentations/instrumentations')]; + instrumentationsModule = require('../../../src/tracing/opentelemetry-instrumentations/instrumentations'); + }); + + describe('getInstrumentations', () => { + it('should return an object', () => { + const instrumentations = instrumentationsModule.getInstrumentations(); + expect(instrumentations).to.be.an('object'); + }); + + it('should return the same object on multiple calls', () => { + const first = instrumentationsModule.getInstrumentations(); + const second = instrumentationsModule.getInstrumentations(); + expect(first).to.equal(second); + }); + + it('should contain fs instrumentation', () => { + const instrumentations = instrumentationsModule.getInstrumentations(); + expect(instrumentations).to.have.property('@opentelemetry/instrumentation-fs'); + expect(instrumentations['@opentelemetry/instrumentation-fs']).to.deep.equal({ name: 'fs' }); + }); + + it('should contain restify instrumentation', () => { + const instrumentations = instrumentationsModule.getInstrumentations(); + expect(instrumentations).to.have.property('@opentelemetry/instrumentation-restify'); + expect(instrumentations['@opentelemetry/instrumentation-restify']).to.deep.equal({ name: 'restify' }); + }); + + it('should have exactly 6 instrumentations', () => { + const instrumentations = instrumentationsModule.getInstrumentations(); + expect(Object.keys(instrumentations)).to.have.lengthOf(6); + }); + }); + + describe('getInstrumentationPackageNames', () => { + it('should return an array', () => { + const packageNames = instrumentationsModule.getInstrumentationPackageNames(); + expect(packageNames).to.be.an('array'); + }); + + it('should return all package names', () => { + const packageNames = instrumentationsModule.getInstrumentationPackageNames(); + expect(packageNames).to.have.lengthOf(6); + }); + + it('should include all expected package names', () => { + const packageNames = instrumentationsModule.getInstrumentationPackageNames(); + const expected = [ + '@opentelemetry/instrumentation-fs', + '@opentelemetry/instrumentation-restify', + '@opentelemetry/instrumentation-socket.io', + '@opentelemetry/instrumentation-tedious', + '@opentelemetry/instrumentation-oracledb', + '@instana/instrumentation-confluent-kafka-javascript' + ]; + + expected.forEach(pkg => { + expect(packageNames).to.include(pkg); + }); + }); + + it('should match the keys from getInstrumentations', () => { + const instrumentations = instrumentationsModule.getInstrumentations(); + const packageNames = instrumentationsModule.getInstrumentationPackageNames(); + + expect(packageNames).to.have.lengthOf(Object.keys(instrumentations).length); + packageNames.forEach(name => { + expect(instrumentations).to.have.property(name); + }); + }); + }); + + describe('preloadOtelInstrumentations', () => { + let consoleLogStub; + + beforeEach(() => { + consoleLogStub = sinon.stub(console, 'log'); + }); + + afterEach(() => { + consoleLogStub.restore(); + }); + + it('should be a function', () => { + expect(instrumentationsModule.preloadOtelInstrumentations).to.be.a('function'); + }); + + it('should not throw when called', () => { + expect(() => { + instrumentationsModule.preloadOtelInstrumentations(); + }).to.not.throw(); + }); + + it('should complete in reasonable time', () => { + const startTime = Date.now(); + instrumentationsModule.preloadOtelInstrumentations(); + const duration = Date.now() - startTime; + + expect(duration).to.be.lessThan(1000); + }); + }); +}); diff --git a/packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js b/packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js deleted file mode 100644 index 726a992c13..0000000000 --- a/packages/core/test/tracing/opentelemetry-instrumentations/preload_test.js +++ /dev/null @@ -1,146 +0,0 @@ -/* - * (c) Copyright IBM Corp. 2026 - */ - -'use strict'; - -const expect = require('chai').expect; -const proxyquire = require('proxyquire'); -const sinon = require('sinon'); - -describe('OpenTelemetry instrumentations preloading', () => { - let preloadModule; - let consoleLogStub; - - beforeEach(() => { - consoleLogStub = sinon.stub(console, 'log'); - preloadModule = proxyquire('../../../src/tracing/opentelemetry-instrumentations/instrumentations', {}); - }); - - afterEach(() => { - consoleLogStub.restore(); - }); - - describe('getInstrumentations', () => { - it('should return the instrumentations registry object', () => { - const instrumentations = preloadModule.getInstrumentations(); - - expect(instrumentations).to.be.an('object'); - expect(instrumentations).to.have.property('@opentelemetry/instrumentation-fs'); - expect(instrumentations['@opentelemetry/instrumentation-fs']).to.deep.equal({ name: 'fs' }); - }); - - it('should include all expected instrumentations', () => { - const instrumentations = preloadModule.getInstrumentations(); - const expectedPackages = [ - '@opentelemetry/instrumentation-fs', - '@opentelemetry/instrumentation-restify', - '@opentelemetry/instrumentation-socket.io', - '@opentelemetry/instrumentation-tedious', - '@opentelemetry/instrumentation-oracledb', - '@instana/instrumentation-confluent-kafka-javascript' - ]; - - expectedPackages.forEach(pkg => { - expect(instrumentations).to.have.property(pkg); - }); - }); - }); - - describe('getInstrumentationPackageNames', () => { - it('should return an array of package names', () => { - const packageNames = preloadModule.getInstrumentationPackageNames(); - - expect(packageNames).to.be.an('array'); - expect(packageNames.length).to.be.greaterThan(0); - }); - - it('should include all expected package names', () => { - const packageNames = preloadModule.getInstrumentationPackageNames(); - - expect(packageNames).to.include('@opentelemetry/instrumentation-fs'); - expect(packageNames).to.include('@opentelemetry/instrumentation-restify'); - expect(packageNames).to.include('@opentelemetry/instrumentation-socket.io'); - expect(packageNames).to.include('@opentelemetry/instrumentation-tedious'); - expect(packageNames).to.include('@opentelemetry/instrumentation-oracledb'); - expect(packageNames).to.include('@instana/instrumentation-confluent-kafka-javascript'); - }); - - it('should return the same count as the instrumentations object', () => { - const instrumentations = preloadModule.getInstrumentations(); - const packageNames = preloadModule.getInstrumentationPackageNames(); - - expect(packageNames.length).to.equal(Object.keys(instrumentations).length); - }); - }); - - describe('preloadOtelInstrumentations', () => { - it('should be a function', () => { - expect(preloadModule.preloadOtelInstrumentations).to.be.a('function'); - }); - - it('should not throw when called', () => { - expect(() => { - preloadModule.preloadOtelInstrumentations(); - }).to.not.throw(); - }); - - it('should log preloading start message', () => { - preloadModule.preloadOtelInstrumentations(); - - const startMessage = consoleLogStub.args.find( - args => args[0].includes('Preloading') && args[0].includes('OpenTelemetry instrumentations') - ); - expect(startMessage).to.exist; - }); - - it('should use package names from instrumentations registry', () => { - const packageNames = preloadModule.getInstrumentationPackageNames(); - - expect(packageNames).to.be.an('array'); - expect(packageNames).to.include('@opentelemetry/instrumentation-fs'); - expect(packageNames).to.include('@opentelemetry/instrumentation-restify'); - expect(packageNames.length).to.be.greaterThan(0); - }); - }); -}); - -describe('Config integration', () => { - let configModule; - - beforeEach(() => { - delete require.cache[require.resolve('../../../src/config')]; - configModule = require('../../../src/config'); - }); - - it('should have isAwsLambda in default config', () => { - const config = configModule.normalize({}); - - expect(config.tracing).to.have.property('isAwsLambda'); - expect(config.tracing.isAwsLambda).to.be.false; - }); - - it('should allow setting isAwsLambda to true', () => { - const config = configModule.normalize({ - tracing: { - isAwsLambda: true - } - }); - - expect(config.tracing.isAwsLambda).to.be.true; - }); - - it('should preserve other tracing config when setting isAwsLambda', () => { - const config = configModule.normalize({ - tracing: { - enabled: true, - isAwsLambda: true, - useOpentelemetry: true - } - }); - - expect(config.tracing.enabled).to.be.true; - expect(config.tracing.isAwsLambda).to.be.true; - expect(config.tracing.useOpentelemetry).to.be.true; - }); -}); From 49c68b8f5d5cbbe13565aef700becb626977a6ae Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 12:55:24 +0530 Subject: [PATCH 05/20] chore: cleanup --- packages/aws-lambda/src/wrapper.js | 5 +--- packages/core/src/config/index.js | 18 +------------ .../core/test/config/normalizeConfig_test.js | 27 ------------------- 3 files changed, 2 insertions(+), 48 deletions(-) diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 1d83530bae..d2c5693d88 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -24,8 +24,7 @@ const lambdaConfigDefaults = { tracing: { forceTransmissionStartingAt: 25, transmissionDelay: 100, - initialTransmissionDelay: 100, - isAwsLambda: true + initialTransmissionDelay: 100 } }; @@ -316,8 +315,6 @@ function init(event, arnInfo, _config) { retries: !!useLambdaExtension }); - instanaCore.tracing.otelInstrumentations.preloadOtelInstrumentations(); - instanaCore.init(config, backendConnector, identityProvider); // After core init, because ssm requires require('@aws-sdk/client-ssm'), which triggers diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 3c8536e8eb..bbc2a7fcd4 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -36,7 +36,6 @@ const { validateStackTraceMode, validateStackTraceLength } = require('./configVa * @property {boolean} [ignoreEndpointsDisableSuppression] * @property {boolean} [disableEOLEvents] * @property {globalStackTraceConfig} [global] - * @property {boolean} [isAwsLambda] */ /** @@ -121,8 +120,7 @@ let defaults = { }, ignoreEndpoints: {}, ignoreEndpointsDisableSuppression: false, - disableEOLEvents: false, - isAwsLambda: false + disableEOLEvents: false }, secrets: { matcherMode: 'contains-ignore-case', @@ -249,7 +247,6 @@ function normalizeTracingConfig(config) { normalizeIgnoreEndpoints(config); normalizeIgnoreEndpointsDisableSuppression(config); normalizeDisableEOLEvents(config); - normalizeIsAwsLambda(config); } /** @@ -818,16 +815,3 @@ function normalizeDisableEOLEvents(config) { config.tracing.disableEOLEvents = defaults.tracing.disableEOLEvents; } -/** - * @param {InstanaConfig} config - */ -function normalizeIsAwsLambda(config) { - if (config.tracing.isAwsLambda === false) { - return; - } - if (config.tracing.isAwsLambda === true) { - return; - } - - config.tracing.isAwsLambda = defaults.tracing.isAwsLambda; -} diff --git a/packages/core/test/config/normalizeConfig_test.js b/packages/core/test/config/normalizeConfig_test.js index 45c3578f69..7c35400caf 100644 --- a/packages/core/test/config/normalizeConfig_test.js +++ b/packages/core/test/config/normalizeConfig_test.js @@ -943,32 +943,6 @@ describe('config.normalizeConfig', () => { expect(config.tracing.ignoreEndpoints).to.deep.equal({}); }); - it('should default to false', () => { - const config = coreConfig.normalize({}); - expect(config.tracing.isAwsLambda).to.be.false; - }); - - it('should accept true value', () => { - const config = coreConfig.normalize({ - tracing: { - isAwsLambda: true - } - }); - expect(config.tracing.isAwsLambda).to.be.true; - }); - - it('should work with custom defaults', () => { - const customDefaults = { - tracing: { - isAwsLambda: true, - forceTransmissionStartingAt: 25 - } - }; - const config = coreConfig.normalize({}, customDefaults); - expect(config.tracing.isAwsLambda).to.be.true; - expect(config.tracing.forceTransmissionStartingAt).to.equal(25); - }); - describe('when testing ignore endpoints reading from INSTANA_IGNORE_ENDPOINTS_PATH env variable', () => { let filePaths; @@ -1073,7 +1047,6 @@ describe('config.normalizeConfig', () => { expect(config.tracing.kafka.traceCorrelation).to.be.true; expect(config.tracing.useOpentelemetry).to.equal(true); expect(config.tracing.allowRootExitSpan).to.equal(false); - expect(config.tracing.isAwsLambda).to.equal(false); expect(config.secrets).to.be.an('object'); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); From b96f2a2d669e8bb486f633e45bdb7fec79a01a8e Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 12:57:40 +0530 Subject: [PATCH 06/20] chore: cleanup --- .../opentelemetry-instrumentations/index.js | 3 -- .../instrumentations.js | 4 -- .../instrumentations_test.js | 38 ------------------- 3 files changed, 45 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/index.js b/packages/core/src/tracing/opentelemetry-instrumentations/index.js index 7d7060cd51..f7a110b2a0 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/index.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/index.js @@ -10,8 +10,5 @@ module.exports = { }, get preloadOtelInstrumentations() { return require('./instrumentations').preloadOtelInstrumentations; - }, - get getInstrumentationPackageNames() { - return require('./instrumentations').getInstrumentationPackageNames; } }; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js index 3ac0f17385..ac45482d02 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -27,10 +27,6 @@ exports.getInstrumentations = () => { return instrumentations; }; -exports.getInstrumentationPackageNames = () => { - return Object.keys(instrumentations); -}; - /** * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. * This is particularly useful in AWS Lambda environments where cold start performance is critical. diff --git a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js index 8948847c68..7916104b12 100644 --- a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js +++ b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js @@ -45,44 +45,6 @@ describe('OpenTelemetry instrumentations registry', () => { }); }); - describe('getInstrumentationPackageNames', () => { - it('should return an array', () => { - const packageNames = instrumentationsModule.getInstrumentationPackageNames(); - expect(packageNames).to.be.an('array'); - }); - - it('should return all package names', () => { - const packageNames = instrumentationsModule.getInstrumentationPackageNames(); - expect(packageNames).to.have.lengthOf(6); - }); - - it('should include all expected package names', () => { - const packageNames = instrumentationsModule.getInstrumentationPackageNames(); - const expected = [ - '@opentelemetry/instrumentation-fs', - '@opentelemetry/instrumentation-restify', - '@opentelemetry/instrumentation-socket.io', - '@opentelemetry/instrumentation-tedious', - '@opentelemetry/instrumentation-oracledb', - '@instana/instrumentation-confluent-kafka-javascript' - ]; - - expected.forEach(pkg => { - expect(packageNames).to.include(pkg); - }); - }); - - it('should match the keys from getInstrumentations', () => { - const instrumentations = instrumentationsModule.getInstrumentations(); - const packageNames = instrumentationsModule.getInstrumentationPackageNames(); - - expect(packageNames).to.have.lengthOf(Object.keys(instrumentations).length); - packageNames.forEach(name => { - expect(instrumentations).to.have.property(name); - }); - }); - }); - describe('preloadOtelInstrumentations', () => { let consoleLogStub; From 4a5908519a2b7db495b752d1c75c7b8f35a24ab8 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 13:00:06 +0530 Subject: [PATCH 07/20] chore: cleanup --- packages/aws-lambda/src/wrapper.js | 4 ++-- .../src/tracing/opentelemetry-instrumentations/index.js | 4 ++-- .../opentelemetry-instrumentations/instrumentations.js | 2 +- .../instrumentations_test.js | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index d2c5693d88..22ffb9fc99 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -36,8 +36,8 @@ coreConfig.init(logger); let config = coreConfig.normalize({}, lambdaConfigDefaults); let coldStart = true; -// Preload OpenTelemetry instrumentations before core init to avoid lazy loading overhead -instanaCore.tracing.otelInstrumentations.preloadOtelInstrumentations(); +// Preload OpenTelemetry instrumentations to avoid lazy loading overhead +instanaCore.tracing.otelInstrumentations.preload(); // Initialize instrumentations early to allow for require statements after our // package has been required but before the actual instana.wrap(...) call. diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/index.js b/packages/core/src/tracing/opentelemetry-instrumentations/index.js index f7a110b2a0..c997c0cf8d 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/index.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/index.js @@ -8,7 +8,7 @@ module.exports = { get otelInstrumentations() { return require('./wrap'); }, - get preloadOtelInstrumentations() { - return require('./instrumentations').preloadOtelInstrumentations; + get preload() { + return require('./instrumentations').preload; } }; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js index ac45482d02..8f18cfd1af 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -31,7 +31,7 @@ exports.getInstrumentations = () => { * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. * This is particularly useful in AWS Lambda environments where cold start performance is critical. */ -exports.preloadOtelInstrumentations = () => { +exports.preload = () => { const packageNames = Object.keys(instrumentations); // eslint-disable-next-line no-console diff --git a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js index 7916104b12..2973e23279 100644 --- a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js +++ b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js @@ -45,7 +45,7 @@ describe('OpenTelemetry instrumentations registry', () => { }); }); - describe('preloadOtelInstrumentations', () => { + describe('preload', () => { let consoleLogStub; beforeEach(() => { @@ -57,18 +57,18 @@ describe('OpenTelemetry instrumentations registry', () => { }); it('should be a function', () => { - expect(instrumentationsModule.preloadOtelInstrumentations).to.be.a('function'); + expect(instrumentationsModule.preload).to.be.a('function'); }); it('should not throw when called', () => { expect(() => { - instrumentationsModule.preloadOtelInstrumentations(); + instrumentationsModule.preload(); }).to.not.throw(); }); it('should complete in reasonable time', () => { const startTime = Date.now(); - instrumentationsModule.preloadOtelInstrumentations(); + instrumentationsModule.preload(); const duration = Date.now() - startTime; expect(duration).to.be.lessThan(1000); From 1694849b1cdd71a9c1383ecb3f1823792f5c76db Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 16:55:46 +0530 Subject: [PATCH 08/20] chore: remove logging --- .../instrumentations.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js index 8f18cfd1af..ae9fc0a335 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -29,23 +29,11 @@ exports.getInstrumentations = () => { /** * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. - * This is particularly useful in AWS Lambda environments where cold start performance is critical. + * This is particularly useful in AWS Lambda environments where cold start performance is affected by the lazy loading. */ exports.preload = () => { const packageNames = Object.keys(instrumentations); - - // eslint-disable-next-line no-console - console.log(`[Instana] Preloading ${packageNames.length} OpenTelemetry instrumentations...`); - packageNames.forEach(packageName => { - const pkgStart = Date.now(); - try { - require(packageName); - // eslint-disable-next-line no-console - console.debug(`[PERF] [OTEL] [EARLY-PRELOAD] ${packageName} loaded in ${Date.now() - pkgStart}ms`); - } catch (e) { - // eslint-disable-next-line no-console - console.debug(`[PERF] [OTEL] [EARLY-PRELOAD] ${packageName} failed: ${e.message}`); - } + require(packageName); }); }; From 79bdd7cbc405dfc1f13010f8ff94dd8258cee7b4 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 17:37:54 +0530 Subject: [PATCH 09/20] chore: moved to preinit --- packages/aws-lambda/src/wrapper.js | 3 +-- packages/core/src/config/index.js | 16 ++++++++++- packages/core/src/index.js | 3 +++ .../core/test/config/normalizeConfig_test.js | 27 +++++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 22ffb9fc99..cd2ddd1081 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -35,9 +35,8 @@ const logger = serverlessLogger.init(); coreConfig.init(logger); let config = coreConfig.normalize({}, lambdaConfigDefaults); let coldStart = true; - // Preload OpenTelemetry instrumentations to avoid lazy loading overhead -instanaCore.tracing.otelInstrumentations.preload(); +config.tracing.preloadOtelInstrumentations = true; // Initialize instrumentations early to allow for require statements after our // package has been required but before the actual instana.wrap(...) call. diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index bbc2a7fcd4..04a0dcb254 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -36,6 +36,7 @@ const { validateStackTraceMode, validateStackTraceLength } = require('./configVa * @property {boolean} [ignoreEndpointsDisableSuppression] * @property {boolean} [disableEOLEvents] * @property {globalStackTraceConfig} [global] + * @property {boolean} [preloadOtelInstrumentations] */ /** @@ -120,7 +121,8 @@ let defaults = { }, ignoreEndpoints: {}, ignoreEndpointsDisableSuppression: false, - disableEOLEvents: false + disableEOLEvents: false, + preloadOtelInstrumentations: false }, secrets: { matcherMode: 'contains-ignore-case', @@ -171,6 +173,7 @@ module.exports.normalize = (userConfig, defaultsOverride = {}) => { normalizeMetricsConfig(targetConfig); normalizeTracingConfig(targetConfig); normalizeSecrets(targetConfig); + normalizePreloadOtelInstrumentations(targetConfig); return targetConfig; }; @@ -815,3 +818,14 @@ function normalizeDisableEOLEvents(config) { config.tracing.disableEOLEvents = defaults.tracing.disableEOLEvents; } + +/** + * @param {InstanaConfig} config + */ +function normalizePreloadOtelInstrumentations(config) { + if (config.tracing.preloadOtelInstrumentations === true) { + return; + } + + config.tracing.preloadOtelInstrumentations = defaults.tracing.preloadOtelInstrumentations; +} diff --git a/packages/core/src/index.js b/packages/core/src/index.js index b774b855f0..e73645ac3b 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -62,6 +62,9 @@ function registerAdditionalInstrumentations(additionalInstrumentationModules) { * @param {import('./config').InstanaConfig} preliminaryConfig */ function preInit(preliminaryConfig) { + if (preliminaryConfig.tracing.preloadOtelInstrumentations) { + tracing.otelInstrumentations.preload(); + } util.init(preliminaryConfig); util.hasThePackageBeenInitializedTooLate.activate(); tracing.preInit(preliminaryConfig); diff --git a/packages/core/test/config/normalizeConfig_test.js b/packages/core/test/config/normalizeConfig_test.js index 7c35400caf..45a3c256e4 100644 --- a/packages/core/test/config/normalizeConfig_test.js +++ b/packages/core/test/config/normalizeConfig_test.js @@ -943,6 +943,32 @@ describe('config.normalizeConfig', () => { expect(config.tracing.ignoreEndpoints).to.deep.equal({}); }); + it('preloadOtelInstrumentations should default to false', () => { + const config = coreConfig.normalize({}); + expect(config.tracing.preloadOtelInstrumentations).to.be.false; + }); + + it('preloadOtelInstrumentations should accept true value', () => { + const config = coreConfig.normalize({ + tracing: { + preloadOtelInstrumentations: true + } + }); + expect(config.tracing.preloadOtelInstrumentations).to.be.true; + }); + + it('preloadOtelInstrumentations should work with custom defaults', () => { + const customDefaults = { + tracing: { + preloadOtelInstrumentations: true, + forceTransmissionStartingAt: 25 + } + }; + const config = coreConfig.normalize({}, customDefaults); + expect(config.tracing.preloadOtelInstrumentations).to.be.true; + expect(config.tracing.forceTransmissionStartingAt).to.equal(25); + }); + describe('when testing ignore endpoints reading from INSTANA_IGNORE_ENDPOINTS_PATH env variable', () => { let filePaths; @@ -1047,6 +1073,7 @@ describe('config.normalizeConfig', () => { expect(config.tracing.kafka.traceCorrelation).to.be.true; expect(config.tracing.useOpentelemetry).to.equal(true); expect(config.tracing.allowRootExitSpan).to.equal(false); + expect(config.tracing.preloadOtelInstrumentations).to.equal(false); expect(config.secrets).to.be.an('object'); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); From bf60bc83688c3cd2b8c2dbc6a839998f0257971f Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 18:27:51 +0530 Subject: [PATCH 10/20] chore: moved to preinit --- packages/aws-lambda/src/wrapper.js | 4 ++-- packages/core/src/config/index.js | 10 +++++----- packages/core/src/index.js | 3 --- packages/core/src/tracing/index.js | 7 +++++-- .../tracing/opentelemetry-instrumentations/index.js | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index cd2ddd1081..42be9b4563 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -21,6 +21,8 @@ const { tracing, coreConfig } = instanaCore; const { tracingHeaders, constants, spanBuffer } = tracing; const lambdaConfigDefaults = { + // Preload OpenTelemetry instrumentations to avoid lazy loading overhead + preloadOtelInstrumentations: true, tracing: { forceTransmissionStartingAt: 25, transmissionDelay: 100, @@ -35,8 +37,6 @@ const logger = serverlessLogger.init(); coreConfig.init(logger); let config = coreConfig.normalize({}, lambdaConfigDefaults); let coldStart = true; -// Preload OpenTelemetry instrumentations to avoid lazy loading overhead -config.tracing.preloadOtelInstrumentations = true; // Initialize instrumentations early to allow for require statements after our // package has been required but before the actual instana.wrap(...) call. diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 04a0dcb254..0063c6fa3d 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -36,7 +36,6 @@ const { validateStackTraceMode, validateStackTraceLength } = require('./configVa * @property {boolean} [ignoreEndpointsDisableSuppression] * @property {boolean} [disableEOLEvents] * @property {globalStackTraceConfig} [global] - * @property {boolean} [preloadOtelInstrumentations] */ /** @@ -83,6 +82,7 @@ const allowedSecretMatchers = ['equals', 'equals-ignore-case', 'contains', 'cont * @property {InstanaTracingOption} [tracing] * @property {InstanaSecretsOption} [secrets] * @property {number} [timeBetweenHealthcheckCalls] + * @property {boolean} [preloadOtelInstrumentations] */ /** @type {import('../core').GenericLogger} */ @@ -121,9 +121,9 @@ let defaults = { }, ignoreEndpoints: {}, ignoreEndpointsDisableSuppression: false, - disableEOLEvents: false, - preloadOtelInstrumentations: false + disableEOLEvents: false }, + preloadOtelInstrumentations: false, secrets: { matcherMode: 'contains-ignore-case', keywords: ['key', 'pass', 'secret'] @@ -823,9 +823,9 @@ function normalizeDisableEOLEvents(config) { * @param {InstanaConfig} config */ function normalizePreloadOtelInstrumentations(config) { - if (config.tracing.preloadOtelInstrumentations === true) { + if (config.preloadOtelInstrumentations === true) { return; } - config.tracing.preloadOtelInstrumentations = defaults.tracing.preloadOtelInstrumentations; + config.preloadOtelInstrumentations = defaults.preloadOtelInstrumentations; } diff --git a/packages/core/src/index.js b/packages/core/src/index.js index e73645ac3b..b774b855f0 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -62,9 +62,6 @@ function registerAdditionalInstrumentations(additionalInstrumentationModules) { * @param {import('./config').InstanaConfig} preliminaryConfig */ function preInit(preliminaryConfig) { - if (preliminaryConfig.tracing.preloadOtelInstrumentations) { - tracing.otelInstrumentations.preload(); - } util.init(preliminaryConfig); util.hasThePackageBeenInitializedTooLate.activate(); tracing.preInit(preliminaryConfig); diff --git a/packages/core/src/tracing/index.js b/packages/core/src/tracing/index.js index 914c3331f1..54f20bdff9 100644 --- a/packages/core/src/tracing/index.js +++ b/packages/core/src/tracing/index.js @@ -15,7 +15,7 @@ const tracingUtil = require('./tracingUtil'); const spanBuffer = require('./spanBuffer'); const shimmer = require('./shimmer'); const supportedVersion = require('./supportedVersion'); -const { otelInstrumentations } = require('./opentelemetry-instrumentations'); +const { otelInstrumentations, otelInstrumentationsPreload } = require('./opentelemetry-instrumentations'); const cls = require('./cls'); const coreUtil = require('../util'); @@ -162,6 +162,10 @@ exports.preInit = function preInit(preliminaryConfig) { * Another possible use case is, that its theoretically possible that the customer * can already start using the SDK although we are not fully initialized. */ + if (preliminaryConfig.preloadOtelInstrumentations) { + // Preload OpenTelemetry instrumentations to avoid lazy loading overhead + otelInstrumentationsPreload(); + } spanHandle.init(preliminaryConfig); shimmer.init(preliminaryConfig); cls.init(preliminaryConfig); @@ -353,4 +357,3 @@ exports._debugCurrentSpanName = function _debugCurrentSpanName() { }; exports.shimmer = require('./shimmer'); -exports.otelInstrumentations = require('./opentelemetry-instrumentations'); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/index.js b/packages/core/src/tracing/opentelemetry-instrumentations/index.js index c997c0cf8d..96102f0efd 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/index.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/index.js @@ -8,7 +8,7 @@ module.exports = { get otelInstrumentations() { return require('./wrap'); }, - get preload() { + get otelInstrumentationsPreload() { return require('./instrumentations').preload; } }; From 6c49f44caddea4d482efa42e4d0f7b62a9fac652 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 2 Feb 2026 18:37:29 +0530 Subject: [PATCH 11/20] test: fix --- packages/core/test/config/normalizeConfig_test.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/core/test/config/normalizeConfig_test.js b/packages/core/test/config/normalizeConfig_test.js index 45a3c256e4..4daddedf42 100644 --- a/packages/core/test/config/normalizeConfig_test.js +++ b/packages/core/test/config/normalizeConfig_test.js @@ -945,27 +945,25 @@ describe('config.normalizeConfig', () => { it('preloadOtelInstrumentations should default to false', () => { const config = coreConfig.normalize({}); - expect(config.tracing.preloadOtelInstrumentations).to.be.false; + expect(config.preloadOtelInstrumentations).to.be.false; }); it('preloadOtelInstrumentations should accept true value', () => { const config = coreConfig.normalize({ - tracing: { - preloadOtelInstrumentations: true - } + preloadOtelInstrumentations: true }); - expect(config.tracing.preloadOtelInstrumentations).to.be.true; + expect(config.preloadOtelInstrumentations).to.be.true; }); it('preloadOtelInstrumentations should work with custom defaults', () => { const customDefaults = { + preloadOtelInstrumentations: true, tracing: { - preloadOtelInstrumentations: true, forceTransmissionStartingAt: 25 } }; const config = coreConfig.normalize({}, customDefaults); - expect(config.tracing.preloadOtelInstrumentations).to.be.true; + expect(config.preloadOtelInstrumentations).to.be.true; expect(config.tracing.forceTransmissionStartingAt).to.equal(25); }); @@ -1073,7 +1071,8 @@ describe('config.normalizeConfig', () => { expect(config.tracing.kafka.traceCorrelation).to.be.true; expect(config.tracing.useOpentelemetry).to.equal(true); expect(config.tracing.allowRootExitSpan).to.equal(false); - expect(config.tracing.preloadOtelInstrumentations).to.equal(false); + + expect(config.preloadOtelInstrumentations).to.equal(false); expect(config.secrets).to.be.an('object'); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); From 6ebf334371efba0611c610bfe4bda13a949240b0 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 3 Feb 2026 10:39:49 +0530 Subject: [PATCH 12/20] chore: updates --- packages/aws-lambda/src/wrapper.js | 5 +++-- packages/core/src/config/index.js | 12 ++++++------ packages/core/src/tracing/index.js | 6 +++--- .../opentelemetry-instrumentations/index.js | 6 +++--- .../instrumentations.js | 7 ++++++- .../opentelemetry-instrumentations/wrap.js | 9 +++++---- .../core/test/config/normalizeConfig_test.js | 18 +++++++++--------- 7 files changed, 35 insertions(+), 28 deletions(-) diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 42be9b4563..76a9d1e7b6 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -21,8 +21,9 @@ const { tracing, coreConfig } = instanaCore; const { tracingHeaders, constants, spanBuffer } = tracing; const lambdaConfigDefaults = { - // Preload OpenTelemetry instrumentations to avoid lazy loading overhead - preloadOtelInstrumentations: true, + // Preload OpenTelemetry deps to avoid lazy loading overhead + // See https://jsw.ibm.com/browse/INSTA-71262 + preloadOpentelemetry: true, tracing: { forceTransmissionStartingAt: 25, transmissionDelay: 100, diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 0063c6fa3d..dde9e8e041 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -82,7 +82,7 @@ const allowedSecretMatchers = ['equals', 'equals-ignore-case', 'contains', 'cont * @property {InstanaTracingOption} [tracing] * @property {InstanaSecretsOption} [secrets] * @property {number} [timeBetweenHealthcheckCalls] - * @property {boolean} [preloadOtelInstrumentations] + * @property {boolean} [preloadOpentelemetry] */ /** @type {import('../core').GenericLogger} */ @@ -123,7 +123,7 @@ let defaults = { ignoreEndpointsDisableSuppression: false, disableEOLEvents: false }, - preloadOtelInstrumentations: false, + preloadOpentelemetry: false, secrets: { matcherMode: 'contains-ignore-case', keywords: ['key', 'pass', 'secret'] @@ -173,7 +173,7 @@ module.exports.normalize = (userConfig, defaultsOverride = {}) => { normalizeMetricsConfig(targetConfig); normalizeTracingConfig(targetConfig); normalizeSecrets(targetConfig); - normalizePreloadOtelInstrumentations(targetConfig); + normalizePreloadOpentelemetry(targetConfig); return targetConfig; }; @@ -822,10 +822,10 @@ function normalizeDisableEOLEvents(config) { /** * @param {InstanaConfig} config */ -function normalizePreloadOtelInstrumentations(config) { - if (config.preloadOtelInstrumentations === true) { +function normalizePreloadOpentelemetry(config) { + if (config.preloadOpentelemetry === true) { return; } - config.preloadOtelInstrumentations = defaults.preloadOtelInstrumentations; + config.preloadOpentelemetry = defaults.preloadOpentelemetry; } diff --git a/packages/core/src/tracing/index.js b/packages/core/src/tracing/index.js index 54f20bdff9..4b69d577c5 100644 --- a/packages/core/src/tracing/index.js +++ b/packages/core/src/tracing/index.js @@ -15,7 +15,7 @@ const tracingUtil = require('./tracingUtil'); const spanBuffer = require('./spanBuffer'); const shimmer = require('./shimmer'); const supportedVersion = require('./supportedVersion'); -const { otelInstrumentations, otelInstrumentationsPreload } = require('./opentelemetry-instrumentations'); +const otelInstrumentations = require('./opentelemetry-instrumentations'); const cls = require('./cls'); const coreUtil = require('../util'); @@ -162,9 +162,9 @@ exports.preInit = function preInit(preliminaryConfig) { * Another possible use case is, that its theoretically possible that the customer * can already start using the SDK although we are not fully initialized. */ - if (preliminaryConfig.preloadOtelInstrumentations) { + if (preliminaryConfig.preloadOpentelemetry) { // Preload OpenTelemetry instrumentations to avoid lazy loading overhead - otelInstrumentationsPreload(); + otelInstrumentations.preload(); } spanHandle.init(preliminaryConfig); shimmer.init(preliminaryConfig); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/index.js b/packages/core/src/tracing/opentelemetry-instrumentations/index.js index 96102f0efd..10510a237e 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/index.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/index.js @@ -5,10 +5,10 @@ 'use strict'; module.exports = { - get otelInstrumentations() { - return require('./wrap'); + get init() { + return require('./wrap').init; }, - get otelInstrumentationsPreload() { + get preload() { return require('./instrumentations').preload; } }; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js index ae9fc0a335..252e55088d 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js @@ -28,10 +28,15 @@ exports.getInstrumentations = () => { }; /** - * Preloads OpenTelemetry instrumentation packages to avoid lazy loading overhead. + * Preloads OpenTelemetry instrumentation packages and core dependencies to avoid lazy loading overhead. * This is particularly useful in AWS Lambda environments where cold start performance is affected by the lazy loading. */ exports.preload = () => { + require('@opentelemetry/context-async-hooks'); + require('@opentelemetry/core'); + require('@opentelemetry/api'); + require('@opentelemetry/sdk-trace-base'); + const packageNames = Object.keys(instrumentations); packageNames.forEach(packageName => { require(packageName); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index cbe1d794a8..427130f1f1 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -5,10 +5,6 @@ 'use strict'; -const { AsyncHooksContextManager } = require('@opentelemetry/context-async-hooks'); -const { W3CTraceContextPropagator, hrTimeDuration, hrTimeToMilliseconds } = require('@opentelemetry/core'); -const api = require('@opentelemetry/api'); -const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base'); const utils = require('./utils'); const constants = require('../constants'); const supportedVersion = require('../supportedVersion'); @@ -20,6 +16,11 @@ const instrumentations = getInstrumentations(); // logger.debug -> creates fs call -> calls transformToInstanaSpan -> calls logger.debug // use uninstrumented logger, but useless for production module.exports.init = (_config, cls) => { + const { AsyncHooksContextManager } = require('@opentelemetry/context-async-hooks'); + const { W3CTraceContextPropagator, hrTimeDuration, hrTimeToMilliseconds } = require('@opentelemetry/core'); + const api = require('@opentelemetry/api'); + const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base'); + if (!supportedVersion(process.versions.node)) { return; } diff --git a/packages/core/test/config/normalizeConfig_test.js b/packages/core/test/config/normalizeConfig_test.js index 4daddedf42..b61295fe6b 100644 --- a/packages/core/test/config/normalizeConfig_test.js +++ b/packages/core/test/config/normalizeConfig_test.js @@ -943,27 +943,27 @@ describe('config.normalizeConfig', () => { expect(config.tracing.ignoreEndpoints).to.deep.equal({}); }); - it('preloadOtelInstrumentations should default to false', () => { + it('preloadOpentelemetry should default to false', () => { const config = coreConfig.normalize({}); - expect(config.preloadOtelInstrumentations).to.be.false; + expect(config.preloadOpentelemetry).to.be.false; }); - it('preloadOtelInstrumentations should accept true value', () => { + it('preloadOpentelemetry should accept true value', () => { const config = coreConfig.normalize({ - preloadOtelInstrumentations: true + preloadOpentelemetry: true }); - expect(config.preloadOtelInstrumentations).to.be.true; + expect(config.preloadOpentelemetry).to.be.true; }); - it('preloadOtelInstrumentations should work with custom defaults', () => { + it('preloadOpentelemetry should work with custom defaults', () => { const customDefaults = { - preloadOtelInstrumentations: true, + preloadOpentelemetry: true, tracing: { forceTransmissionStartingAt: 25 } }; const config = coreConfig.normalize({}, customDefaults); - expect(config.preloadOtelInstrumentations).to.be.true; + expect(config.preloadOpentelemetry).to.be.true; expect(config.tracing.forceTransmissionStartingAt).to.equal(25); }); @@ -1072,7 +1072,7 @@ describe('config.normalizeConfig', () => { expect(config.tracing.useOpentelemetry).to.equal(true); expect(config.tracing.allowRootExitSpan).to.equal(false); - expect(config.preloadOtelInstrumentations).to.equal(false); + expect(config.preloadOpentelemetry).to.equal(false); expect(config.secrets).to.be.an('object'); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); From f0d57cbae385881c208220eaa1439fb8dde44d03 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 3 Feb 2026 17:30:54 +0530 Subject: [PATCH 13/20] chore: update --- packages/core/src/tracing/index.js | 5 +- .../confluent-kafka.js | 4 + .../opentelemetry-instrumentations/fs.js | 4 + .../opentelemetry-instrumentations/index.js | 4 +- .../instrumentations.js | 44 ----------- .../opentelemetry-instrumentations/oracle.js | 4 + .../opentelemetry-instrumentations/restify.js | 4 + .../socket.io.js | 5 ++ .../opentelemetry-instrumentations/tedious.js | 4 + .../opentelemetry-instrumentations/wrap.js | 34 +++++++- .../instrumentations_test.js | 77 ------------------- 11 files changed, 60 insertions(+), 129 deletions(-) delete mode 100644 packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js delete mode 100644 packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js diff --git a/packages/core/src/tracing/index.js b/packages/core/src/tracing/index.js index 4b69d577c5..65fd713186 100644 --- a/packages/core/src/tracing/index.js +++ b/packages/core/src/tracing/index.js @@ -162,10 +162,7 @@ exports.preInit = function preInit(preliminaryConfig) { * Another possible use case is, that its theoretically possible that the customer * can already start using the SDK although we are not fully initialized. */ - if (preliminaryConfig.preloadOpentelemetry) { - // Preload OpenTelemetry instrumentations to avoid lazy loading overhead - otelInstrumentations.preload(); - } + otelInstrumentations.preInit(preliminaryConfig); spanHandle.init(preliminaryConfig); shimmer.init(preliminaryConfig); cls.init(preliminaryConfig); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js b/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js index 3df80c30e5..a6be3f1948 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js @@ -7,6 +7,10 @@ const constants = require('../constants'); const W3cTraceContext = require('../w3c_trace_context/W3cTraceContext'); +module.exports.preInit = () => { + require('@instana/instrumentation-confluent-kafka-javascript'); +}; + module.exports.init = () => { const { ConfluentKafkaInstrumentation } = require('@instana/instrumentation-confluent-kafka-javascript'); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/fs.js b/packages/core/src/tracing/opentelemetry-instrumentations/fs.js index e4e8d01567..9c04bf2950 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/fs.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/fs.js @@ -4,6 +4,10 @@ 'use strict'; +module.exports.preInit = () => { + require('@opentelemetry/instrumentation-fs'); +}; + // NOTE: otel fs instrumentation does not capture the file name currently module.exports.init = ({ cls, api }) => { const constants = require('../constants'); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/index.js b/packages/core/src/tracing/opentelemetry-instrumentations/index.js index 10510a237e..85133c5c48 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/index.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/index.js @@ -8,7 +8,7 @@ module.exports = { get init() { return require('./wrap').init; }, - get preload() { - return require('./instrumentations').preload; + get preInit() { + return require('./wrap').preInit; } }; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js b/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js deleted file mode 100644 index 252e55088d..0000000000 --- a/packages/core/src/tracing/opentelemetry-instrumentations/instrumentations.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * (c) Copyright IBM Corp. 2026 - */ - -'use strict'; - -/** - * Registry of supported OpenTelemetry instrumentations. - * Maps instrumentation package names to their internal module names. - * - * NOTE: Please refrain from utilizing third-party instrumentations. - * Instead, opt for officially released instrumentations available in the OpenTelemetry - * repository at https://github.com/open-telemetry/opentelemetry-js-contrib. - * Third-party instrumentations typically bypass a review process, - * resulting in suboptimal code coverage and potential vulnerabilities. - */ -const instrumentations = { - '@opentelemetry/instrumentation-fs': { name: 'fs' }, - '@opentelemetry/instrumentation-restify': { name: 'restify' }, - '@opentelemetry/instrumentation-socket.io': { name: 'socket.io' }, - '@opentelemetry/instrumentation-tedious': { name: 'tedious' }, - '@opentelemetry/instrumentation-oracledb': { name: 'oracle' }, - '@instana/instrumentation-confluent-kafka-javascript': { name: 'confluent-kafka' } -}; - -exports.getInstrumentations = () => { - return instrumentations; -}; - -/** - * Preloads OpenTelemetry instrumentation packages and core dependencies to avoid lazy loading overhead. - * This is particularly useful in AWS Lambda environments where cold start performance is affected by the lazy loading. - */ -exports.preload = () => { - require('@opentelemetry/context-async-hooks'); - require('@opentelemetry/core'); - require('@opentelemetry/api'); - require('@opentelemetry/sdk-trace-base'); - - const packageNames = Object.keys(instrumentations); - packageNames.forEach(packageName => { - require(packageName); - }); -}; diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js b/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js index 35a3c9b592..3551038051 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js @@ -6,6 +6,10 @@ const constants = require('../constants'); +module.exports.preInit = () => { + require('@opentelemetry/instrumentation-oracledb'); +}; + module.exports.init = () => { const { OracleInstrumentation } = require('@opentelemetry/instrumentation-oracledb'); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/restify.js b/packages/core/src/tracing/opentelemetry-instrumentations/restify.js index bf4282f9d2..bc96045aaf 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/restify.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/restify.js @@ -6,6 +6,10 @@ const constants = require('../constants'); +module.exports.preInit = () => { + require('@opentelemetry/instrumentation-restify'); +}; + module.exports.init = () => { const { RestifyInstrumentation } = require('@opentelemetry/instrumentation-restify'); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js b/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js index 240095f667..994187f7dc 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js @@ -7,6 +7,11 @@ const constants = require('../constants'); const isOnEvent = otelSpan => otelSpan.name.indexOf('receive') !== -1; + +exports.preInit = () => { + require('@opentelemetry/instrumentation-socket.io'); +}; + /** * socket.io-client is not instrumented. * We can easily instrument socket.io-client by instrumenting @socket.io/component-emitter diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js b/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js index 0b0753bdc7..99aa9abe85 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js @@ -6,6 +6,10 @@ const constants = require('../constants'); +module.exports.preInit = () => { + require('@opentelemetry/instrumentation-tedious'); +}; + module.exports.init = () => { // Opentelemetry only supports tedious version >=1.11.0 and <=15, please refer the following link // for more details: https://www.npmjs.com/package/@opentelemetry/instrumentation-tedious#supported-versions diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index 427130f1f1..abdddcc4c5 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -8,9 +8,39 @@ const utils = require('./utils'); const constants = require('../constants'); const supportedVersion = require('../supportedVersion'); -const { getInstrumentations } = require('./instrumentations'); -const instrumentations = getInstrumentations(); +const instrumentations = { + '@opentelemetry/instrumentation-fs': { name: 'fs' }, + '@opentelemetry/instrumentation-restify': { name: 'restify' }, + '@opentelemetry/instrumentation-socket.io': { name: 'socket.io' }, + '@opentelemetry/instrumentation-tedious': { name: 'tedious' }, + '@opentelemetry/instrumentation-oracledb': { name: 'oracle' }, + '@instana/instrumentation-confluent-kafka-javascript': { name: 'confluent-kafka' } +}; + +/** + * Preloads OpenTelemetry dependencies when preloadOpentelemetry config is enabled. + * @param {import('../../config').InstanaConfig} config + */ +module.exports.preInit = config => { + if (!config.preloadOpentelemetry) { + return; + } + + require('@opentelemetry/context-async-hooks'); + require('@opentelemetry/core'); + require('@opentelemetry/api'); + require('@opentelemetry/sdk-trace-base'); + + Object.keys(instrumentations).forEach(k => { + const value = instrumentations[k]; + const instrumentation = require(`./${value.name}`); + + if (instrumentation.preInit) { + instrumentation.preInit(); + } + }); +}; // NOTE: using a logger might create a recursive execution // logger.debug -> creates fs call -> calls transformToInstanaSpan -> calls logger.debug diff --git a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js b/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js deleted file mode 100644 index 2973e23279..0000000000 --- a/packages/core/test/tracing/opentelemetry-instrumentations/instrumentations_test.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * (c) Copyright IBM Corp. 2026 - */ - -'use strict'; - -const expect = require('chai').expect; -const sinon = require('sinon'); - -describe('OpenTelemetry instrumentations registry', () => { - let instrumentationsModule; - - beforeEach(() => { - delete require.cache[require.resolve('../../../src/tracing/opentelemetry-instrumentations/instrumentations')]; - instrumentationsModule = require('../../../src/tracing/opentelemetry-instrumentations/instrumentations'); - }); - - describe('getInstrumentations', () => { - it('should return an object', () => { - const instrumentations = instrumentationsModule.getInstrumentations(); - expect(instrumentations).to.be.an('object'); - }); - - it('should return the same object on multiple calls', () => { - const first = instrumentationsModule.getInstrumentations(); - const second = instrumentationsModule.getInstrumentations(); - expect(first).to.equal(second); - }); - - it('should contain fs instrumentation', () => { - const instrumentations = instrumentationsModule.getInstrumentations(); - expect(instrumentations).to.have.property('@opentelemetry/instrumentation-fs'); - expect(instrumentations['@opentelemetry/instrumentation-fs']).to.deep.equal({ name: 'fs' }); - }); - - it('should contain restify instrumentation', () => { - const instrumentations = instrumentationsModule.getInstrumentations(); - expect(instrumentations).to.have.property('@opentelemetry/instrumentation-restify'); - expect(instrumentations['@opentelemetry/instrumentation-restify']).to.deep.equal({ name: 'restify' }); - }); - - it('should have exactly 6 instrumentations', () => { - const instrumentations = instrumentationsModule.getInstrumentations(); - expect(Object.keys(instrumentations)).to.have.lengthOf(6); - }); - }); - - describe('preload', () => { - let consoleLogStub; - - beforeEach(() => { - consoleLogStub = sinon.stub(console, 'log'); - }); - - afterEach(() => { - consoleLogStub.restore(); - }); - - it('should be a function', () => { - expect(instrumentationsModule.preload).to.be.a('function'); - }); - - it('should not throw when called', () => { - expect(() => { - instrumentationsModule.preload(); - }).to.not.throw(); - }); - - it('should complete in reasonable time', () => { - const startTime = Date.now(); - instrumentationsModule.preload(); - const duration = Date.now() - startTime; - - expect(duration).to.be.lessThan(1000); - }); - }); -}); From 4a6e6a679fe7be4fa32396912398f03b8e0775b5 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 3 Feb 2026 20:38:40 +0530 Subject: [PATCH 14/20] chore: updated --- .../opentelemetry-instrumentations/wrap.js | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index abdddcc4c5..fdac58fae7 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -18,27 +18,37 @@ const instrumentations = { '@instana/instrumentation-confluent-kafka-javascript': { name: 'confluent-kafka' } }; -/** - * Preloads OpenTelemetry dependencies when preloadOpentelemetry config is enabled. - * @param {import('../../config').InstanaConfig} config - */ +let AsyncHooksContextManager; +let W3CTraceContextPropagator; +let hrTimeDuration; +let hrTimeToMilliseconds; +let api; +let BasicTracerProvider; +let coreModule; + +function loadOtelDependencies() { + api = api || require('@opentelemetry/api'); + coreModule = coreModule || require('@opentelemetry/core'); + AsyncHooksContextManager = + AsyncHooksContextManager || require('@opentelemetry/context-async-hooks').AsyncHooksContextManager; + BasicTracerProvider = BasicTracerProvider || require('@opentelemetry/sdk-trace-base').BasicTracerProvider; + + W3CTraceContextPropagator = coreModule.W3CTraceContextPropagator; + hrTimeDuration = coreModule.hrTimeDuration; + hrTimeToMilliseconds = coreModule.hrTimeToMilliseconds; +} + module.exports.preInit = config => { - if (!config.preloadOpentelemetry) { + if (!supportedVersion(process.versions.node)) { return; } + if (!config?.preloadOpentelemetry) return; - require('@opentelemetry/context-async-hooks'); - require('@opentelemetry/core'); - require('@opentelemetry/api'); - require('@opentelemetry/sdk-trace-base'); - - Object.keys(instrumentations).forEach(k => { - const value = instrumentations[k]; - const instrumentation = require(`./${value.name}`); + loadOtelDependencies(); - if (instrumentation.preInit) { - instrumentation.preInit(); - } + Object.values(instrumentations).forEach(instr => { + const instrumentation = require(`./${instr.name}`); + if (instrumentation.preInit) instrumentation.preInit(); }); }; @@ -46,15 +56,12 @@ module.exports.preInit = config => { // logger.debug -> creates fs call -> calls transformToInstanaSpan -> calls logger.debug // use uninstrumented logger, but useless for production module.exports.init = (_config, cls) => { - const { AsyncHooksContextManager } = require('@opentelemetry/context-async-hooks'); - const { W3CTraceContextPropagator, hrTimeDuration, hrTimeToMilliseconds } = require('@opentelemetry/core'); - const api = require('@opentelemetry/api'); - const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base'); - if (!supportedVersion(process.versions.node)) { return; } + loadOtelDependencies(); + Object.keys(instrumentations).forEach(k => { const value = instrumentations[k]; const instrumentation = require(`./${value.name}`); From bd5100292378685ad5ad30d1203f98caaf2bfc11 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 3 Feb 2026 21:52:30 +0530 Subject: [PATCH 15/20] chore: updated --- .../src/tracing/opentelemetry-instrumentations/wrap.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index fdac58fae7..60fd0e42bc 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -42,13 +42,18 @@ module.exports.preInit = config => { if (!supportedVersion(process.versions.node)) { return; } - if (!config?.preloadOpentelemetry) return; + + if (!config?.preloadOpentelemetry) { + return; + } loadOtelDependencies(); Object.values(instrumentations).forEach(instr => { const instrumentation = require(`./${instr.name}`); - if (instrumentation.preInit) instrumentation.preInit(); + if (instrumentation.preInit) { + instrumentation.preInit(); + } }); }; From 327cc4e2920ac445c0a1347dd72fd3c84f8875d8 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 3 Feb 2026 21:56:17 +0530 Subject: [PATCH 16/20] chore: updated --- .../core/src/tracing/opentelemetry-instrumentations/wrap.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index 60fd0e42bc..e8a2c31fb7 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -9,6 +9,11 @@ const utils = require('./utils'); const constants = require('../constants'); const supportedVersion = require('../supportedVersion'); +// NOTE: Please refrain from utilizing third-party instrumentations. +// Instead, opt for officially released instrumentations available in the OpenTelemetry +// repository at https://github.com/open-telemetry/opentelemetry-js-contrib. +// Third-party instrumentations typically bypass a review process, +// resulting in suboptimal code coverage and potential vulnerabilities. const instrumentations = { '@opentelemetry/instrumentation-fs': { name: 'fs' }, '@opentelemetry/instrumentation-restify': { name: 'restify' }, From 525729193c7dc1e5f85196835db97bd7e71b0ecd Mon Sep 17 00:00:00 2001 From: Arya Date: Wed, 4 Feb 2026 17:00:47 +0530 Subject: [PATCH 17/20] chore: updated --- .../opentelemetry-instrumentations/wrap.js | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index e8a2c31fb7..3fbccee51e 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -31,7 +31,7 @@ let api; let BasicTracerProvider; let coreModule; -function loadOtelDependencies() { +function initOtelCoreDependencies() { api = api || require('@opentelemetry/api'); coreModule = coreModule || require('@opentelemetry/core'); AsyncHooksContextManager = @@ -43,6 +43,15 @@ function loadOtelDependencies() { hrTimeToMilliseconds = coreModule.hrTimeToMilliseconds; } +function initInstrumentations() { + Object.values(instrumentations).forEach(instr => { + const instrumentation = require(`./${instr.name}`); + if (instrumentation.preInit) { + instrumentation.preInit(); + } + }); +} + module.exports.preInit = config => { if (!supportedVersion(process.versions.node)) { return; @@ -52,14 +61,8 @@ module.exports.preInit = config => { return; } - loadOtelDependencies(); - - Object.values(instrumentations).forEach(instr => { - const instrumentation = require(`./${instr.name}`); - if (instrumentation.preInit) { - instrumentation.preInit(); - } - }); + initOtelCoreDependencies(); + initInstrumentations(); }; // NOTE: using a logger might create a recursive execution @@ -70,7 +73,7 @@ module.exports.init = (_config, cls) => { return; } - loadOtelDependencies(); + initOtelCoreDependencies(); Object.keys(instrumentations).forEach(k => { const value = instrumentations[k]; From 70f9bf499804c6a7349156fa4c103bd88e831e73 Mon Sep 17 00:00:00 2001 From: Arya Date: Thu, 5 Feb 2026 16:06:12 +0530 Subject: [PATCH 18/20] chore: update --- .../confluent-kafka.js | 12 ++++++++++-- .../src/tracing/opentelemetry-instrumentations/fs.js | 10 ++++++++-- .../tracing/opentelemetry-instrumentations/oracle.js | 11 +++++++++-- .../opentelemetry-instrumentations/restify.js | 12 ++++++++++-- .../opentelemetry-instrumentations/socket.io.js | 11 +++++++++-- .../opentelemetry-instrumentations/tedious.js | 11 +++++++++-- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js b/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js index a6be3f1948..f4d99ff076 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/confluent-kafka.js @@ -7,12 +7,20 @@ const constants = require('../constants'); const W3cTraceContext = require('../w3c_trace_context/W3cTraceContext'); +let ConfluentKafkaInstrumentation; + +function initInstrumentation() { + ConfluentKafkaInstrumentation = + ConfluentKafkaInstrumentation || + require('@instana/instrumentation-confluent-kafka-javascript').ConfluentKafkaInstrumentation; +} + module.exports.preInit = () => { - require('@instana/instrumentation-confluent-kafka-javascript'); + initInstrumentation(); }; module.exports.init = () => { - const { ConfluentKafkaInstrumentation } = require('@instana/instrumentation-confluent-kafka-javascript'); + initInstrumentation(); const instrumentation = new ConfluentKafkaInstrumentation({}); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/fs.js b/packages/core/src/tracing/opentelemetry-instrumentations/fs.js index 9c04bf2950..8ea068cb33 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/fs.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/fs.js @@ -4,15 +4,21 @@ 'use strict'; +let FsInstrumentation; + +function initInstrumentation() { + FsInstrumentation = FsInstrumentation || require('@opentelemetry/instrumentation-fs').FsInstrumentation; +} + module.exports.preInit = () => { - require('@opentelemetry/instrumentation-fs'); + initInstrumentation(); }; // NOTE: otel fs instrumentation does not capture the file name currently module.exports.init = ({ cls, api }) => { + initInstrumentation(); const constants = require('../constants'); const { NonRecordingSpan } = require('./files/NonRecordingSpan'); - const { FsInstrumentation } = require('@opentelemetry/instrumentation-fs'); // eslint-disable-next-line max-len // https://github.com/open-telemetry/opentelemetry-js-contrib/pull/1335/files#diff-9a2f445c78d964623d07987299501cbc3101cbe0f76f9e18d2d75787601539daR428 diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js b/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js index 3551038051..13bf58f281 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/oracle.js @@ -6,12 +6,19 @@ const constants = require('../constants'); +let OracleInstrumentation; + +function initInstrumentation() { + OracleInstrumentation = + OracleInstrumentation || require('@opentelemetry/instrumentation-oracledb').OracleInstrumentation; +} + module.exports.preInit = () => { - require('@opentelemetry/instrumentation-oracledb'); + initInstrumentation(); }; module.exports.init = () => { - const { OracleInstrumentation } = require('@opentelemetry/instrumentation-oracledb'); + initInstrumentation(); const instrumentation = new OracleInstrumentation(); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/restify.js b/packages/core/src/tracing/opentelemetry-instrumentations/restify.js index bc96045aaf..5c8182a87a 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/restify.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/restify.js @@ -6,12 +6,20 @@ const constants = require('../constants'); +let RestifyInstrumentation; + +function initInstrumentation() { + if (!RestifyInstrumentation) { + RestifyInstrumentation = require('@opentelemetry/instrumentation-restify').RestifyInstrumentation; + } +} + module.exports.preInit = () => { - require('@opentelemetry/instrumentation-restify'); + initInstrumentation(); }; module.exports.init = () => { - const { RestifyInstrumentation } = require('@opentelemetry/instrumentation-restify'); + initInstrumentation(); const instrumentation = new RestifyInstrumentation(); diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js b/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js index 994187f7dc..168e2bb9db 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/socket.io.js @@ -6,10 +6,17 @@ const constants = require('../constants'); +let SocketIoInstrumentation; + +function initInstrumentation() { + SocketIoInstrumentation = + SocketIoInstrumentation || require('@opentelemetry/instrumentation-socket.io').SocketIoInstrumentation; +} + const isOnEvent = otelSpan => otelSpan.name.indexOf('receive') !== -1; exports.preInit = () => { - require('@opentelemetry/instrumentation-socket.io'); + initInstrumentation(); }; /** @@ -23,7 +30,7 @@ exports.preInit = () => { * headers or meta data, only payload! */ exports.init = () => { - const { SocketIoInstrumentation } = require('@opentelemetry/instrumentation-socket.io'); + initInstrumentation(); const instrumentation = new SocketIoInstrumentation(); if (!instrumentation.getConfig().enabled) { diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js b/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js index 99aa9abe85..a8ea5ef5bd 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/tedious.js @@ -6,15 +6,22 @@ const constants = require('../constants'); +let TediousInstrumentation; + +function initInstrumentation() { + TediousInstrumentation = + TediousInstrumentation || require('@opentelemetry/instrumentation-tedious').TediousInstrumentation; +} + module.exports.preInit = () => { - require('@opentelemetry/instrumentation-tedious'); + initInstrumentation(); }; module.exports.init = () => { // Opentelemetry only supports tedious version >=1.11.0 and <=15, please refer the following link // for more details: https://www.npmjs.com/package/@opentelemetry/instrumentation-tedious#supported-versions - const { TediousInstrumentation } = require('@opentelemetry/instrumentation-tedious'); + initInstrumentation(); const instrumentation = new TediousInstrumentation(); From 23520c04c44e7c0cf26745d7b2052c2255688305 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 9 Feb 2026 10:08:40 +0530 Subject: [PATCH 19/20] chore: updated --- .../core/src/tracing/opentelemetry-instrumentations/wrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index 3fbccee51e..25fb921155 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -43,7 +43,7 @@ function initOtelCoreDependencies() { hrTimeToMilliseconds = coreModule.hrTimeToMilliseconds; } -function initInstrumentations() { +function preInitInstrumentations() { Object.values(instrumentations).forEach(instr => { const instrumentation = require(`./${instr.name}`); if (instrumentation.preInit) { @@ -62,7 +62,7 @@ module.exports.preInit = config => { } initOtelCoreDependencies(); - initInstrumentations(); + preInitInstrumentations(); }; // NOTE: using a logger might create a recursive execution From 6cd4698dedb90fd0ef5b7b664369ebffbc5892d6 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 9 Feb 2026 11:40:48 +0530 Subject: [PATCH 20/20] chore: updated --- .../opentelemetry-instrumentations/wrap.js | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js index 25fb921155..8ebbcf66c5 100644 --- a/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js +++ b/packages/core/src/tracing/opentelemetry-instrumentations/wrap.js @@ -43,12 +43,24 @@ function initOtelCoreDependencies() { hrTimeToMilliseconds = coreModule.hrTimeToMilliseconds; } +function getInstrumentation(instr) { + if (!instr.module) { + instr.module = require(`./${instr.name}`); + } + return instr.module; +} + function preInitInstrumentations() { Object.values(instrumentations).forEach(instr => { - const instrumentation = require(`./${instr.name}`); - if (instrumentation.preInit) { - instrumentation.preInit(); - } + const instrumentation = getInstrumentation(instr); + instrumentation.preInit?.(); + }); +} + +function initInstrumentations(cls) { + Object.values(instrumentations).forEach(instr => { + const instrumentation = getInstrumentation(instr); + instrumentation.init?.({ cls, api: api }); }); } @@ -74,13 +86,7 @@ module.exports.init = (_config, cls) => { } initOtelCoreDependencies(); - - Object.keys(instrumentations).forEach(k => { - const value = instrumentations[k]; - const instrumentation = require(`./${value.name}`); - instrumentation.init({ cls, api: api }); - value.module = instrumentation; - }); + initInstrumentations(cls); const prepareData = (otelSpan, instrumentation) => { const obj = {