diff --git a/packages/aws-fargate/src/activate.js b/packages/aws-fargate/src/activate.js index 05b3a785a6..0aa5042be5 100644 --- a/packages/aws-fargate/src/activate.js +++ b/packages/aws-fargate/src/activate.js @@ -6,25 +6,30 @@ 'use strict'; const instanaCore = require('@instana/core'); -const { backendConnector, consoleLogger: log } = require('@instana/serverless'); +const { backendConnector, consoleLogger: serverlessLogger } = require('@instana/serverless'); const identityProvider = require('./identity_provider'); const metrics = require('./metrics'); const { fullyQualifiedContainerId } = require('./metrics/container/containerUtil'); +const { tracing, coreConfig, coreUtils } = instanaCore; -const { tracing, util: coreUtil } = instanaCore; -const { normalizeConfig } = coreUtil; +const instanaCtr = new instanaCore.InstanaCtr(); -const logger = log.init(); -const config = normalizeConfig({}, logger); +coreUtils.init(instanaCtr); +coreConfig.init(instanaCtr); +serverlessLogger.init(instanaCtr); + +instanaCtr.set('utils', coreUtils.create()); +instanaCtr.set('config', coreConfig.create()); +instanaCtr.set('logger', serverlessLogger.create()); function init() { - instanaCore.preInit(config); + instanaCore.preInit(instanaCtr.config(), instanaCtr.utils()); - metrics.init(config, function onReady(err, ecsContainerPayload) { + metrics.init(instanaCtr.config(), function onReady(err, ecsContainerPayload) { if (err) { - logger.error( - `Initializing @instana/aws-fargate failed. This fargate task will not be monitored. + instanaCtr.logger().error( + `Initializing @instana/aws-fargate failed. This fargate task will not be monitored. ${err?.message} ${err?.stack}` ); metrics.deactivate(); @@ -34,10 +39,12 @@ function init() { try { const taskArn = ecsContainerPayload && ecsContainerPayload.data ? ecsContainerPayload.data.taskArn : null; if (!taskArn) { - logger.error( - 'Initializing @instana/aws-fargate failed, the metadata did not have a task ARN. This fargate task will ' + - 'not be monitored.' - ); + instanaCtr + .logger() + .error( + 'Initializing @instana/aws-fargate failed, the metadata did not have a task ARN. This fargate task will ' + + 'not be monitored.' + ); metrics.deactivate(); return; } @@ -45,10 +52,12 @@ function init() { ? fullyQualifiedContainerId(taskArn, ecsContainerPayload.data.containerName) : null; if (!containerId) { - logger.error( - 'Initializing @instana/aws-fargate failed, the metadata did not have a container name. This fargate task ' + - 'will not be monitored.' - ); + instanaCtr + .logger() + .error( + 'Initializing @instana/aws-fargate failed, the metadata did not have a container name. This fargate task ' + + 'will not be monitored.' + ); metrics.deactivate(); return; } @@ -56,23 +65,25 @@ function init() { identityProvider.init(taskArn, containerId); backendConnector.init({ - config, + config: instanaCtr.config(), identityProvider, defaultTimeout: 950 }); - instanaCore.init(config, backendConnector, identityProvider); + instanaCore.init(instanaCtr.config(), instanaCtr.utils(), backendConnector, identityProvider); metrics.activate(backendConnector); tracing.activate(); - logger.debug('@instana/aws-fargate initialized.'); + instanaCtr.logger().debug('@instana/aws-fargate initialized.'); // eslint-disable-next-line no-unused-expressions process.send && process.send('instana.aws-fargate.initialized'); } catch (e) { - logger.error( - `Initializing @instana/aws-fargate failed. This fargate task will not be monitored. ${e?.message} ${e?.stack}` - ); + instanaCtr + .logger() + .error( + `Initializing @instana/aws-fargate failed. This fargate task will not be monitored. ${e?.message} ${e?.stack}` + ); } }); } @@ -88,7 +99,7 @@ exports.sdk = tracing.sdk; // NOTE: this is the external interface for the customer. They can set a custom logger. exports.setLogger = function setLogger(_logger) { - log.init({ logger: _logger }); + instanaCtr.logger().setLogger(_logger); }; exports.opentracing = tracing.opentracing; diff --git a/packages/aws-fargate/test/Control.js b/packages/aws-fargate/test/Control.js index de10e80e60..847707d0e5 100644 --- a/packages/aws-fargate/test/Control.js +++ b/packages/aws-fargate/test/Control.js @@ -13,7 +13,7 @@ const config = require('@instana/core/test/config'); const AbstractServerlessControl = require('../../serverless/test/util/AbstractServerlessControl'); const portfinder = require('../../collector/test/test_util/portfinder'); const PATH_TO_INSTANA_FARGATE_PACKAGE = path.join(__dirname, '..'); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; let execArg; function Control(opts) { diff --git a/packages/aws-fargate/test/metrics/transmissionCycle_test.js b/packages/aws-fargate/test/metrics/transmissionCycle_test.js index 759368a124..4173e6cacc 100644 --- a/packages/aws-fargate/test/metrics/transmissionCycle_test.js +++ b/packages/aws-fargate/test/metrics/transmissionCycle_test.js @@ -32,7 +32,7 @@ describe('transmission cycle', function () { let onReadyError; before(() => { - const config = core.util.normalizeConfig({}); + const config = core.config.normalize(); core.secrets.init(config); const metadataMockPort = portfinder(); diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 1e6aaab80b..973e02c4d5 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -6,7 +6,7 @@ 'use strict'; const instanaCore = require('@instana/core'); -const { backendConnector, consoleLogger: log, environment } = require('@instana/serverless'); +const { backendConnector, consoleLogger: serverlessLogger, environment } = require('@instana/serverless'); const arnParser = require('./arn'); const identityProvider = require('./identity_provider'); const metrics = require('./metrics'); @@ -15,21 +15,29 @@ const triggers = require('./triggers'); const processResult = require('./process_result'); const captureHeaders = require('./capture_headers'); -const { tracing, util: coreUtil } = instanaCore; -const { normalizeConfig } = coreUtil; +const { tracing, coreConfig, coreUtils } = instanaCore; const { tracingHeaders, constants, spanBuffer } = tracing; const lambdaConfigDefaults = { tracing: { forceTransmissionStartingAt: 25, transmissionDelay: 100, initialTransmissionDelay: 100 } }; -const logger = log.init(); -let config = normalizeConfig({}, logger, lambdaConfigDefaults); let coldStart = true; +const instanaCtr = new instanaCore.InstanaCtr(); + +coreUtils.init(instanaCtr); +coreConfig.init(instanaCtr); +serverlessLogger.init(instanaCtr); + +instanaCtr.set('utils', coreUtils.create()); +instanaCtr.set('config', coreConfig.create({}, lambdaConfigDefaults)); +instanaCtr.set('logger', serverlessLogger.create()); + // Initialize instrumentations early to allow for require statements after our // package has been required but before the actual instana.wrap(...) call. -instanaCore.preInit(config); +// TODO: refactor to use `instanaCtr` only! +instanaCore.preInit(instanaCtr.config(), instanaCtr.utils()); /** * Wraps an AWS Lambda handler so that metrics and traces are reported to Instana. This function will figure out if the @@ -191,7 +199,7 @@ function shimmedHandler(originalHandler, originalThis, originalArgs, _config) { process.env.INSTANA_ENABLE_LAMBDA_TIMEOUT_DETECTION && process.env.INSTANA_ENABLE_LAMBDA_TIMEOUT_DETECTION === 'true' ) { - logger.debug('Heuristical timeout detection enabled. Please only use for debugging purposes.'); + instanaCtr.logger().debug('Heuristical timeout detection enabled. Please only use for debugging purposes.'); registerTimeoutDetection(context, entrySpan); } @@ -245,34 +253,41 @@ function init(event, arnInfo, _config) { // CASE: customer provides a custom logger or custom level if (customConfig.logger || customConfig.level) { - log.init(customConfig); + instanaCtr.setLogger(serverlessLogger.create(customConfig)); } - // NOTE: We SHOULD renormalize because of: + // NOTE: We SHOULD re-create the config object, because: // - in-code _config object // - late env variables (less likely) // - custom logger // - we always renormalize unconditionally to ensure safety. - config = normalizeConfig(customConfig, logger, lambdaConfigDefaults); + // This is a consequence of pre-initializing early. + instanaCtr.set('config', coreConfig.create(customConfig, lambdaConfigDefaults)); - if (!config.tracing.enabled) { + if (!instanaCtr.config().tracing.enabled) { return false; } const useLambdaExtension = shouldUseLambdaExtension(); if (useLambdaExtension) { - logger.info('@instana/aws-lambda will use the Instana Lambda extension to send data to the Instana back end.'); + instanaCtr + .logger() + .info('@instana/aws-lambda will use the Instana Lambda extension to send data to the Instana back end.'); } else { - logger.info( - '@instana/aws-lambda will not use the Instana Lambda extension, but instead send data to the Instana back end ' + - 'directly.' - ); + instanaCtr + .logger() + .info( + '@instana/aws-lambda will not use the Instana Lambda extension, ' + + 'but instead send data to the Instana back end ' + + 'directly.' + ); } identityProvider.init(arnInfo); - triggers.init(config); + triggers.init(instanaCtr.config()); + backendConnector.init({ - config, + config: instanaCtr.config(), identityProvider, defaultTimeout: 500, useLambdaExtension, @@ -282,16 +297,16 @@ function init(event, arnInfo, _config) { retries: !!useLambdaExtension }); - instanaCore.init(config, backendConnector, identityProvider); + instanaCore.init(instanaCtr.config(), instanaCtr.utils(), backendConnector, identityProvider); // After core init, because ssm requires require('@aws-sdk/client-ssm'), which triggers // the requireHook + shimmer. Any module which requires another external module has to be // initialized after the core. - ssm.init(config); + ssm.init(instanaCtr.config()); spanBuffer.setIsFaaS(true); - captureHeaders.init(config); - metrics.init(config); + captureHeaders.init(instanaCtr.config()); + metrics.init(instanaCtr.config()); metrics.activate(); tracing.activate(); @@ -311,10 +326,12 @@ function registerTimeoutDetection(context, entrySpan) { : 2000; if (initialRemainingMillis <= minimumTimeoutInMs) { - logger.debug( - 'Heuristical timeout detection will be disabled for Lambda functions with a short timeout ' + - '(2 seconds and smaller).' - ); + instanaCtr + .logger() + .debug( + 'Heuristical timeout detection will be disabled for Lambda functions with a short timeout ' + + '(2 seconds and smaller).' + ); return; } @@ -329,9 +346,9 @@ function registerTimeoutDetection(context, entrySpan) { triggerTimeoutHandlingAfter = initialRemainingMillis - 400; } - logger.debug( - `Registering heuristical timeout detection to be triggered in ${triggerTimeoutHandlingAfter} milliseconds.` - ); + instanaCtr + .logger() + .debug(`Registering heuristical timeout detection to be triggered in ${triggerTimeoutHandlingAfter} milliseconds.`); setTimeout(() => { postHandlerForTimeout(entrySpan, getRemainingTimeInMillis(context)); @@ -342,7 +359,9 @@ function getRemainingTimeInMillis(context) { if (context && typeof context.getRemainingTimeInMillis === 'function') { return context.getRemainingTimeInMillis(); } else { - logger.warn('context.getRemainingTimeInMillis() is not available, timeout detection will be disabled.'); + instanaCtr + .logger() + .warn('context.getRemainingTimeInMillis() is not available, timeout detection will be disabled.'); return null; } } @@ -352,7 +371,7 @@ function getRemainingTimeInMillis(context) { // used or not e.g. by checking the lambda handler name if that is possible. function shouldUseLambdaExtension() { if (process.env.INSTANA_DISABLE_LAMBDA_EXTENSION) { - logger.info('INSTANA_DISABLE_LAMBDA_EXTENSION is set, not using the Lambda extension.'); + instanaCtr.logger().info('INSTANA_DISABLE_LAMBDA_EXTENSION is set, not using the Lambda extension.'); return false; } else { // Note: We could also use context.memoryLimitInMB here instead of the env var AWS_LAMBDA_FUNCTION_MEMORY_SIZE (both @@ -360,28 +379,33 @@ function shouldUseLambdaExtension() { // The context object is not available to the extension, so we prefer the env var over the value from the context. const memorySetting = process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE; if (!memorySetting) { - logger.debug( - 'The environment variable AWS_LAMBDA_FUNCTION_MEMORY_SIZE is not present, cannot determine memory settings.' - ); + instanaCtr + .logger() + .debug( + 'The environment variable AWS_LAMBDA_FUNCTION_MEMORY_SIZE is not present, cannot determine memory settings.' + ); return true; } const memorySize = parseInt(memorySetting, 10); if (isNaN(memorySize)) { - logger.debug( - `Could not parse the value of the environment variable AWS_LAMBDA_FUNCTION_MEMORY_SIZE: "${memorySetting}", ` + - 'cannot determine memory settings, not using the Lambda extension.' - ); + instanaCtr + .logger() + .debug( + 'Could not parse the value of the environment variable ' + + `AWS_LAMBDA_FUNCTION_MEMORY_SIZE: "${memorySetting}", ` + + 'cannot determine memory settings, not using the Lambda extension.' + ); return false; } if (memorySize < 256) { - let logFn = logger.debug; + let logFn = instanaCtr.logger().debug; // CASE: We try to determine if the customer has the extension installed. We need to put a warning // because the extension is **not** working and might block the lambda extension when // its not used correctly e.g. slow startup of extension or waiting for invokes or incoming spans // from the tracer. if (process.env._HANDLER?.includes('instana-aws-lambda-auto-wrap')) { - logFn = logger.warn; + logFn = instanaCtr.logger().warn; } logFn( @@ -428,7 +452,7 @@ function sendToBackend({ spans, metricsPayload, finalLambdaRequest, callback }) return ssm.waitAndGetInstanaKey((err, value) => { if (err) { - logger.debug(err); + instanaCtr.logger().debug(err); return callback(); } @@ -513,14 +537,14 @@ function postHandlerForTimeout(entrySpan, remainingMillis) { * `setTimeout` is not 100% reliable */ if (remainingMillis < 200) { - logger.debug('Skipping heuristical timeout detection because lambda timeout exceeded already.'); + instanaCtr.logger().debug('Skipping heuristical timeout detection because lambda timeout exceeded already.'); return; } if (entrySpan) { // CASE: Timeout not needed, we already send the data to the backend successfully if (entrySpan.transmitted) { - logger.debug('Skipping heuristical timeout detection because BE data was sent already.'); + instanaCtr.logger().debug('Skipping heuristical timeout detection because BE data was sent already.'); return; } @@ -531,7 +555,7 @@ function postHandlerForTimeout(entrySpan, remainingMillis) { entrySpan.transmit(); } - logger.debug(`Heuristical timeout detection was triggered with ${remainingMillis} milliseconds left.`); + instanaCtr.logger().debug(`Heuristical timeout detection was triggered with ${remainingMillis} milliseconds left.`); // deliberately not gathering metrics but only sending spans. const spans = spanBuffer.getAndResetSpans(); @@ -551,7 +575,7 @@ exports.currentSpan = function getHandleForCurrentSpan() { exports.sdk = tracing.sdk; exports.setLogger = function setLogger(_logger) { - log.init({ logger: _logger }); + instanaCtr.logger().setLogger(_logger); }; exports.opentracing = tracing.opentracing; diff --git a/packages/azure-container-services/src/activate.js b/packages/azure-container-services/src/activate.js index 31f3d724e8..54c1464d78 100644 --- a/packages/azure-container-services/src/activate.js +++ b/packages/azure-container-services/src/activate.js @@ -5,26 +5,33 @@ 'use strict'; const instanaCore = require('@instana/core'); -const { backendConnector, consoleLogger: log } = require('@instana/serverless'); +const { backendConnector, consoleLogger: serverlessLogger } = require('@instana/serverless'); const identityProvider = require('./identity_provider'); +const { tracing, coreConfig, coreUtils } = instanaCore; -const { tracing, util: coreUtil } = instanaCore; -const { normalizeConfig } = coreUtil; +const instanaCtr = new instanaCore.InstanaCtr(); -const logger = log.init(); -const config = normalizeConfig({}, logger); +coreUtils.init(instanaCtr); +coreConfig.init(instanaCtr); +serverlessLogger.init(instanaCtr); + +instanaCtr.set('utils', coreUtils.create()); +instanaCtr.set('config', coreConfig.create()); +instanaCtr.set('logger', serverlessLogger.create()); function init() { // For more details about environment variables in azure, please see // https://learn.microsoft.com/en-us/azure/app-service/reference-app-settings?tabs=kudu%2Cdotnet#app-environment if (!process.env.WEBSITE_OWNER_NAME && !process.env.WEBSITE_SITE_NAME && !process.env.WEBSITE_RESOURCE_GROUP) { - logger.error( - 'Initializing @instana/azure-container-services failed. The environment variables' + - `WEBSITE_OWNER_NAME: ${process.env.WEBSITE_OWNER_NAME} WEBSITE_SITE_NAME: ${process.env.WEBSITE_SITE_NAME} ` + - `WEBSITE_RESOURCE_GROUP: ${process.env.WEBSITE_RESOURCE_GROUP} are not set. ` + - 'This container instance will not be monitored.' - ); + instanaCtr + .logger() + .error( + 'Initializing @instana/azure-container-services failed. The environment variables' + + `WEBSITE_OWNER_NAME: ${process.env.WEBSITE_OWNER_NAME} WEBSITE_SITE_NAME: ${process.env.WEBSITE_SITE_NAME} ` + + `WEBSITE_RESOURCE_GROUP: ${process.env.WEBSITE_RESOURCE_GROUP} are not set. ` + + 'This container instance will not be monitored.' + ); return; } // In contrast to Fargate, the Azure Agent collects required metrics information from Azure APIs to oversee @@ -34,23 +41,25 @@ function init() { identityProvider.init(); backendConnector.init({ - config, + config: instanaCtr.config(), identityProvider, defaultTimeout: 950 }); - instanaCore.init(config, backendConnector, identityProvider); + instanaCore.init(instanaCtr.config(), instanaCtr.utils(), backendConnector, identityProvider); tracing.activate(); - logger.debug('@instana/azure-container-services initialized.'); + instanaCtr.logger().debug('@instana/azure-container-services initialized.'); // eslint-disable-next-line no-unused-expressions process.send && process.send('instana.azure-app-service.initialized'); } catch (e) { - logger.error( - 'Initializing @instana/azure-container-services failed. This azure container service will not be monitored.' + - `${e?.message} ${e?.stack}` - ); + instanaCtr + .logger() + .error( + 'Initializing @instana/azure-container-services failed. This azure container service will not be monitored.' + + `${e?.message} ${e?.stack}` + ); } } @@ -64,7 +73,7 @@ exports.sdk = tracing.sdk; // NOTE: this is the external interface for the customer. They can set a custom logger. exports.setLogger = function setLogger(_logger) { - log.init({ logger: _logger }); + instanaCtr.logger().setLogger(_logger); }; exports.opentracing = tracing.opentracing; diff --git a/packages/azure-container-services/test/Control.js b/packages/azure-container-services/test/Control.js index f62c82d7b7..e113d959b1 100644 --- a/packages/azure-container-services/test/Control.js +++ b/packages/azure-container-services/test/Control.js @@ -10,7 +10,7 @@ const fetch = require('node-fetch-v2'); const portfinder = require('@instana/collector/test/test_util/portfinder'); const config = require('@instana/core/test/config'); const AbstractServerlessControl = require('../../serverless/test/util/AbstractServerlessControl'); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; const PATH_TO_INSTANA_AZURE_PACKAGE = path.join(__dirname, '..'); let execArg; diff --git a/packages/collector/src/actions/source.js b/packages/collector/src/actions/source.js index fbab69d19e..47fd29b029 100644 --- a/packages/collector/src/actions/source.js +++ b/packages/collector/src/actions/source.js @@ -13,7 +13,7 @@ let logger; const validFileRequests = /\.(js|ts|jsx)$|(^|\/)package\.json$/i; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/collector/src/agent/opts.js b/packages/collector/src/agent/opts.js index 1017c5433f..90b20acbf7 100644 --- a/packages/collector/src/agent/opts.js +++ b/packages/collector/src/agent/opts.js @@ -16,7 +16,7 @@ exports.agentUuid = undefined; // @ts-ignore - Cannot redeclare exported variable exports.autoProfile = false; -/** @type {import('@instana/core/src/util/normalizeConfig').AgentConfig} config */ +/** @type {import('@instana/core/src/config/normalizeConfig').AgentConfig} config */ exports.config = {}; /** diff --git a/packages/collector/src/agent/requestHandler.js b/packages/collector/src/agent/requestHandler.js index 4ef16c5f61..c766a7e0d9 100644 --- a/packages/collector/src/agent/requestHandler.js +++ b/packages/collector/src/agent/requestHandler.js @@ -30,7 +30,7 @@ const actionMapping = { }; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/collector/src/agentConnection.js b/packages/collector/src/agentConnection.js index d8e67cb508..a1a51c5775 100644 --- a/packages/collector/src/agentConnection.js +++ b/packages/collector/src/agentConnection.js @@ -5,7 +5,7 @@ 'use strict'; -const { util, uninstrumentedHttp, uninstrumentedFs: fs } = require('@instana/core'); +const { uninstrumentedHttp, uninstrumentedFs: fs } = require('@instana/core'); const pathUtil = require('path'); const circularReferenceRemover = require('./util/removeCircular'); const agentOpts = require('./agent/opts'); @@ -34,12 +34,17 @@ let isConnected = false; /** @type {string | null} */ let cpuSetFileContent = null; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils * @param {any} _pidStore */ -exports.init = function init(config, _pidStore) { +exports.init = function init(config, utils, _pidStore) { logger = config.logger; + coreUtils = utils; pidStore = _pidStore; cmdline.init(config); @@ -90,7 +95,7 @@ exports.AgentEventSeverity = { * @param {(err: Error, rawResponse?: string) => void} callback */ exports.announceNodeCollector = function announceNodeCollector(callback) { - const cb = util.atMostOnce('callback for announceNodeCollector', callback); + const cb = coreUtils.atMostOnce('callback for announceNodeCollector', callback); /** @type {AgentConnectionPayload} */ const payload = { @@ -221,7 +226,7 @@ exports.checkWhetherAgentIsReadyToAcceptData = function checkWhetherAgentIsReady * @param {(...args: *) => *} cb */ function checkWhetherResponseForPathIsOkay(path, cb) { - cb = util.atMostOnce('callback for checkWhetherResponseForPathIsOkay', cb); + cb = coreUtils.atMostOnce('callback for checkWhetherResponseForPathIsOkay', cb); const req = http.request( { @@ -257,7 +262,7 @@ function checkWhetherResponseForPathIsOkay(path, cb) { * @param {(...args: *) => *} cb */ exports.sendMetrics = function sendMetrics(data, cb) { - cb = util.atMostOnce('callback for sendMetrics', cb); + cb = coreUtils.atMostOnce('callback for sendMetrics', cb); sendData(`/com.instana.plugin.nodejs.${pidStore.pid}`, data, (err, body) => { if (err) { @@ -283,7 +288,7 @@ exports.sendMetrics = function sendMetrics(data, cb) { * @param {(...args: *) => *} cb */ exports.sendSpans = function sendSpans(spans, cb) { - const callback = util.atMostOnce('callback for sendSpans', err => { + const callback = coreUtils.atMostOnce('callback for sendSpans', err => { if (err && !maxContentErrorHasBeenLogged && err instanceof PayloadTooLargeError) { logLargeSpans(spans); } else if (err) { @@ -304,7 +309,7 @@ exports.sendSpans = function sendSpans(spans, cb) { * @param {(...args: *) => *} cb */ exports.sendProfiles = function sendProfiles(profiles, cb) { - const callback = util.atMostOnce('callback for sendProfiles', err => { + const callback = coreUtils.atMostOnce('callback for sendProfiles', err => { if (err && err instanceof PayloadTooLargeError) { logger.warn('Profiles are too too large to be sent.'); } else if (err && err.statusCode === 404) { @@ -324,7 +329,7 @@ exports.sendProfiles = function sendProfiles(profiles, cb) { * @param {(...args: *) => *} cb */ exports.sendEvent = function sendEvent(eventData, cb) { - const callback = util.atMostOnce('callback for sendEvent', (err, responseBody) => { + const callback = coreUtils.atMostOnce('callback for sendEvent', (err, responseBody) => { cb(err, responseBody); }); @@ -346,7 +351,7 @@ exports.sendAgentMonitoringEvent = function sendAgentMonitoringEvent(code, categ category }; - const callback = util.atMostOnce('callback for sendAgentMonitoringEvent', (err, responseBody) => { + const callback = coreUtils.atMostOnce('callback for sendAgentMonitoringEvent', (err, responseBody) => { cb(err, responseBody); }); @@ -359,7 +364,7 @@ exports.sendAgentMonitoringEvent = function sendAgentMonitoringEvent(code, categ * @param {(...args: *) => *} cb */ exports.sendAgentResponseToAgent = function sendAgentResponseToAgent(messageId, response, cb) { - cb = util.atMostOnce('callback for sendAgentResponseToAgent', cb); + cb = coreUtils.atMostOnce('callback for sendAgentResponseToAgent', cb); sendData( `/com.instana.plugin.nodejs/response.${pidStore.pid}?messageId=${encodeURIComponent(messageId)}`, @@ -373,7 +378,7 @@ exports.sendAgentResponseToAgent = function sendAgentResponseToAgent(messageId, * @param {(...args: *) => *} cb */ exports.sendTracingMetricsToAgent = function sendTracingMetricsToAgent(tracingMetrics, cb) { - const callback = util.atMostOnce('callback for sendTracingMetricsToAgent', err => { + const callback = coreUtils.atMostOnce('callback for sendTracingMetricsToAgent', err => { cb(err); }); @@ -388,7 +393,7 @@ exports.sendTracingMetricsToAgent = function sendTracingMetricsToAgent(tracingMe * @returns */ function sendData(path, data, cb, ignore404 = false) { - cb = util.atMostOnce(`callback for sendData: ${path}`, cb); + cb = coreUtils.atMostOnce(`callback for sendData: ${path}`, cb); const payloadAsString = JSON.stringify(data, circularReferenceRemover()); if (typeof logger.trace === 'function') { @@ -499,7 +504,7 @@ function logLargeSpans(spans) { .slice(0, 4) .map( s => - `span name: ${s.span.n}, largest attribute: ${util + `span name: ${s.span.n}, largest attribute: ${coreUtils .propertySizes(s.span) .sort((p1, p2) => p2.length - p1.length) .slice(0, 1) diff --git a/packages/collector/src/announceCycle/agentHostLookup.js b/packages/collector/src/announceCycle/agentHostLookup.js index a19d6057ed..95f0412bc3 100644 --- a/packages/collector/src/announceCycle/agentHostLookup.js +++ b/packages/collector/src/announceCycle/agentHostLookup.js @@ -6,7 +6,7 @@ 'use strict'; const { callbackify } = require('util'); -const { atMostOnce } = require('@instana/core').util; +const { atMostOnce } = require('@instana/core').coreUtils; const { http } = require('@instana/core').uninstrumentedHttp; const agentOpts = require('../agent/opts'); @@ -17,7 +17,7 @@ const readDefaultGateway = callbackify(defaultGatewayParser.parseProcSelfNetRout let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ const init = config => { logger = config.logger; diff --git a/packages/collector/src/announceCycle/agentready.js b/packages/collector/src/announceCycle/agentready.js index d190acdd62..11b3e531a8 100644 --- a/packages/collector/src/announceCycle/agentready.js +++ b/packages/collector/src/announceCycle/agentready.js @@ -61,7 +61,7 @@ let pidStore; let disableEOLEvents; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config * @param {any} _pidStore */ function init(config, _pidStore) { diff --git a/packages/collector/src/announceCycle/announced.js b/packages/collector/src/announceCycle/announced.js index bd787b6681..1d1dfe4b6d 100644 --- a/packages/collector/src/announceCycle/announced.js +++ b/packages/collector/src/announceCycle/announced.js @@ -12,7 +12,7 @@ let logger; const MAX_RETRIES = 60; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ function init(config) { logger = config.logger; @@ -29,7 +29,7 @@ function checkWhetherAgentIsReadyToAccept(totalNumberOfAttempts, ctx) { ctx.transitionTo('agentready'); } else if (totalNumberOfAttempts > MAX_RETRIES) { logger.warn( - `The Instana host agent is not yet ready to accept data after ${totalNumberOfAttempts} attempts. + `The Instana host agent is not yet ready to accept data after ${totalNumberOfAttempts} attempts. Restarting the cycle to establish a connection.` ); ctx.transitionTo('unannounced'); diff --git a/packages/collector/src/announceCycle/defaultGatewayParser.js b/packages/collector/src/announceCycle/defaultGatewayParser.js index dbb51bbce1..0b5adc4611 100644 --- a/packages/collector/src/announceCycle/defaultGatewayParser.js +++ b/packages/collector/src/announceCycle/defaultGatewayParser.js @@ -13,7 +13,7 @@ let logger; let cachedResult; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/collector/src/announceCycle/index.js b/packages/collector/src/announceCycle/index.js index 2d1e53905b..88d7668f38 100644 --- a/packages/collector/src/announceCycle/index.js +++ b/packages/collector/src/announceCycle/index.js @@ -52,16 +52,17 @@ const ctx = { }; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils * @param {any} pidStore */ -exports.init = function init(config, pidStore) { +exports.init = function init(config, utils, pidStore) { logger = config.logger; agentHostLookup.init(config); announced.init(config); agentready.init(config, pidStore); - unannounced.init(config, pidStore); + unannounced.init(config, utils, pidStore); }; exports.start = function start() { diff --git a/packages/collector/src/announceCycle/unannounced.js b/packages/collector/src/announceCycle/unannounced.js index a9acbfbb42..c6528868c8 100644 --- a/packages/collector/src/announceCycle/unannounced.js +++ b/packages/collector/src/announceCycle/unannounced.js @@ -8,7 +8,7 @@ const { secrets, tracing, - util: { ensureNestedObjectExists, configNormalizers } + coreConfig: { configNormalizers } } = require('@instana/core'); const { constants: tracingConstants } = tracing; @@ -20,6 +20,9 @@ let logger; /** @type {{ pid: number }} */ let pidStore; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + const initialRetryDelay = 10 * 1000; // 10 seconds const backoffFactor = 1.5; const maxRetryDelay = 60 * 1000; // one minute @@ -35,7 +38,7 @@ const maxRetryDelay = 60 * 1000; // one minute /** * @typedef {Object} SecretsConfig * @property {Array.} list - * @property {import('@instana/core/src/util/normalizeConfig').MatchingOption} matcher + * @property {import('@instana/core/src/config/normalizeConfig').MatchingOption} matcher */ /** @@ -53,10 +56,12 @@ const maxRetryDelay = 60 * 1000; // one minute */ /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils * @param {any} _pidStore */ -function init(config, _pidStore) { +function init(config, utils, _pidStore) { + coreUtils = utils; logger = config.logger; pidStore = _pidStore; } @@ -130,17 +135,17 @@ function applySecretsConfiguration(agentResponse) { if (agentResponse.secrets) { if (!(typeof agentResponse.secrets.matcher === 'string')) { logger.warn( - `Received an invalid secrets configuration from the Instana host agent, attribute matcher is not a string: + `Received an invalid secrets configuration from the Instana host agent, attribute matcher is not a string: ${agentResponse.secrets.matcher}` ); } else if (Object.keys(secrets.matchers).indexOf(agentResponse.secrets.matcher) < 0) { logger.warn( - `Received an invalid secrets configuration from the Intana agent, matcher is not supported: + `Received an invalid secrets configuration from the Intana agent, matcher is not supported: ${agentResponse.secrets.matcher}` ); } else if (!Array.isArray(agentResponse.secrets.list)) { logger.warn( - `Received an invalid secrets configuration from the Instana host agent, attribute list is not an array: + `Received an invalid secrets configuration from the Instana host agent, attribute list is not an array: ${agentResponse.secrets.list}` ); } else { @@ -168,7 +173,7 @@ function applyExtraHttpHeaderConfiguration(agentResponse) { */ function actuallyApplyExtraHttpHeaderConfiguration(extraHeaders) { if (Array.isArray(extraHeaders)) { - ensureNestedObjectExists(agentOpts.config, ['tracing', 'http']); + coreUtils.ensureNestedObjectExists(agentOpts.config, ['tracing', 'http']); // The Node.js HTTP API converts all incoming HTTP headers into lowercase. agentOpts.config.tracing.http.extraHttpHeadersToCapture = extraHeaders.map((/** @type {string} */ s) => s.toLowerCase() @@ -188,7 +193,7 @@ function applyKafkaTracingConfiguration(agentResponse) { ? kafkaTracingConfigFromAgent['trace-correlation'] : tracingConstants.kafkaTraceCorrelationDefault }; - ensureNestedObjectExists(agentOpts.config, ['tracing', 'kafka']); + coreUtils.ensureNestedObjectExists(agentOpts.config, ['tracing', 'kafka']); agentOpts.config.tracing.kafka = kafkaTracingConfig; } // There is no fallback because there is are no legacy agent response attributes for the Kafka tracing config, those @@ -201,7 +206,7 @@ function applyKafkaTracingConfiguration(agentResponse) { function applySpanBatchingConfiguration(agentResponse) { if (agentResponse.tracing) { if (agentResponse.tracing['span-batching-enabled'] === true) { - ensureNestedObjectExists(agentOpts.config, ['tracing']); + coreUtils.ensureNestedObjectExists(agentOpts.config, ['tracing']); agentOpts.config.tracing.spanBatchingEnabled = true; } return; @@ -211,7 +216,7 @@ function applySpanBatchingConfiguration(agentResponse) { // common tracing options section. We can remove this legacy fallback approximately in May 2023. if (agentResponse.spanBatchingEnabled === true || agentResponse.spanBatchingEnabled === 'true') { logger.info('Enabling span batching via Instana host agent configuration.'); - ensureNestedObjectExists(agentOpts.config, ['tracing']); + coreUtils.ensureNestedObjectExists(agentOpts.config, ['tracing']); agentOpts.config.tracing.spanBatchingEnabled = true; } } @@ -235,7 +240,7 @@ function applyIgnoreEndpointsConfiguration(agentResponse) { const ignoreEndpointsConfig = agentResponse?.tracing?.['ignore-endpoints']; if (!ignoreEndpointsConfig) return; - ensureNestedObjectExists(agentOpts.config, ['tracing', 'ignoreEndpoints']); + coreUtils.ensureNestedObjectExists(agentOpts.config, ['tracing', 'ignoreEndpoints']); agentOpts.config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(ignoreEndpointsConfig); } @@ -251,11 +256,12 @@ function applyDisableConfiguration(agentResponse) { const disablingConfig = agentResponse?.tracing?.disable; if (!disablingConfig) return; - ensureNestedObjectExists(agentOpts.config, ['tracing', 'disable']); + coreUtils.ensureNestedObjectExists(agentOpts.config, ['tracing', 'disable']); agentOpts.config.tracing.disable = configNormalizers.disable.normalizeExternalConfig({ tracing: { disable: disablingConfig } }); } + module.exports = { init, diff --git a/packages/collector/src/cmdline.js b/packages/collector/src/cmdline.js index 28131e18bf..7b9c6ef40f 100644 --- a/packages/collector/src/cmdline.js +++ b/packages/collector/src/cmdline.js @@ -11,7 +11,7 @@ const { uninstrumentedFs: fs } = require('@instana/core'); let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/collector/src/immediate.js b/packages/collector/src/immediate.js index 0ac46511a7..98ee993352 100644 --- a/packages/collector/src/immediate.js +++ b/packages/collector/src/immediate.js @@ -17,7 +17,7 @@ if (isNodeJsTooOld()) { return; } -const { util: coreUtil } = require('@instana/core'); +const excludedFromInstrumentation = require('@instana/core/src/util/excludedFromInstrumentation'); const agentOpts = require('./agent/opts'); // This file can be used with NODE_OPTIONS or `node --require` to instrument a Node.js app with Instana without @@ -25,7 +25,7 @@ const agentOpts = require('./agent/opts'); // eslint-disable-next-line max-len // https://www.ibm.com/docs/en/instana-observability/current?topic=nodejs-collector-installation#activating-the-collector -const isExcludedFromInstrumentation = coreUtil.excludedFromInstrumentation && coreUtil.excludedFromInstrumentation(); +const isExcludedFromInstrumentation = excludedFromInstrumentation && excludedFromInstrumentation(); // In case this is a child process of an instrumented parent process we might receive the agent uuid from the parent // process to be able to produce and collect spans immediately without waiting for a connection to the agent in this diff --git a/packages/collector/src/index.js b/packages/collector/src/index.js index 8ded6deb64..4d51237717 100644 --- a/packages/collector/src/index.js +++ b/packages/collector/src/index.js @@ -46,14 +46,21 @@ const instanaNodeJsCore = require('@instana/core'); const instanaSharedMetrics = require('@instana/shared-metrics'); require('./tracing'); // load additional instrumentations -const log = require('./logger'); +const collectorLogger = require('./logger'); const normalizeCollectorConfig = require('./util/normalizeConfig'); const experimental = require('./experimental'); +const { coreConfig, coreUtils } = instanaNodeJsCore; + +const instanaCtr = new instanaNodeJsCore.InstanaCtr(); + +coreUtils.init(instanaCtr); +coreConfig.init(instanaCtr); +collectorLogger.init(instanaCtr); + +instanaCtr.set('utils', coreUtils.create()); +instanaCtr.set('config', coreConfig.create()); +instanaCtr.set('logger', collectorLogger.create()); -// NOTE: Default collector logger && config for cases like `preinit`. -const logger = log.init(); -/** @type {import('./types/collector').CollectorConfig} */ -let config = instanaNodeJsCore.util.normalizeConfig({}, logger); /** @type {import('./agentConnection')} */ let agentConnection; @@ -96,13 +103,13 @@ function init(_config = {}) { // @ts-ignore: Property '__INSTANA_INITIALIZED' does not exist on type global global.__INSTANA_INITIALIZED = true; - // CASE: reinit logger if custom logger or log level is provided. + // CASE: recreate logger if custom logger or log level is provided. if (_config.logger || _config.level) { - log.init(_config); + instanaCtr.set('logger', collectorLogger.create(_config)); } - config = normalizeCollectorConfig(_config); - config = instanaNodeJsCore.util.normalizeConfig(config, logger); + const collectorConfigNormalized = normalizeCollectorConfig(_config); + instanaCtr.set('config', coreConfig.create(collectorConfigNormalized)); agentConnection = require('./agentConnection'); const agentOpts = require('./agent/opts'); @@ -111,18 +118,21 @@ function init(_config = {}) { const announceCycle = require('./announceCycle'); const metrics = require('./metrics'); - pidStore.init(config); - agentOpts.init(config); - announceCycle.init(config, pidStore); - agentConnection.init(config, pidStore); - instanaNodeJsCore.init(config, agentConnection, pidStore); + pidStore.init(instanaCtr.config()); + agentOpts.init(instanaCtr.config()); + announceCycle.init(instanaCtr.config(), instanaCtr.utils(), pidStore); + agentConnection.init(instanaCtr.config(), instanaCtr.utils(), pidStore); + instanaNodeJsCore.init(instanaCtr.config(), instanaCtr.utils(), agentConnection, pidStore); if (isMainThread) { - uncaught.init(config, agentConnection, pidStore); - metrics.init(config, pidStore); + uncaught.init(instanaCtr.config(), agentConnection, pidStore); + metrics.init(instanaCtr.config(), instanaCtr.utils(), pidStore); } - logger.info(`@instana/collector module version: ${require(path.join(__dirname, '..', 'package.json')).version}`); + instanaCtr + .logger() + .info(`@instana/collector module version: ${require(path.join(__dirname, '..', 'package.json')).version}`); + announceCycle.start(); return init; @@ -157,7 +167,7 @@ init.isConnected = function isConnected() { */ init.setLogger = function setLogger(_logger) { // NOTE: Override our default logger with customer's logger - log.init({ logger: _logger }); + instanaCtr.logger().setLogger(_logger); }; init.core = instanaNodeJsCore; @@ -172,7 +182,7 @@ if (process.env.INSTANA_IMMEDIATE_INIT != null && process.env.INSTANA_IMMEDIATE_ process.env.INSTANA_EARLY_INSTRUMENTATION != null && process.env.INSTANA_EARLY_INSTRUMENTATION.toLowerCase() === 'true' ) { - instanaNodeJsCore.preInit(config); + instanaNodeJsCore.preInit(instanaCtr.config(), instanaCtr.utils()); } module.exports = init; diff --git a/packages/collector/src/logger.js b/packages/collector/src/logger.js index 74fc739d0f..c9c46b5a5e 100644 --- a/packages/collector/src/logger.js +++ b/packages/collector/src/logger.js @@ -16,6 +16,7 @@ try { // thread (0). } +const os = require('os'); const uninstrumentedLogger = require('./uninstrumentedLogger'); const loggerToAgentStream = require('./agent/loggerToAgentStream'); @@ -49,13 +50,19 @@ class InstanaLogger { } /** - * @param {import('./types/collector').CollectorConfig} config + * @param {import('@instana/core/src/instanaCtr').InstanaCtrType} [_instanaCtr] */ -exports.init = function init(config = {}) { +// eslint-disable-next-line no-unused-vars +exports.init = _instanaCtr => {}; + +/** + * @param {import('./types/collector').CollectorConfig} customConfig + */ +exports.create = (customConfig = {}) => { /** @type {import('@instana/core/src/core').GenericLogger} */ let parentLogger; - if (config.logger && typeof config.logger.child === 'function') { + if (customConfig.logger && typeof customConfig.logger.child === 'function') { // A bunyan or pino logger has been provided via config. In either case we create a child logger directly under the // given logger which serves as the parent for all loggers we create later on. @@ -65,7 +72,7 @@ exports.init = function init(config = {}) { // It takes the parent logger level. // We cannot fix this in our side. // https://github.com/winstonjs/winston/issues/1854#issuecomment-710195110 - parentLogger = config.logger.child({ + parentLogger = customConfig.logger.child({ // TODO: Rename to "instana-nodejs-logger" in next major version. module: 'instana-nodejs-logger-parent', threadId @@ -74,15 +81,16 @@ exports.init = function init(config = {}) { // CASE: Attach custom instana meta attribute to filter out internal instana logs. // This will prevent these logs from being traced. parentLogger.__instana = true; - } else if (config.logger && hasLoggingFunctions(config.logger)) { + } else if (customConfig.logger && hasLoggingFunctions(customConfig.logger)) { // CASE: Built-in console logger or log4js. We use it as is. // The __instana attribute identifies the Instana logger, distinguishing it from the client application logger, // and also prevents these logs from being traced // Extends config.logger with __instana while preserving its prototype and methods. - parentLogger = Object.setPrototypeOf({ ...config.logger, __instana: 1 }, Object.getPrototypeOf(config.logger)); + parentLogger = Object.setPrototypeOf( + { ...customConfig.logger, __instana: 1 }, + Object.getPrototypeOf(customConfig.logger) + ); } else { - const os = require('os'); - // No custom logger has been provided via config, we create a new pino logger as our internal // Instana logger. @@ -138,8 +146,8 @@ exports.init = function init(config = {}) { if (process.env['INSTANA_DEBUG']) { setLoggerLevel(parentLogger, 'debug'); - } else if (config.level) { - setLoggerLevel(parentLogger, config.level); + } else if (customConfig.level) { + setLoggerLevel(parentLogger, customConfig.level); } else if (process.env['INSTANA_LOG_LEVEL']) { setLoggerLevel(parentLogger, process.env['INSTANA_LOG_LEVEL'].toLowerCase()); } diff --git a/packages/collector/src/metrics/index.js b/packages/collector/src/metrics/index.js index 9bb2282073..44f73168f2 100644 --- a/packages/collector/src/metrics/index.js +++ b/packages/collector/src/metrics/index.js @@ -14,12 +14,13 @@ const additionalMetrics = [pid]; /** * @param {import('@instana/core/src/metrics').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils * @param {any} pidStore */ -exports.init = function init(config, pidStore) { +exports.init = function init(config, utils, pidStore) { coreMetrics.init(config); sharedMetrics.init(config); - transmissionCycle.init(config); + transmissionCycle.init(config, utils); additionalMetrics.forEach(metric => { metric.init(config, pidStore); diff --git a/packages/collector/src/metrics/initializedTooLate.js b/packages/collector/src/metrics/initializedTooLate.js index a6ff2df91d..bf3e79a928 100644 --- a/packages/collector/src/metrics/initializedTooLate.js +++ b/packages/collector/src/metrics/initializedTooLate.js @@ -5,7 +5,7 @@ 'use strict'; -const hasThePackageBeenInitializedTooLate = require('@instana/core').util.hasThePackageBeenInitializedTooLate; +const hasThePackageBeenInitializedTooLate = require('@instana/core').coreUtils.hasThePackageBeenInitializedTooLate; exports.payloadPrefix = 'initTooLate'; exports.currentPayload = undefined; diff --git a/packages/collector/src/metrics/pid.js b/packages/collector/src/metrics/pid.js index 5460db4a6d..6b47639b34 100644 --- a/packages/collector/src/metrics/pid.js +++ b/packages/collector/src/metrics/pid.js @@ -8,7 +8,7 @@ let pid; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config * @param {{ pid: number, onPidChange: (callback: (pid: number) => void) => void }} pidStore */ exports.init = function init(config, pidStore) { diff --git a/packages/collector/src/metrics/transmissionCycle.js b/packages/collector/src/metrics/transmissionCycle.js index db757808fb..cbdb449848 100644 --- a/packages/collector/src/metrics/transmissionCycle.js +++ b/packages/collector/src/metrics/transmissionCycle.js @@ -5,8 +5,6 @@ 'use strict'; -const core = require('@instana/core'); - /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; @@ -31,13 +29,17 @@ let previousTransmittedValue; let transmissionTimeoutHandle; let transmissionDelay = 1000; let isActive = false; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; /** * @param {import('@instana/core/src/metrics').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -exports.init = function init(config) { +exports.init = function init(config, utils) { logger = config.logger; transmissionDelay = config.metrics.transmissionDelay; + coreUtils = utils; }; /** @@ -90,7 +92,7 @@ function sendMetrics() { } // clone retrieved objects to allow mutations in metric retrievers - const newValueToTransmit = core.util.clone(metrics.gatherData()); + const newValueToTransmit = coreUtils.clone(metrics.gatherData()); /** @type {Object} */ let payload; @@ -98,7 +100,7 @@ function sendMetrics() { if (isFullTransmission) { payload = newValueToTransmit; } else { - payload = core.util.compression(previousTransmittedValue, newValueToTransmit); + payload = coreUtils.compression(previousTransmittedValue, newValueToTransmit); } downstreamConnection.sendMetrics(payload, onMetricsHaveBeenSent.bind(null, isFullTransmission, newValueToTransmit)); diff --git a/packages/collector/src/pidStore/index.js b/packages/collector/src/pidStore/index.js index 86c40fa48e..aad9acaaf8 100644 --- a/packages/collector/src/pidStore/index.js +++ b/packages/collector/src/pidStore/index.js @@ -20,7 +20,7 @@ const eventName = 'pidChanged'; let eventEmitter; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/collector/src/tracing/instrumentation/process/edgemicro.js b/packages/collector/src/tracing/instrumentation/process/edgemicro.js index 7d34419742..4d9a74492b 100644 --- a/packages/collector/src/tracing/instrumentation/process/edgemicro.js +++ b/packages/collector/src/tracing/instrumentation/process/edgemicro.js @@ -7,14 +7,14 @@ const cluster = require('cluster'); -const hook = require('@instana/core').util.hook; +const hook = require('@instana/core').coreUtils.hook; const selfPath = require('./selfPath'); /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function (config) { logger = config.logger; diff --git a/packages/collector/src/util/initializedTooLate.js b/packages/collector/src/util/initializedTooLate.js index dc0404491d..049e366cba 100644 --- a/packages/collector/src/util/initializedTooLate.js +++ b/packages/collector/src/util/initializedTooLate.js @@ -12,13 +12,13 @@ const FIRE_MONITORING_EVENT_DURATION_IN_MS = process.env.INSTANA_FIRE_MONITORING ? Number(process.env.INSTANA_FIRE_MONITORING_EVENT_DURATION_IN_MS) : 600000; -const hasThePackageBeenInitializedTooLate = require('@instana/core').util.hasThePackageBeenInitializedTooLate; +const hasThePackageBeenInitializedTooLate = require('@instana/core').coreUtils.hasThePackageBeenInitializedTooLate; const agentConnection = require('../agentConnection'); let warningHasBeenLogged = false; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/collector/test/agentConnection_test.js b/packages/collector/test/agentConnection_test.js index 0158ac1da2..faa703f9c2 100644 --- a/packages/collector/test/agentConnection_test.js +++ b/packages/collector/test/agentConnection_test.js @@ -9,6 +9,7 @@ const expect = require('chai').expect; const constants = require('@instana/core').tracing.constants; const supportedVersion = require('@instana/core').tracing.supportedVersion; +const coreUtils = require('@instana/core/src/util').coreUtils; const testConfig = require('../../core/test/config'); const testUtils = require('../../core/test/test_util'); @@ -80,7 +81,7 @@ mochaSuiteFn('agent connection', function () { agentOpts.port = agentControls.getPort(); agentConnection = require('../src/agentConnection'); pidStore.init(config); - agentConnection.init(config, pidStore); + agentConnection.init(config, coreUtils, pidStore); await agentControls.simulateDiscovery(process.pid); await agentControls.clearReceivedData(); diff --git a/packages/collector/test/bazel_inode_test.js b/packages/collector/test/bazel_inode_test.js index 3f5f5aad29..05ee87f634 100644 --- a/packages/collector/test/bazel_inode_test.js +++ b/packages/collector/test/bazel_inode_test.js @@ -34,7 +34,7 @@ describe('agent connection/bazel', function () { '@instana/core': mockInstanaCoreHttp() }); - agentConnection.init({ logger: testUtils.createFakeLogger() }, { pid: 1234 }); + agentConnection.init({ logger: testUtils.createFakeLogger() }, {}, { pid: 1234 }); }); it('should remove the leading path segmentes which node-patches prepends', done => { @@ -59,7 +59,7 @@ describe('agent connection/bazel', function () { '@instana/core': mockInstanaCoreHttp() }); - agentConnection.init({ logger: testUtils.createFakeLogger() }, { pid: 1234 }); + agentConnection.init({ logger: testUtils.createFakeLogger() }, {}, { pid: 1234 }); }); it('should not modify the readlinkSync result', done => { diff --git a/packages/collector/test/test_util/ProcessControls.js b/packages/collector/test/test_util/ProcessControls.js index 7e3cb54cae..f61741c83d 100644 --- a/packages/collector/test/test_util/ProcessControls.js +++ b/packages/collector/test/test_util/ProcessControls.js @@ -20,7 +20,7 @@ const globalAgent = require('../globalAgent'); const portFinder = require('./portfinder'); const sslDir = path.join(__dirname, '..', 'apps', 'ssl'); const cert = fs.readFileSync(path.join(sslDir, 'cert')); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; class ProcessControls { /** diff --git a/packages/collector/test/tracing/native_esm/customInstrumentation/squareCalc.js b/packages/collector/test/tracing/native_esm/customInstrumentation/squareCalc.js index d689a3b264..4b1ac5da2b 100644 --- a/packages/collector/test/tracing/native_esm/customInstrumentation/squareCalc.js +++ b/packages/collector/test/tracing/native_esm/customInstrumentation/squareCalc.js @@ -7,7 +7,7 @@ const { EXIT } = require('@instana/core').tracing.constants; const tracingUtil = require('../../../../../core/src/tracing/tracingUtil'); const cls = require('../../../../../core/src/tracing/cls'); -const hook = require('@instana/core').util.hook; +const hook = require('@instana/core').coreUtils.hook; // eslint-disable-next-line no-unused-vars let isActive = false; diff --git a/packages/collector/test/tracing/sdk/multiple_installations/esm/test.js b/packages/collector/test/tracing/sdk/multiple_installations/esm/test.js index 9944c824ed..897a655ae4 100644 --- a/packages/collector/test/tracing/sdk/multiple_installations/esm/test.js +++ b/packages/collector/test/tracing/sdk/multiple_installations/esm/test.js @@ -15,7 +15,7 @@ const config = require('@instana/core/test/config'); const testUtils = require('@instana/core/test/test_util'); const ProcessControls = require('../../../../test_util/ProcessControls'); const globalAgent = require('../../../../globalAgent'); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; const mochaSuiteFn = supportedVersion(process.versions.node) ? describe : describe.skip; mochaSuiteFn('[ESM] tracing/sdk/multiple_installations', function () { diff --git a/packages/core/src/util/configNormalizers/disable.js b/packages/core/src/config/configNormalizers/disable.js similarity index 76% rename from packages/core/src/util/configNormalizers/disable.js rename to packages/core/src/config/configNormalizers/disable.js index c15369b920..32a616ad0c 100644 --- a/packages/core/src/util/configNormalizers/disable.js +++ b/packages/core/src/config/configNormalizers/disable.js @@ -5,14 +5,15 @@ 'use strict'; const { DISABLABLE_INSTRUMENTATION_GROUPS } = require('../../tracing/constants'); -/** @type {import('../../core').GenericLogger} */ -let logger; + +/** @type {import('../../instanaCtr').InstanaCtrType} */ +let instanaCtr; /** - * @param {import('../../util/normalizeConfig').InstanaConfig} _config + * @param {import('../../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function init(_config) { - logger = _config.logger; +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; }; /** @@ -23,29 +24,35 @@ exports.init = function init(_config) { * 2. `tracing.disabledTracers` (deprecated) * 3. Environment variables (`INSTANA_TRACING_DISABLE*`) * - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config */ exports.normalize = function normalize(config) { if (!config?.tracing) config.tracing = {}; try { // Disable all tracing if explicitly set 'disable' to true if (config.tracing.disable === true) { - logger?.info('Tracing has been disabled via "tracing.disable: true" configuration.'); + instanaCtr.logger().info('Tracing has been disabled via "tracing.disable: true" configuration.'); return true; } const hasDisableConfig = isDisableConfigNonEmpty(config); if (hasDisableConfig) { - logger?.info( - `Tracing selectively disabled as per "tracing.disable" configuration: ${JSON.stringify(config.tracing.disable)}` - ); + instanaCtr + .logger() + .info( + `Tracing selectively disabled as per "tracing.disable" configuration: ${JSON.stringify( + config.tracing.disable + )}` + ); } // Handle deprecated `disabledTracers` config if (config.tracing.disabledTracers) { - logger?.warn( - 'The configuration property "tracing.disabledTracers" is deprecated and will be removed in the next ' + - 'major release. Please use "tracing.disable" instead.' - ); + instanaCtr + .logger() + .warn( + 'The configuration property "tracing.disabledTracers" is deprecated and will be removed in the next ' + + 'major release. Please use "tracing.disable" instead.' + ); if (!hasDisableConfig) { config.tracing.disable = { instrumentations: config.tracing.disabledTracers }; } @@ -75,14 +82,14 @@ exports.normalize = function normalize(config) { return disableConfig || {}; } catch (error) { // Fallback to an empty disable config on error - logger?.debug(`Error while normalizing tracing.disable config: ${error?.message} ${error?.stack}`); + instanaCtr.logger().debug(`Error while normalizing tracing.disable config: ${error?.message} ${error?.stack}`); return {}; } }; /** * Handles config from agent. - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config */ exports.normalizeExternalConfig = function normalizeExternalConfig(config) { try { @@ -91,7 +98,9 @@ exports.normalizeExternalConfig = function normalizeExternalConfig(config) { return categorizeDisableEntries(flattenedEntries); } } catch (error) { - logger?.debug(`Error while normalizing external tracing.disable config: ${error?.message} ${error?.stack}`); + instanaCtr + .logger() + .debug(`Error while normalizing external tracing.disable config: ${error?.message} ${error?.stack}`); } return {}; @@ -111,10 +120,12 @@ function getDisableFromEnv() { // @deprecated if (process.env.INSTANA_DISABLED_TRACERS) { - logger?.warn( - 'The environment variable "INSTANA_DISABLED_TRACERS" is deprecated and will be removed in the next ' + - 'major release. Use "INSTANA_TRACING_DISABLE" instead.' - ); + instanaCtr + .logger() + .warn( + 'The environment variable "INSTANA_DISABLED_TRACERS" is deprecated and will be removed in the next ' + + 'major release. Use "INSTANA_TRACING_DISABLE" instead.' + ); disable.instrumentations = parseEnvVar(process.env.INSTANA_DISABLED_TRACERS); } @@ -123,7 +134,7 @@ function getDisableFromEnv() { const envVarValue = process.env.INSTANA_TRACING_DISABLE; if (envVarValue === 'true') { - logger?.info('Tracing has been disabled via environment variable "INSTANA_TRACING_DISABLE=true".'); + instanaCtr.logger().info('Tracing has been disabled via environment variable "INSTANA_TRACING_DISABLE=true".'); return true; } @@ -136,24 +147,30 @@ function getDisableFromEnv() { disable.groups = categorized.groups; } - logger?.info(`Tracing has been disabled via "INSTANA_TRACING_DISABLE=${envVarValue}"`); + instanaCtr.logger().info(`Tracing has been disabled via "INSTANA_TRACING_DISABLE=${envVarValue}"`); } } if (process.env.INSTANA_TRACING_DISABLE_INSTRUMENTATIONS) { disable.instrumentations = parseEnvVar(process.env.INSTANA_TRACING_DISABLE_INSTRUMENTATIONS); - logger?.info( - `Tracing instrumentations disabled via "INSTANA_TRACING_DISABLE_INSTRUMENTATIONS": ${JSON.stringify( - disable.instrumentations - )}` - ); + instanaCtr + .logger() + .info( + `Tracing instrumentations disabled via "INSTANA_TRACING_DISABLE_INSTRUMENTATIONS": ${JSON.stringify( + disable.instrumentations + )}` + ); } if (process.env.INSTANA_TRACING_DISABLE_GROUPS) { disable.groups = parseEnvVar(process.env.INSTANA_TRACING_DISABLE_GROUPS); - logger?.info( - `Tracing instrumentation groups disabled via "INSTANA_TRACING_DISABLE_GROUPS": ${JSON.stringify(disable.groups)}` - ); + instanaCtr + .logger() + .info( + `Tracing instrumentation groups disabled via "INSTANA_TRACING_DISABLE_GROUPS": ${JSON.stringify( + disable.groups + )}` + ); } return Object.keys(disable).length > 0 ? disable : null; @@ -244,7 +261,7 @@ function isNonEmptyObject(obj) { } /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config */ function isDisableConfigNonEmpty(config) { const disableConfig = config.tracing?.disable; diff --git a/packages/core/src/util/configNormalizers/ignoreEndpoints.js b/packages/core/src/config/configNormalizers/ignoreEndpoints.js similarity index 87% rename from packages/core/src/util/configNormalizers/ignoreEndpoints.js rename to packages/core/src/config/configNormalizers/ignoreEndpoints.js index 65c41dd1b0..a99322d889 100644 --- a/packages/core/src/util/configNormalizers/ignoreEndpoints.js +++ b/packages/core/src/config/configNormalizers/ignoreEndpoints.js @@ -5,14 +5,15 @@ 'use strict'; const path = require('path'); -const { read } = require('../yamlReader'); -/** @type {import('../../core').GenericLogger} */ -let logger; + +/** @type {import('../../instanaCtr').InstanaCtrType} */ +let instanaCtr; + /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function init(config) { - logger = config.logger; +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; }; /** @@ -77,7 +78,7 @@ exports.normalizeConfig = function normalizeConfig(ignoreEndpointConfig) { }) ); } catch (error) { - logger?.warn('Error when parsing ignore-endpoints configuration', error?.message); + instanaCtr.logger().warn('Error when parsing ignore-endpoints configuration', error?.message); return {}; } }; @@ -100,7 +101,7 @@ exports.fromEnv = function fromEnv(ignoreEndpointsEnv) { const [serviceName, endpointList] = (serviceEntry || '').split(':').map(part => part.trim()); if (!serviceName || !endpointList) { - logger?.warn( + instanaCtr.logger().warn( // eslint-disable-next-line max-len `Invalid configuration: entry in INSTANA_IGNORE_ENDPOINTS ${ignoreEndpointsEnv}: "${serviceEntry}". Expected format is e.g. "service:endpoint1,endpoint2".` ); @@ -113,7 +114,9 @@ exports.fromEnv = function fromEnv(ignoreEndpointsEnv) { return exports.normalizeConfig(Object.assign({}, ...parsedConfig)); } catch (error) { - logger?.warn(`Failed to parse INSTANA_IGNORE_ENDPOINTS: ${ignoreEndpointsEnv}. Error: ${error?.message}`); + instanaCtr + .logger() + .warn(`Failed to parse INSTANA_IGNORE_ENDPOINTS: ${ignoreEndpointsEnv}. Error: ${error?.message}`); return {}; } }; @@ -129,16 +132,17 @@ exports.fromEnv = function fromEnv(ignoreEndpointsEnv) { */ exports.fromYaml = function fromYaml(yamlFilePath) { if (!path.isAbsolute(yamlFilePath)) { - logger?.warn( + instanaCtr.logger().warn( // eslint-disable-next-line max-len `Invalid configuration: INSTANA_IGNORE_ENDPOINTS_PATH file path ${yamlFilePath} is not absolute.` ); return {}; } /** @type {Record} */ - const endpointsConfig = read(yamlFilePath); + const endpointsConfig = instanaCtr.utils().yamlReader.read(yamlFilePath); + if (!endpointsConfig || typeof endpointsConfig !== 'object') { - logger?.debug( + instanaCtr.logger().debug( // eslint-disable-next-line max-len `Invalid configuration: INSTANA_IGNORE_ENDPOINTS_PATH value is not valid, got: ${typeof endpointsConfig}. Provide valid YAML file` ); @@ -146,12 +150,12 @@ exports.fromYaml = function fromYaml(yamlFilePath) { } if (!endpointsConfig.tracing && !endpointsConfig['com.instana.tracing']) { - logger?.debug('Invalid configuration: INSTANA_IGNORE_ENDPOINTS_PATH root key must be "tracing".'); + instanaCtr.logger().debug('Invalid configuration: INSTANA_IGNORE_ENDPOINTS_PATH root key must be "tracing".'); return {}; } if (endpointsConfig['com.instana.tracing']) { - logger?.info( + instanaCtr.logger().info( // eslint-disable-next-line max-len `Detected the root key "com.instana.tracing" in the YAML file at "${yamlFilePath}". This format is accepted, but please migrate to using "tracing" as the root key.` ); diff --git a/packages/core/src/util/configNormalizers/index.js b/packages/core/src/config/configNormalizers/index.js similarity index 57% rename from packages/core/src/util/configNormalizers/index.js rename to packages/core/src/config/configNormalizers/index.js index 4a88d3b799..ea098e526d 100644 --- a/packages/core/src/util/configNormalizers/index.js +++ b/packages/core/src/config/configNormalizers/index.js @@ -8,11 +8,11 @@ const disable = require('./disable'); const ignoreEndpoints = require('./ignoreEndpoints'); /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../instanaCtr').InstanaCtrType} instanaCtr */ -exports.init = function init(config) { - disable.init(config); - ignoreEndpoints.init(config); +exports.init = function init(instanaCtr) { + disable.init(instanaCtr); + ignoreEndpoints.init(instanaCtr); }; exports.disable = disable; diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js new file mode 100644 index 0000000000..1f3bf0c6e1 --- /dev/null +++ b/packages/core/src/config/index.js @@ -0,0 +1,22 @@ +/* + * (c) Copyright IBM Corp. 2025 + */ + +'use strict'; + +const normalizeConfig = require('./normalizeConfig'); +const configNormalizers = require('./configNormalizers'); + +/** + * @param {import('../instanaCtr').InstanaCtrType} instanaCtr + */ +exports.init = instanaCtr => { + normalizeConfig.init(instanaCtr); + configNormalizers.init(instanaCtr); +}; + +exports.create = function () { + return normalizeConfig.create(...arguments); +}; + +exports.configNormalizers = configNormalizers; diff --git a/packages/core/src/util/normalizeConfig.js b/packages/core/src/config/normalizeConfig.js similarity index 75% rename from packages/core/src/util/normalizeConfig.js rename to packages/core/src/config/normalizeConfig.js index 34a94d703c..cd4c713ce0 100644 --- a/packages/core/src/util/normalizeConfig.js +++ b/packages/core/src/config/normalizeConfig.js @@ -9,7 +9,6 @@ const supportedTracingVersion = require('../tracing/supportedVersion'); const configNormalizers = require('./configNormalizers'); -const deepMerge = require('./deepMerge'); /** * @typedef {Object} InstanaTracingOption @@ -98,9 +97,6 @@ const allowedSecretMatchers = ['equals', 'equals-ignore-case', 'contains', 'cont * @property {boolean} [traceCorrelation] */ -/** @type {import('../core').GenericLogger} */ -let logger; - /** @type {InstanaConfig} */ let defaults = { serviceName: null, @@ -143,44 +139,40 @@ let defaults = { const validSecretsMatcherModes = ['equals-ignore-case', 'equals', 'contains-ignore-case', 'contains', 'regex', 'none']; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; + +/** + * @param {import('../instanaCtr').InstanaCtrType} [__instanaCtr] + */ +module.exports.init = function init(__instanaCtr) { + instanaCtr = __instanaCtr; +}; + /** * Merges the config that was passed to the init function with environment variables and default values. */ /** - * @param {InstanaConfig} [config] - * @param {import('../core').GenericLogger} [_logger] + * @param {InstanaConfig} [customConfig] * @param {InstanaConfig} [defaultsOverride] * @returns {InstanaConfig} */ -module.exports = function normalizeConfig(config, _logger, defaultsOverride = {}) { - if (_logger) { - logger = _logger; - } else { - // NOTE: This is only a hard backup. This should not happen. We always pass in - // our custom logger from the upper package. - logger = { - debug: console.log, - info: console.log, - warn: console.warn, - error: console.error, - trace: console.trace - }; - } - +module.exports.create = (customConfig, defaultsOverride = {}) => { if (defaultsOverride && typeof defaultsOverride === 'object') { - defaults = deepMerge(defaults, defaultsOverride); + defaults = instanaCtr.utils().deepMerge(defaults, defaultsOverride); } - /** @type InstanaConfig */ + /** @type {InstanaConfig} */ let targetConfig = {}; // NOTE: Do not modify the original object - if (config !== null) { - targetConfig = Object.assign({}, config); + if (customConfig !== null) { + targetConfig = Object.assign({}, customConfig); } - targetConfig.logger = logger; + // TODO: Remove when all modules use instanaCtr + targetConfig.logger = instanaCtr.logger(); normalizeServiceName(targetConfig); normalizePackageJsonPath(targetConfig); @@ -198,9 +190,11 @@ function normalizeServiceName(config) { config.serviceName = process.env['INSTANA_SERVICE_NAME']; } if (config.serviceName != null && typeof config.serviceName !== 'string') { - logger.warn( - `Invalid configuration: config.serviceName is not a string, the value will be ignored: ${config.serviceName}` - ); + instanaCtr + .logger() + .warn( + `Invalid configuration: config.serviceName is not a string, the value will be ignored: ${config.serviceName}` + ); config.serviceName = defaults.serviceName; } } @@ -213,9 +207,11 @@ function normalizePackageJsonPath(config) { config.packageJsonPath = process.env['INSTANA_PACKAGE_JSON_PATH']; } if (config.packageJsonPath != null && typeof config.packageJsonPath !== 'string') { - logger.warn( - `Invalid configuration: config.packageJsonPath is not a string, the value will be ignored: ${config.packageJsonPath}` - ); + instanaCtr + .logger() + .warn( + `Invalid configuration: config.packageJsonPath is not a string, the value will be ignored: ${config.packageJsonPath}` + ); config.packageJsonPath = null; } @@ -271,7 +267,7 @@ function normalizeTracingConfig(config) { */ function normalizeTracingEnabled(config) { if (config.tracing.enabled === false) { - logger.info('Not enabling tracing as it is explicitly disabled via config.'); + instanaCtr.logger().info('Not enabling tracing as it is explicitly disabled via config.'); return; } if (config.tracing.enabled === true) { @@ -280,11 +276,15 @@ function normalizeTracingEnabled(config) { // @deprecated if (process.env['INSTANA_DISABLE_TRACING'] === 'true') { - logger.info('Not enabling tracing as it is explicitly disabled via environment variable INSTANA_DISABLE_TRACING.'); - logger.warn( - 'The environment variable INSTANA_DISABLE_TRACING is deprecated and will be removed in the next major release. ' + - 'Please use INSTANA_TRACING_DISABLE="true" instead.' - ); + instanaCtr + .logger() + .info('Not enabling tracing as it is explicitly disabled via environment variable INSTANA_DISABLE_TRACING.'); + instanaCtr + .logger() + .warn( + 'The environment variable INSTANA_DISABLE_TRACING is deprecated and will be removed in the next major release. ' + + 'Please use INSTANA_TRACING_DISABLE="true" instead.' + ); config.tracing.enabled = false; return; } @@ -338,30 +338,34 @@ function normalizeUseOpentelemetry(config) { */ function normalizeAutomaticTracingEnabled(config) { if (!config.tracing.enabled) { - logger.info('Not enabling automatic tracing as tracing in general is explicitly disabled via config.'); + instanaCtr.logger().info('Not enabling automatic tracing as tracing in general is explicitly disabled via config.'); config.tracing.automaticTracingEnabled = false; return; } if (config.tracing.automaticTracingEnabled === false) { - logger.info('Not enabling automatic tracing as it is explicitly disabled via config.'); + instanaCtr.logger().info('Not enabling automatic tracing as it is explicitly disabled via config.'); config.tracing.automaticTracingEnabled = false; return; } if (process.env['INSTANA_DISABLE_AUTO_INSTR'] === 'true') { - logger.info( - 'Not enabling automatic tracing as it is explicitly disabled via environment variable INSTANA_DISABLE_AUTO_INSTR.' - ); + instanaCtr + .logger() + .info( + 'Not enabling automatic tracing as it is explicitly disabled via environment variable INSTANA_DISABLE_AUTO_INSTR.' + ); config.tracing.automaticTracingEnabled = false; return; } if (!supportedTracingVersion(process.versions.node)) { - logger.warn( - 'Not enabling automatic tracing, this is an unsupported version of Node.js. ' + - 'See: https://www.ibm.com/docs/en/instana-observability/current?topic=nodejs-support-information#supported-nodejs-versions' - ); + instanaCtr + .logger() + .warn( + 'Not enabling automatic tracing, this is an unsupported version of Node.js. ' + + 'See: https://www.ibm.com/docs/en/instana-observability/current?topic=nodejs-support-information#supported-nodejs-versions' + ); config.tracing.automaticTracingEnabled = false; return; } @@ -405,17 +409,21 @@ function normalizeTracingTransmission(config) { // DEPRECATED! This was never documented, but we shared it with a customer. if (process.env['INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS']) { - logger.warn( - 'The environment variable INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS is deprecated and will be removed in the next major release. ' + - 'Please use INSTANA_TRACING_TRANSMISSION_DELAY instead.' - ); + instanaCtr + .logger() + .warn( + 'The environment variable INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS is deprecated and will be removed in the next major release. ' + + 'Please use INSTANA_TRACING_TRANSMISSION_DELAY instead.' + ); config.tracing.transmissionDelay = parseInt(process.env['INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS'], 10); if (isNaN(config.tracing.transmissionDelay)) { - logger.warn( - `The value of INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS is not a number. Falling back to the default value ${defaults.tracing.transmissionDelay}.` - ); + instanaCtr + .logger() + .warn( + `The value of INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS is not a number. Falling back to the default value ${defaults.tracing.transmissionDelay}.` + ); config.tracing.transmissionDelay = defaults.tracing.transmissionDelay; } @@ -454,11 +462,13 @@ function normalizeTracingHttp(config) { config.tracing.http.extraHttpHeadersToCapture = fromEnvVar; } if (!Array.isArray(config.tracing.http.extraHttpHeadersToCapture)) { - logger.warn( - `Invalid configuration: config.tracing.http.extraHttpHeadersToCapture is not an array, the value will be ignored: ${JSON.stringify( - config.tracing.http.extraHttpHeadersToCapture - )}` - ); + instanaCtr + .logger() + .warn( + `Invalid configuration: config.tracing.http.extraHttpHeadersToCapture is not an array, the value will be ignored: ${JSON.stringify( + config.tracing.http.extraHttpHeadersToCapture + )}` + ); config.tracing.http.extraHttpHeadersToCapture = defaults.tracing.http.extraHttpHeadersToCapture; return; } @@ -494,11 +504,13 @@ function normalizeTracingStackTraceLength(config) { } else if (typeof config.tracing.stackTraceLength === 'string') { parseStringStackTraceLength(config, config.tracing.stackTraceLength); } else { - logger.warn( - `The value of config.tracing.stackTraceLength has the non-supported type ${typeof config.tracing - .stackTraceLength} (the value is "${config.tracing.stackTraceLength}").` + - `Assuming the default stack trace length ${defaults.tracing.stackTraceLength}.` - ); + instanaCtr + .logger() + .warn( + `The value of config.tracing.stackTraceLength has the non-supported type ${typeof config.tracing + .stackTraceLength} (the value is "${config.tracing.stackTraceLength}").` + + `Assuming the default stack trace length ${defaults.tracing.stackTraceLength}.` + ); config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } else { @@ -515,10 +527,12 @@ function parseStringStackTraceLength(config, value) { if (!isNaN(config.tracing.stackTraceLength)) { config.tracing.stackTraceLength = normalizeNumericalStackTraceLength(config.tracing.stackTraceLength); } else { - logger.warn( - `The value of config.tracing.stackTraceLength ("${value}") has type string and cannot be parsed to a numerical ` + - `value. Assuming the default stack trace length ${defaults.tracing.stackTraceLength}.` - ); + instanaCtr + .logger() + .warn( + `The value of config.tracing.stackTraceLength ("${value}") has type string and cannot be parsed to a numerical ` + + `value. Assuming the default stack trace length ${defaults.tracing.stackTraceLength}.` + ); config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } @@ -531,9 +545,9 @@ function normalizeNumericalStackTraceLength(numericalLength) { // just in case folks provide non-integral numbers or negative numbers const normalized = Math.abs(Math.round(numericalLength)); if (normalized !== numericalLength) { - logger.warn( - `Normalized the provided value of config.tracing.stackTraceLength (${numericalLength}) to ${normalized}.` - ); + instanaCtr + .logger() + .warn(`Normalized the provided value of config.tracing.stackTraceLength (${numericalLength}) to ${normalized}.`); } return normalized; } @@ -566,20 +580,22 @@ function normalizeSpanBatchingEnabled(config) { if (config.tracing.spanBatchingEnabled != null) { if (typeof config.tracing.spanBatchingEnabled === 'boolean') { if (config.tracing.spanBatchingEnabled) { - logger.info('Span batching is enabled via config.'); + instanaCtr.logger().info('Span batching is enabled via config.'); } return; } else { - logger.warn( - `Invalid configuration: config.tracing.spanBatchingEnabled is not a boolean value, will be ignored: ${JSON.stringify( - config.tracing.spanBatchingEnabled - )}` - ); + instanaCtr + .logger() + .warn( + `Invalid configuration: config.tracing.spanBatchingEnabled is not a boolean value, will be ignored: ${JSON.stringify( + config.tracing.spanBatchingEnabled + )}` + ); } } if (process.env['INSTANA_SPANBATCHING_ENABLED'] === 'true') { - logger.info('Span batching is enabled via environment variable INSTANA_SPANBATCHING_ENABLED.'); + instanaCtr.logger().info('Span batching is enabled via environment variable INSTANA_SPANBATCHING_ENABLED.'); config.tracing.spanBatchingEnabled = true; return; } @@ -592,13 +608,13 @@ function normalizeSpanBatchingEnabled(config) { */ function normalizeDisableW3cTraceCorrelation(config) { if (config.tracing.disableW3cTraceCorrelation === true) { - logger.info('W3C trace correlation has been disabled via config.'); + instanaCtr.logger().info('W3C trace correlation has been disabled via config.'); return; } if (process.env['INSTANA_DISABLE_W3C_TRACE_CORRELATION']) { - logger.info( - 'W3C trace correlation has been disabled via environment variable INSTANA_DISABLE_W3C_TRACE_CORRELATION.' - ); + instanaCtr + .logger() + .info('W3C trace correlation has been disabled via environment variable INSTANA_DISABLE_W3C_TRACE_CORRELATION.'); config.tracing.disableW3cTraceCorrelation = true; return; } @@ -613,12 +629,14 @@ function normalizeTracingKafka(config) { config.tracing.kafka = config.tracing.kafka || {}; if (config.tracing.kafka.traceCorrelation === false) { - logger.info('Kafka trace correlation has been disabled via config.'); + instanaCtr.logger().info('Kafka trace correlation has been disabled via config.'); } else if ( process.env['INSTANA_KAFKA_TRACE_CORRELATION'] != null && process.env['INSTANA_KAFKA_TRACE_CORRELATION'].toLowerCase() === 'false' ) { - logger.info('Kafka trace correlation has been disabled via environment variable INSTANA_KAFKA_TRACE_CORRELATION.'); + instanaCtr + .logger() + .info('Kafka trace correlation has been disabled via environment variable INSTANA_KAFKA_TRACE_CORRELATION.'); config.tracing.kafka.traceCorrelation = false; } else { config.tracing.kafka.traceCorrelation = defaults.tracing.kafka.traceCorrelation; @@ -643,19 +661,25 @@ function normalizeSecrets(config) { config.secrets.keywords = config.secrets.keywords || fromEnvVar.keywords || defaults.secrets.keywords; if (typeof config.secrets.matcherMode !== 'string') { - logger.warn( - `The value of config.secrets.matcherMode ("${config.secrets.matcherMode}") is not a string. Assuming the default value ${defaults.secrets.matcherMode}.` - ); + instanaCtr + .logger() + .warn( + `The value of config.secrets.matcherMode ("${config.secrets.matcherMode}") is not a string. Assuming the default value ${defaults.secrets.matcherMode}.` + ); config.secrets.matcherMode = defaults.secrets.matcherMode; } else if (validSecretsMatcherModes.indexOf(config.secrets.matcherMode) < 0) { - logger.warn( - `The value of config.secrets.matcherMode (or the matcher mode parsed from INSTANA_SECRETS) (${config.secrets.matcherMode}) is not a supported matcher mode. Assuming the default value ${defaults.secrets.matcherMode}.` - ); + instanaCtr + .logger() + .warn( + `The value of config.secrets.matcherMode (or the matcher mode parsed from INSTANA_SECRETS) (${config.secrets.matcherMode}) is not a supported matcher mode. Assuming the default value ${defaults.secrets.matcherMode}.` + ); config.secrets.matcherMode = defaults.secrets.matcherMode; } else if (!Array.isArray(config.secrets.keywords)) { - logger.warn( - `The value of config.secrets.keywords (${config.secrets.keywords}) is not an array. Assuming the default value ${defaults.secrets.keywords}.` - ); + instanaCtr + .logger() + .warn( + `The value of config.secrets.keywords (${config.secrets.keywords}) is not an array. Assuming the default value ${defaults.secrets.keywords}.` + ); config.secrets.keywords = defaults.secrets.keywords; } if (config.secrets.matcherMode === 'none') { @@ -696,9 +720,11 @@ function parseSecretsEnvVar(envVarValue) { if (!keywords) { // a list of keywords (with at least one element) is mandatory for all matcher modes except "none" - logger.warn( - `The value of INSTANA_SECRETS (${envVarValue}) cannot be parsed. Please use the following format: INSTANA_SECRETS=:[,]. This setting will be ignored.` - ); + instanaCtr + .logger() + .warn( + `The value of INSTANA_SECRETS (${envVarValue}) cannot be parsed. Please use the following format: INSTANA_SECRETS=:[,]. This setting will be ignored.` + ); return {}; } @@ -727,7 +753,7 @@ function normalizeSingleValue(configValue, defaultValue, configPath, envVarKey) } if (typeof configValue !== 'number' || isNaN(configValue)) { - logger.warn( + instanaCtr.logger().warn( `The value of ${configPath} (or ${envVarKey}) ("${originalValue}") is ' + 'not numerical or cannot be parsed to a numerical value. Assuming the default value ${defaultValue}.` ); @@ -746,18 +772,22 @@ function normalizeIgnoreEndpoints(config) { const ignoreEndpointsConfig = config.tracing.ignoreEndpoints; if (typeof ignoreEndpointsConfig !== 'object' || Array.isArray(ignoreEndpointsConfig)) { - logger.warn( - `Invalid tracing.ignoreEndpoints configuration. Expected an object, but received: ${JSON.stringify( - ignoreEndpointsConfig - )}` - ); + instanaCtr + .logger() + .warn( + `Invalid tracing.ignoreEndpoints configuration. Expected an object, but received: ${JSON.stringify( + ignoreEndpointsConfig + )}` + ); config.tracing.ignoreEndpoints = {}; return; } // Case 1: Use in-code configuration if available if (Object.keys(ignoreEndpointsConfig).length) { config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(ignoreEndpointsConfig); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + instanaCtr + .logger() + .debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); return; } @@ -769,7 +799,9 @@ function normalizeIgnoreEndpoints(config) { process.env.INSTANA_IGNORE_ENDPOINTS_PATH ); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + instanaCtr + .logger() + .debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); return; } @@ -778,7 +810,9 @@ function normalizeIgnoreEndpoints(config) { // Provides a simple way to configure ignored operations via environment variables. if (process.env.INSTANA_IGNORE_ENDPOINTS) { config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromEnv(process.env.INSTANA_IGNORE_ENDPOINTS); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + instanaCtr + .logger() + .debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); return; } } @@ -788,9 +822,11 @@ function normalizeIgnoreEndpoints(config) { */ function normalizeIgnoreEndpointsDisableSuppression(config) { if (process.env['INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION'] === 'true') { - logger.info( - 'Disabling downstream suppression for ignoring endpoints feature as it is explicitly disabled via environment variable "INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION".' - ); + instanaCtr + .logger() + .info( + 'Disabling downstream suppression for ignoring endpoints feature as it is explicitly disabled via environment variable "INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION".' + ); config.tracing.ignoreEndpointsDisableSuppression = true; return; } @@ -805,9 +841,11 @@ function normalizeDisableEOLEvents(config) { config.tracing = config.tracing || {}; if (process.env['INSTANA_TRACING_DISABLE_EOL_EVENTS'] === 'true') { - logger.info( - 'Disabling EOL events as it is explicitly disabled via environment variable "INSTANA_TRACING_DISABLE_EOL_EVENTS".' - ); + instanaCtr + .logger() + .info( + 'Disabling EOL events as it is explicitly disabled via environment variable "INSTANA_TRACING_DISABLE_EOL_EVENTS".' + ); config.tracing.disableEOLEvents = true; return; } diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 82e2672aa8..2c88427a8e 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -12,7 +12,9 @@ const uninstrumentedFs = require('./uninstrumentedFs'); const metrics = require('./metrics'); const secrets = require('./secrets'); const tracing = require('./tracing'); -const util = require('./util'); +const coreConfig = require('./config'); +const coreUtils = require('./util'); +const instanaCtr = require('./instanaCtr'); /** * @typedef {{ @@ -58,28 +60,30 @@ function registerAdditionalInstrumentations(additionalInstrumentationModules) { * access to the customers configuration yet! * Some logs will appear BEFORE the actual initialization. * e.g. customer passes a custom log level or a custon logger. - * @param {import('./util/normalizeConfig').InstanaConfig} preliminaryConfig + * @param {import('./config/normalizeConfig').InstanaConfig} preliminaryConfig + * @param {import('./util/index').CoreUtilsType} utils */ -function preInit(preliminaryConfig) { - util.init(preliminaryConfig); - util.hasThePackageBeenInitializedTooLate.activate(); - tracing.preInit(preliminaryConfig); +function preInit(preliminaryConfig, utils) { + utils.hasThePackageBeenInitializedTooLate.activate(); // Initialize secrets as early as possible, in particular for env var collection in fargate/google-cloud-run when // the config comes from INSTANA_SECRETS. secrets.init(preliminaryConfig); + + tracing.preInit(preliminaryConfig, utils); } /** * - * @param {import('./util/normalizeConfig').InstanaConfig} config + * @param {import('./config/normalizeConfig').InstanaConfig} config + * @param {import('./util/index').CoreUtilsType} utils * @param {DownstreamConnection} downstreamConnection * @param {import('../../collector/src/pidStore')} processIdentityProvider */ -function init(config, downstreamConnection, processIdentityProvider) { - util.init(config); - util.hasThePackageBeenInitializedTooLate.activate(); +function init(config, utils, downstreamConnection, processIdentityProvider) { + utils.hasThePackageBeenInitializedTooLate.activate(); secrets.init(config); - tracing.init(config, downstreamConnection, processIdentityProvider); + + tracing.init(config, utils, downstreamConnection, processIdentityProvider); } module.exports = { @@ -93,8 +97,10 @@ module.exports = { tracing, uninstrumentedHttp, uninstrumentedFs, - util, + coreConfig, + coreUtils, init, + InstanaCtr: instanaCtr.InstanaCtr, preInit, registerAdditionalInstrumentations }; diff --git a/packages/core/src/instanaCtr.js b/packages/core/src/instanaCtr.js new file mode 100644 index 0000000000..a3fdee0bef --- /dev/null +++ b/packages/core/src/instanaCtr.js @@ -0,0 +1,59 @@ +/* + * (c) Copyright IBM Corp. 2025 + */ + +'use strict'; + +/** + * @typedef {object} InstanaCtrType + * @property {function} utils + * @property {function} config + * @property {function} logger + */ + +class InstanaCtr { + /** @type {import('./util/index').CoreUtilsType} */ + utils_i; + + /** @type {import('./config/normalizeConfig').InstanaConfig} */ + config_i; + + /** @type {import('./core').GenericLogger} */ + logger_i; + + /** + * @param {string} name + * @param {*} instance + */ + set(name, instance) { + Object.defineProperty(this, `${name}_i`, { + configurable: true, + enumerable: true, + writable: false, + value: instance + }); + } + + /** + * @returns {import('./util/index').CoreUtilsType} + */ + utils() { + return this.utils_i; + } + + /** + * @returns {import('./config/normalizeConfig').InstanaConfig} + */ + config() { + return this.config_i; + } + + /** + * @returns {import('./core').GenericLogger} + */ + logger() { + return this.logger_i; + } +} + +exports.InstanaCtr = InstanaCtr; diff --git a/packages/core/src/metrics/index.js b/packages/core/src/metrics/index.js index ffc36c7ff1..a051c2b1e5 100644 --- a/packages/core/src/metrics/index.js +++ b/packages/core/src/metrics/index.js @@ -8,7 +8,7 @@ const fs = require('../uninstrumentedFs'); const path = require('path'); -/** @typedef {import('../util/normalizeConfig').InstanaConfig} InstanaConfig */ +/** @typedef {import('../config/normalizeConfig').InstanaConfig} InstanaConfig */ /** @type {InstanaConfig} */ let config; diff --git a/packages/core/src/secrets.js b/packages/core/src/secrets.js index 9fdd78b8cc..0d7e051100 100644 --- a/packages/core/src/secrets.js +++ b/packages/core/src/secrets.js @@ -174,7 +174,7 @@ function toLowerCase(configuredSecrets) { let isSecretInternal; /** - * @param {import('./util/normalizeConfig').InstanaConfig} config + * @param {import('./config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; @@ -189,7 +189,7 @@ exports.isSecret = function isSecret(key) { }; /** - * @param {import('@instana/core/src/util/normalizeConfig').MatchingOption} matcherId + * @param {import('@instana/core/src/config/normalizeConfig').MatchingOption} matcherId * @param {Array.} secretsList */ exports.setMatcher = function setMatcher(matcherId, secretsList) { diff --git a/packages/core/src/tracing/cls.js b/packages/core/src/tracing/cls.js index 972562ec10..b3e1525ec1 100644 --- a/packages/core/src/tracing/cls.js +++ b/packages/core/src/tracing/cls.js @@ -43,7 +43,7 @@ let ignoreEndpointsDisableDownStreamSuppression; const ns = hooked.createNamespace('instana.collector'); /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../config/normalizeConfig').InstanaConfig} config * @param {import('../../../collector/src/pidStore')} [_processIdentityProvider] */ function init(config, _processIdentityProvider) { diff --git a/packages/core/src/tracing/index.js b/packages/core/src/tracing/index.js index 398448f0d0..bf7c3346ca 100644 --- a/packages/core/src/tracing/index.js +++ b/packages/core/src/tracing/index.js @@ -17,14 +17,16 @@ const shimmer = require('./shimmer'); const supportedVersion = require('./supportedVersion'); const { otelInstrumentations } = require('./opentelemetry-instrumentations'); const cls = require('./cls'); -const coreUtil = require('../util'); let tracingEnabled = false; let tracingActivated = false; let instrumenationsInitialized = false; let automaticTracingEnabled = false; -/** @type {import('../util/normalizeConfig').InstanaConfig} */ +/** @type {import('../util').CoreUtilsType} */ +let coreUtils = null; + +/** @type {import('../config/normalizeConfig').InstanaConfig} */ let config = null; /** @typedef {import('../../../collector/src/pidStore')} CollectorPIDStore */ @@ -162,9 +164,12 @@ exports.registerAdditionalInstrumentations = function registerAdditionalInstrume }; /** - * @param {import('../util/normalizeConfig').InstanaConfig} preliminaryConfig + * @param {import('../config/normalizeConfig').InstanaConfig} preliminaryConfig + * @param {import('../util').CoreUtilsType} utils */ -exports.preInit = function preInit(preliminaryConfig) { +exports.preInit = function preInit(preliminaryConfig, utils) { + coreUtils = utils; + /** * On e.g. Fargate the `preInit` function is called as early as possible * and all our modules (shimmer, cls, sdk etc.) need to be initialized. @@ -192,20 +197,23 @@ exports.preInit = function preInit(preliminaryConfig) { }; /** - * @param {import('../util/normalizeConfig').InstanaConfig} _config + * @param {import('../config/normalizeConfig').InstanaConfig} _config + * @param {import('../util').CoreUtilsType} utils * @param {import('..').DownstreamConnection} downstreamConnection * @param {CollectorPIDStore} _processIdentityProvider */ -exports.init = function init(_config, downstreamConnection, _processIdentityProvider) { +exports.init = function init(_config, utils, downstreamConnection, _processIdentityProvider) { + coreUtils = utils; + if (process.env.INSTANA_DEBUG || process.env.INSTANA_LOG_LEVEL === 'debug') { - const preloadFlags = coreUtil.preloadFlags.get(); + const preloadFlags = coreUtils.preloadFlags.get(); // eslint-disable-next-line no-console console.debug(`The App is using the following preload flags: ${preloadFlags}`); } // Consider removing this in the next major release of the @instana package. - if (coreUtil.esm.hasExperimentalLoaderFlag()) { + if (coreUtils.esm.hasExperimentalLoaderFlag()) { // eslint-disable-next-line no-console console.warn( 'Node.js introduced breaking changes in versions 18.19.0 and above, leading to the discontinuation of support ' + @@ -242,8 +250,8 @@ exports.init = function init(_config, downstreamConnection, _processIdentityProv if (_config.tracing.useOpentelemetry) { otelInstrumentations.init(config, cls); } - if (coreUtil.esm.isESMApp()) { - coreUtil.iitmHook.activate(); + if (coreUtils.esm.isESMApp()) { + coreUtils.iitmHook.activate(); } } } @@ -254,7 +262,7 @@ exports.init = function init(_config, downstreamConnection, _processIdentityProv }; /** - * @param {import('../util/normalizeConfig').InstanaConfig} _config + * @param {import('../config/normalizeConfig').InstanaConfig} _config */ function initInstrumenations(_config) { // initialize all instrumentations @@ -263,7 +271,7 @@ function initInstrumenations(_config) { instrumentationModules[instrumentationKey] = require(instrumentationKey); if ( - !coreUtil.disableInstrumentation.isInstrumentationDisabled({ + !coreUtils.disableInstrumentation.isInstrumentationDisabled({ instrumentationModules, instrumentationKey }) @@ -293,7 +301,7 @@ function initInstrumenations(_config) { exports.activate = function activate(extraConfig = {}) { if (tracingEnabled && !tracingActivated) { tracingActivated = true; - coreUtil.activate(extraConfig); + coreUtils.activate(extraConfig); spanBuffer.activate(extraConfig); opentracing.activate(); sdk.activate(); @@ -309,7 +317,7 @@ exports.activate = function activate(extraConfig = {}) { // // We will revisit this in the future, especially if we encounter issues with disabled instrumentations. if ( - !coreUtil.disableInstrumentation.isInstrumentationDisabled({ + !coreUtils.disableInstrumentation.isInstrumentationDisabled({ instrumentationModules, instrumentationKey }) diff --git a/packages/core/src/tracing/instrumentation/protocols/superagent.js b/packages/core/src/tracing/instrumentation/protocols/superagent.js index 24c6d44524..b779bdc8e5 100644 --- a/packages/core/src/tracing/instrumentation/protocols/superagent.js +++ b/packages/core/src/tracing/instrumentation/protocols/superagent.js @@ -13,7 +13,7 @@ const cls = require('../../cls'); let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function (config) { logger = config.logger; diff --git a/packages/core/src/tracing/opentracing/Span.js b/packages/core/src/tracing/opentracing/Span.js index e93d89c9eb..ce930bfb3d 100644 --- a/packages/core/src/tracing/opentracing/Span.js +++ b/packages/core/src/tracing/opentracing/Span.js @@ -267,7 +267,7 @@ function copyBaggage(baggage) { } /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config * @param {CollectorPIDStore} _processIdentityProvider */ Span.init = function init(config, _processIdentityProvider) { diff --git a/packages/core/src/tracing/opentracing/index.js b/packages/core/src/tracing/opentracing/index.js index 4f8e40fcc9..29b34ae6b9 100644 --- a/packages/core/src/tracing/opentracing/index.js +++ b/packages/core/src/tracing/opentracing/index.js @@ -15,7 +15,7 @@ let cls; let automaticTracingEnabled = false; /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config * @param {boolean} _automaticTracingEnabled * @param {import('../../../../collector/src/pidStore')} processIdentityProvider */ diff --git a/packages/core/src/tracing/sdk/index.js b/packages/core/src/tracing/sdk/index.js index 2eee53d48a..f95e239097 100644 --- a/packages/core/src/tracing/sdk/index.js +++ b/packages/core/src/tracing/sdk/index.js @@ -14,7 +14,7 @@ const callback = sdk.generate(true); const promise = sdk.generate(false); /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config * @param {import('../cls')} _cls */ exports.init = function init(config, _cls) { diff --git a/packages/core/src/tracing/sdk/sdk.js b/packages/core/src/tracing/sdk/sdk.js index eb88a03fed..8d6cacc7a1 100644 --- a/packages/core/src/tracing/sdk/sdk.js +++ b/packages/core/src/tracing/sdk/sdk.js @@ -363,7 +363,7 @@ exports.generate = function (isCallbackApi) { } /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config * @param {import('../cls')} _cls */ function init(config, _cls) { diff --git a/packages/core/src/tracing/spanBuffer.js b/packages/core/src/tracing/spanBuffer.js index 2479124c42..28eeef4181 100644 --- a/packages/core/src/tracing/spanBuffer.js +++ b/packages/core/src/tracing/spanBuffer.js @@ -78,7 +78,7 @@ const batchBucketWidth = 18; const batchingBuckets = new Map(); /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../config/normalizeConfig').InstanaConfig} config * @param {import('..').DownstreamConnection} _downstreamConnection */ exports.init = function init(config, _downstreamConnection) { @@ -103,7 +103,7 @@ exports.init = function init(config, _downstreamConnection) { }; /** - * @param {import('../util/normalizeConfig').AgentConfig} extraConfig + * @param {import('../config/normalizeConfig').AgentConfig} extraConfig */ exports.activate = function activate(extraConfig) { if (!downstreamConnection) { diff --git a/packages/core/src/tracing/spanHandle.js b/packages/core/src/tracing/spanHandle.js index cca9bf5301..4a124cf85d 100644 --- a/packages/core/src/tracing/spanHandle.js +++ b/packages/core/src/tracing/spanHandle.js @@ -440,7 +440,7 @@ NoopSpanHandle.prototype.cancel = function cancel() { }; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/core/src/tracing/tracingHeaders.js b/packages/core/src/tracing/tracingHeaders.js index 64286c5e6e..cddd802229 100644 --- a/packages/core/src/tracing/tracingHeaders.js +++ b/packages/core/src/tracing/tracingHeaders.js @@ -17,7 +17,7 @@ let logger; let disableW3cTraceCorrelation = false; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../config/normalizeConfig').InstanaConfig} config */ exports.init = function (config) { logger = config.logger; diff --git a/packages/core/src/tracing/tracingUtil.js b/packages/core/src/tracing/tracingUtil.js index 405eb981d2..58aa366d55 100644 --- a/packages/core/src/tracing/tracingUtil.js +++ b/packages/core/src/tracing/tracingUtil.js @@ -17,7 +17,7 @@ const hexDecoder = new StringDecoder('hex'); let stackTraceLength = 10; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../config/normalizeConfig').InstanaConfig} config */ exports.init = function (config) { logger = config.logger; diff --git a/packages/core/src/tracing/w3c_trace_context/index.js b/packages/core/src/tracing/w3c_trace_context/index.js index 6ab2d3fbbe..a94edb97fd 100644 --- a/packages/core/src/tracing/w3c_trace_context/index.js +++ b/packages/core/src/tracing/w3c_trace_context/index.js @@ -9,7 +9,7 @@ const create = require('./create'); const parse = require('./parse'); /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { parse.init(config); diff --git a/packages/core/src/tracing/w3c_trace_context/parse.js b/packages/core/src/tracing/w3c_trace_context/parse.js index f5d6ef5cc8..44bf821bc4 100644 --- a/packages/core/src/tracing/w3c_trace_context/parse.js +++ b/packages/core/src/tracing/w3c_trace_context/parse.js @@ -18,7 +18,7 @@ const regexUnknownVersion = /^[0-9a-f]{2}-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f const instanaVendorKeyOffset = constants.w3cInstanaEquals.length; /** - * @param {import('../../util/normalizeConfig').InstanaConfig} config + * @param {import('../../config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; diff --git a/packages/core/src/util/applicationUnderMonitoring.js b/packages/core/src/util/applicationUnderMonitoring.js index 9fb61b62de..a029720413 100644 --- a/packages/core/src/util/applicationUnderMonitoring.js +++ b/packages/core/src/util/applicationUnderMonitoring.js @@ -9,8 +9,8 @@ const fs = require('../uninstrumentedFs'); const path = require('path'); const isESMApp = require('./esm').isESMApp; -/** @type {import('../core').GenericLogger} */ -let logger; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; // Cache determined main package json as these will be referenced often // and identification of these values is expensive. @@ -22,16 +22,11 @@ let mainPackageJsonPath; let nodeModulesPath; let appInstalledIntoNodeModules = false; -/** @type {string} */ -let packageJsonPath; - /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -function init(config) { - logger = config.logger; - - packageJsonPath = config.packageJsonPath; +function init(_instanaCtr) { + instanaCtr = _instanaCtr; } function isAppInstalledIntoNodeModules() { @@ -54,8 +49,8 @@ function getMainPackageJsonStartingAtMainModule(cb) { } // CASE: customer provided custom package.json path, let's try loading it - if (packageJsonPath) { - return readFile(packageJsonPath, cb); + if (instanaCtr.config().packageJsonPath) { + return readFile(instanaCtr.config().packageJsonPath, cb); } return getMainPackageJsonStartingAtDirectory(null, cb); @@ -106,7 +101,9 @@ function readFile(filePath, cb) { try { parsedMainPackageJson = JSON.parse(contents); } catch (e) { - logger.warn(`Package.json file ${packageJsonPath} cannot be parsed: ${e?.message} ${e?.stack}`); + instanaCtr + .logger() + .warn(`Package.json file ${instanaCtr.config().packageJsonPath} cannot be parsed: ${e?.message} ${e?.stack}`); return cb(e, null); } diff --git a/packages/core/src/util/disableInstrumentation.js b/packages/core/src/util/disableInstrumentation.js index c3c4c53ee4..72df4d6cb6 100644 --- a/packages/core/src/util/disableInstrumentation.js +++ b/packages/core/src/util/disableInstrumentation.js @@ -6,21 +6,21 @@ const { DISABLABLE_INSTRUMENTATION_GROUPS } = require('../tracing/constants'); -/** @type {import('../util/normalizeConfig').InstanaConfig} */ -let config; - -/** @type {import('../util/normalizeConfig').AgentConfig} */ +/** @type {import('../config/normalizeConfig').AgentConfig} */ let agentConfig; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; + /** - * @param {import('../util/normalizeConfig').InstanaConfig} _config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -function init(_config) { - config = _config; +function init(_instanaCtr) { + instanaCtr = _instanaCtr; } /** - * @param {import('../util/normalizeConfig').AgentConfig} _agentConfig + * @param {import('../config/normalizeConfig').AgentConfig} _agentConfig */ function activate(_agentConfig) { agentConfig = _agentConfig; @@ -111,7 +111,7 @@ function isInstrumentationDisabled({ instrumentationModules = {}, instrumentatio const context = { moduleName, instrumentationName, group }; // Give priority to service-level config - if (config && shouldDisable(config, context)) { + if (shouldDisable(instanaCtr.config(), context)) { return true; } diff --git a/packages/core/src/util/getPreloadFlags.js b/packages/core/src/util/getPreloadFlags.js index 8645d3429b..90692b22a0 100644 --- a/packages/core/src/util/getPreloadFlags.js +++ b/packages/core/src/util/getPreloadFlags.js @@ -4,14 +4,14 @@ 'use strict'; -/** @type {import('../core').GenericLogger} */ -let logger; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function init(config) { - logger = config.logger; +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; }; exports.get = () => { @@ -48,7 +48,7 @@ exports.get = () => { const result = [nodeOptions, execArgs].filter(Boolean).join(', ') || 'noFlags'; return result; } catch (error) { - logger.error(`Error occurred while doing preload flag filtering: ${error?.message} ${error?.stack}`); + instanaCtr.logger().error(`Error occurred while doing preload flag filtering: ${error?.message} ${error?.stack}`); return ''; } }; diff --git a/packages/core/src/util/iitmHook.js b/packages/core/src/util/iitmHook.js index 4ef047d5c2..61f7d7b967 100644 --- a/packages/core/src/util/iitmHook.js +++ b/packages/core/src/util/iitmHook.js @@ -6,17 +6,17 @@ const iitmHook = require('import-in-the-middle'); -/** @type {import('../core').GenericLogger} */ -let logger; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; /** @type {Object.} */ const byModuleNameTransformers = {}; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function init(config) { - logger = config.logger; +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; }; /** @@ -29,7 +29,7 @@ exports.activate = function activate() { if (typeof transformerFn === 'function') { // @ts-ignore iitmHook([moduleName], (exports, name) => { - logger.debug(`iitm-hooking enabled for module ${name}`); + instanaCtr.logger().debug(`iitm-hooking enabled for module ${name}`); if (exports && exports.default) { exports.default = transformerFn(exports.default); } else { @@ -38,11 +38,13 @@ exports.activate = function activate() { return exports; }); } else { - logger.error( - `The transformer is not a function but of type "${typeof transformerFn}" (details: ${ - transformerFn == null ? 'null/undefined' : transformerFn - }).` - ); + instanaCtr + .logger() + .error( + `The transformer is not a function but of type "${typeof transformerFn}" (details: ${ + transformerFn == null ? 'null/undefined' : transformerFn + }).` + ); } }); } diff --git a/packages/core/src/util/index.js b/packages/core/src/util/index.js index 9956c0e8a1..34269c50f9 100644 --- a/packages/core/src/util/index.js +++ b/packages/core/src/util/index.js @@ -11,49 +11,21 @@ const compression = require('./compression'); const ensureNestedObjectExists = require('./ensureNestedObjectExists'); const excludedFromInstrumentation = require('./excludedFromInstrumentation'); const hasThePackageBeenInitializedTooLate = require('./initializedTooLateHeuristic'); -const normalizeConfig = require('./normalizeConfig'); const propertySizes = require('./propertySizes'); const requireHook = require('./requireHook'); const slidingWindow = require('./slidingWindow'); const stackTrace = require('./stackTrace'); const iitmHook = require('./iitmHook'); const hook = require('./hook'); +const deepMerge = require('./deepMerge'); const esm = require('./esm'); const preloadFlags = require('./getPreloadFlags'); -const configNormalizers = require('./configNormalizers'); const spanFilter = require('./spanFilter'); const yamlReader = require('./yamlReader'); const disableInstrumentation = require('./disableInstrumentation'); -/** @type {import('@instana/core/src/core').GenericLogger} */ -let logger; - -/** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config - */ -exports.init = function init(config) { - logger = config.logger; - hasThePackageBeenInitializedTooLate.init(config); - applicationUnderMonitoring.init(config); - requireHook.init(config); - preloadFlags.init(config); - iitmHook.init(config); - configNormalizers.init(config); - spanFilter.init(config); - yamlReader.init(config); - configNormalizers.init(config); - disableInstrumentation.init(config); -}; - -/** - * @param {import('./normalizeConfig').AgentConfig} extraConfig - */ -exports.activate = function activate(extraConfig) { - disableInstrumentation.activate(extraConfig); - spanFilter.activate(extraConfig); -}; - -exports.applicationUnderMonitoring = applicationUnderMonitoring; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; /** * Make sure that a function is only ever called once. This is useful to maintain @@ -66,7 +38,7 @@ exports.applicationUnderMonitoring = applicationUnderMonitoring; * @return {(...args: *) => *} A wrapped function which will forward the first call to `cb` * and log any successive calls. */ -exports.atMostOnce = function atMostOnce(name, cb) { +const atMostOnce = function atMostOnce(name, cb) { let callCount = 0; return function callbackWrappedForAtMostOneExecution() { callCount++; @@ -77,29 +49,85 @@ exports.atMostOnce = function atMostOnce(name, cb) { args: Array.prototype.slice.call(arguments) }; - logger.debug( - `Function ${name} was called ${callCount} times. This time with the following arguments: ${JSON.stringify( - argObj - )}` - ); + instanaCtr + .logger() + .debug( + `Function ${name} was called ${callCount} times. This time with the following arguments: ${JSON.stringify( + argObj + )}` + ); }; }; -exports.preloadFlags = preloadFlags; -exports.clone = clone; -exports.compression = compression; -exports.ensureNestedObjectExists = ensureNestedObjectExists; -exports.excludedFromInstrumentation = excludedFromInstrumentation; -exports.hasThePackageBeenInitializedTooLate = hasThePackageBeenInitializedTooLate; -exports.normalizeConfig = normalizeConfig; -exports.propertySizes = propertySizes; -exports.requireHook = requireHook; -exports.slidingWindow = slidingWindow; -exports.stackTrace = stackTrace; -exports.iitmHook = iitmHook; -exports.hook = hook; -exports.esm = esm; -exports.configNormalizers = configNormalizers; -exports.spanFilter = spanFilter; -exports.yamlReader = yamlReader; -exports.disableInstrumentation = disableInstrumentation; +/** + * @param {import('../config/normalizeConfig').AgentConfig} extraConfig + */ +const activate = function activate(extraConfig) { + disableInstrumentation.activate(extraConfig); + spanFilter.activate(extraConfig); +}; + +/** + * @typedef {Object} CoreUtilsType + * @property {typeof applicationUnderMonitoring} applicationUnderMonitoring + * @property {typeof clone} clone + * @property {typeof activate} activate + * @property {typeof deepMerge} deepMerge + * @property {typeof compression} compression + * @property {typeof ensureNestedObjectExists} ensureNestedObjectExists + * @property {typeof excludedFromInstrumentation} excludedFromInstrumentation + * @property {typeof hasThePackageBeenInitializedTooLate} hasThePackageBeenInitializedTooLate + * @property {typeof propertySizes} propertySizes + * @property {typeof requireHook} requireHook + * @property {typeof slidingWindow} slidingWindow + * @property {typeof stackTrace} stackTrace + * @property {typeof iitmHook} iitmHook + * @property {typeof hook} hook + * @property {typeof esm} esm + * @property {typeof preloadFlags} preloadFlags + * @property {typeof spanFilter} spanFilter + * @property {typeof yamlReader} yamlReader + * @property {typeof disableInstrumentation} disableInstrumentation + * @property {typeof atMostOnce} atMostOnce + */ + +/** + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr + */ +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; + + hasThePackageBeenInitializedTooLate.init(instanaCtr); + applicationUnderMonitoring.init(instanaCtr); + requireHook.init(instanaCtr); + preloadFlags.init(instanaCtr); + iitmHook.init(instanaCtr); + spanFilter.init(instanaCtr); + yamlReader.init(instanaCtr); + disableInstrumentation.init(instanaCtr); +}; + +exports.create = () => { + return { + preloadFlags, + clone, + activate, + compression, + applicationUnderMonitoring, + ensureNestedObjectExists, + excludedFromInstrumentation, + hasThePackageBeenInitializedTooLate, + propertySizes, + requireHook, + atMostOnce, + slidingWindow, + stackTrace, + iitmHook, + hook, + esm, + spanFilter, + yamlReader, + disableInstrumentation, + deepMerge + }; +}; diff --git a/packages/core/src/util/initializedTooLateHeuristic.js b/packages/core/src/util/initializedTooLateHeuristic.js index 867117b1f3..082f79c094 100644 --- a/packages/core/src/util/initializedTooLateHeuristic.js +++ b/packages/core/src/util/initializedTooLateHeuristic.js @@ -5,8 +5,8 @@ 'use strict'; -/** @type {import('../core').GenericLogger} */ -let logger; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; let firstCall = true; let hasBeenInitializedTooLate = false; @@ -81,10 +81,10 @@ const extraPatterns = [ ]; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function init(config) { - logger = config.logger; +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; }; /** @@ -100,7 +100,7 @@ exports.activate = function hasThePackageBeenInitializedTooLate() { if (addExtraPatterns) { patterns = patterns.concat(extraPatterns); } else { - logger.debug( + instanaCtr.logger().debug( // eslint-disable-next-line max-len 'Found @contrast/agent in the modules that have already been loaded. @instana/core will therefore exclude bluebird, request and winston from the check for modules that have been loaded before @instana/core.' ); @@ -111,7 +111,7 @@ exports.activate = function hasThePackageBeenInitializedTooLate() { for (let j = 0; j < patterns.length; j++) { if (patterns[j].test(loadedModules[i])) { hasBeenInitializedTooLate = true; - logger.debug( + instanaCtr.logger().debug( // eslint-disable-next-line max-len `Found a module that has been loaded before @instana/core but should have been loaded afterwards: ${loadedModules[i]}.` ); diff --git a/packages/core/src/util/requireHook.js b/packages/core/src/util/requireHook.js index 1667fec834..662352a011 100644 --- a/packages/core/src/util/requireHook.js +++ b/packages/core/src/util/requireHook.js @@ -35,14 +35,14 @@ let byModuleNameTransformers = {}; let byFileNamePatternTransformers = []; const origLoad = /** @type {*} */ (Module)._load; -/** @type {import('../core').GenericLogger} */ -let logger; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; /** - * @param {import('./normalizeConfig').InstanaConfig} [config] + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function (config) { - logger = config.logger; +exports.init = function (_instanaCtr) { + instanaCtr = _instanaCtr; /** @type {*} */ (Module)._load = patchedModuleLoad; }; @@ -126,19 +126,21 @@ function patchedModuleLoad(moduleName) { try { cacheEntry.moduleExports = transformerFn(cacheEntry.moduleExports, filename) || cacheEntry.moduleExports; } catch (e) { - logger.error( - `Cannot instrument ${moduleName} due to an error in instrumentation: ${e?.message}, ${e?.stack}` - ); + instanaCtr + .logger() + .error(`Cannot instrument ${moduleName} due to an error in instrumentation: ${e?.message}, ${e?.stack}`); } } else { - logger.error( - `A requireHook invariant has been violated for module name ${moduleName}, index ${i}. ` + - `The transformer is not a function but of type "${typeof transformerFn}" (details: ${ - transformerFn == null ? 'null/undefined' : transformerFn - }). The most likely cause is that something has messed with Node.js' ` + - 'module cache. This can result in limited tracing and health check functionality (for example, missing ' + - 'calls in Instana).' - ); + instanaCtr + .logger() + .error( + `A requireHook invariant has been violated for module name ${moduleName}, index ${i}. ` + + `The transformer is not a function but of type "${typeof transformerFn}" (details: ${ + transformerFn == null ? 'null/undefined' : transformerFn + }). The most likely cause is that something has messed with Node.js' ` + + 'module cache. This can result in limited tracing and health check functionality (for example, missing ' + + 'calls in Instana).' + ); } } cacheEntry.appliedByModuleNameTransformers.push(moduleName); diff --git a/packages/core/src/util/spanFilter.js b/packages/core/src/util/spanFilter.js index 03524006ab..d57e165139 100644 --- a/packages/core/src/util/spanFilter.js +++ b/packages/core/src/util/spanFilter.js @@ -4,22 +4,21 @@ 'use strict'; -/** - * @type {import('../tracing').IgnoreEndpoints} - */ -let ignoreEndpoints; +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; + +/** @type {import('../tracing').IgnoreEndpoints} */ +let ignoreEndpointsConfig; /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -function init(config) { - if (config?.tracing?.ignoreEndpoints) { - ignoreEndpoints = config.tracing.ignoreEndpoints; - } +function init(_instanaCtr) { + instanaCtr = _instanaCtr; } /** - * @param {import('../util/normalizeConfig').AgentConfig} extraConfig + * @param {import('../config/normalizeConfig').AgentConfig} extraConfig */ function activate(extraConfig) { /** @@ -36,9 +35,11 @@ function activate(extraConfig) { * * TODO: Perform a major refactoring of configuration priority ordering in INSTA-817. */ - const isIgnoreEndpointsEmpty = !ignoreEndpoints || Object.keys(ignoreEndpoints).length === 0; + ignoreEndpointsConfig = instanaCtr.config().tracing.ignoreEndpoints; + const isIgnoreEndpointsEmpty = !ignoreEndpointsConfig || Object.keys(ignoreEndpointsConfig).length === 0; + if (isIgnoreEndpointsEmpty && extraConfig?.tracing?.ignoreEndpoints) { - ignoreEndpoints = extraConfig.tracing.ignoreEndpoints; + ignoreEndpointsConfig = extraConfig.tracing.ignoreEndpoints; } } @@ -127,10 +128,9 @@ function matchConnections(span, spanTypeKey, ignoreconfig) { /** * @param {import("../core").InstanaBaseSpan} span - * @param {import('../tracing').IgnoreEndpoints} ignoreEndpointsConfig * @returns {boolean} */ -function shouldIgnore(span, ignoreEndpointsConfig) { +function shouldIgnore(span) { // Skip if the span type is not in the ignored list if (!IGNORABLE_SPAN_TYPES.includes(span.n)) { return false; @@ -200,7 +200,7 @@ function normalizeSpanDataTypeKey(spanType) { * @returns {import('../core').InstanaBaseSpan | null} */ function applyFilter(span) { - if (ignoreEndpoints && shouldIgnore(span, ignoreEndpoints)) { + if (ignoreEndpointsConfig && shouldIgnore(span)) { return null; } return span; diff --git a/packages/core/src/util/yamlReader.js b/packages/core/src/util/yamlReader.js index c11eb48206..ad083ca03b 100644 --- a/packages/core/src/util/yamlReader.js +++ b/packages/core/src/util/yamlReader.js @@ -20,13 +20,15 @@ const path = require('path'); * - read-yaml-file parsing took: 0.000536 seconds - Best option * */ -/** @type {import('../core').GenericLogger} */ -let logger; + +/** @type {import('../instanaCtr').InstanaCtrType} */ +let instanaCtr; + /** - * @param {import('../util/normalizeConfig').InstanaConfig} config + * @param {import('../instanaCtr').InstanaCtrType} _instanaCtr */ -exports.init = function init(config) { - logger = config.logger; +exports.init = function init(_instanaCtr) { + instanaCtr = _instanaCtr; }; /** @@ -36,7 +38,7 @@ exports.init = function init(config) { exports.read = function read(filePath) { try { if (!path.isAbsolute(filePath)) { - logger?.warn(`The file path is not absolute. Expected an absolute path, but received: ${filePath}`); + instanaCtr.logger().warn(`The file path is not absolute. Expected an absolute path, but received: ${filePath}`); return {}; } @@ -49,7 +51,7 @@ exports.read = function read(filePath) { delete require.cache[require.resolve('read-yaml-file')]; return result; } catch (error) { - logger?.warn(`Error reading YAML file from ${filePath}: ${error?.message}`); + instanaCtr.logger().warn(`Error reading YAML file from ${filePath}: ${error?.message}`); return {}; } }; diff --git a/packages/core/test/tracing/index_test.js b/packages/core/test/tracing/index_test.js index d1894ee74e..e1a1adf62f 100644 --- a/packages/core/test/tracing/index_test.js +++ b/packages/core/test/tracing/index_test.js @@ -11,7 +11,7 @@ const sinonChai = require('sinon-chai'); const testUtils = require('@instana/core/test/test_util'); const supportedVersion = require('@instana/core').tracing.supportedVersion; -const normalizeConfig = require('../../src/util/normalizeConfig'); +const normalizeConfig = require('../../src/config/normalizeConfig'); const kafkaJs = require('../../src/tracing/instrumentation/messaging/kafkaJs'); const rdKafka = require('../../src/tracing/instrumentation/messaging/rdkafka'); const grpcJs = require('../../src/tracing/instrumentation/protocols/grpcJs'); diff --git a/packages/core/test/util/configNormalizers/disable_test.js b/packages/core/test/util/configNormalizers/disable_test.js index 5fa6cde022..500272ad61 100644 --- a/packages/core/test/util/configNormalizers/disable_test.js +++ b/packages/core/test/util/configNormalizers/disable_test.js @@ -7,7 +7,7 @@ const { describe, it, beforeEach, afterEach } = require('mocha'); const { expect } = require('chai'); -const { normalize, normalizeExternalConfig } = require('../../../src/util/configNormalizers/disable'); +const { normalize, normalizeExternalConfig } = require('../../../src/config/configNormalizers/disable'); function resetEnv() { delete process.env.INSTANA_DISABLED_TRACERS; diff --git a/packages/core/test/util/configNormalizers/ignoreEndpoints_test.js b/packages/core/test/util/configNormalizers/ignoreEndpoints_test.js index 0a1936950b..856284efcf 100644 --- a/packages/core/test/util/configNormalizers/ignoreEndpoints_test.js +++ b/packages/core/test/util/configNormalizers/ignoreEndpoints_test.js @@ -7,7 +7,7 @@ const fs = require('fs'); const path = require('path'); const { expect } = require('chai'); -const { normalizeConfig, fromEnv, fromYaml } = require('../../../src/util/configNormalizers/ignoreEndpoints'); +const { normalizeConfig, fromEnv, fromYaml } = require('../../../src/config/configNormalizers/ignoreEndpoints'); describe('util.ignoreEndpoints', function () { describe('normalizeConfig', function () { @@ -190,7 +190,7 @@ describe('util.ignoreEndpoints', function () { tracingYamlPath, `tracing: ignore-endpoints: - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); @@ -199,7 +199,7 @@ describe('util.ignoreEndpoints', function () { comInstanaTracingYamlPath, `com.instana.tracing: ignore-endpoints: - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); @@ -208,7 +208,7 @@ describe('util.ignoreEndpoints', function () { invalidTracingYamlPath, `instana-tracing: ignore-endpoints: - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); @@ -217,7 +217,7 @@ describe('util.ignoreEndpoints', function () { withoutIgnoreEndpointsYamlPath, `tracing: sampling: - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); @@ -226,10 +226,10 @@ describe('util.ignoreEndpoints', function () { withBasicFilteringYamlPath, `tracing: ignore-endpoints: - redis: + redis: - type - get - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); diff --git a/packages/core/test/util/normalizeConfig_test.js b/packages/core/test/util/normalizeConfig_test.js index 38f863676b..22ba023e78 100644 --- a/packages/core/test/util/normalizeConfig_test.js +++ b/packages/core/test/util/normalizeConfig_test.js @@ -9,7 +9,7 @@ const expect = require('chai').expect; const fs = require('fs'); const path = require('path'); -const normalizeConfig = require('../../src/util/normalizeConfig'); +const normalizeConfig = require('../../src/config/normalizeConfig'); describe('util.normalizeConfig', () => { beforeEach(resetEnv); @@ -862,7 +862,7 @@ describe('util.normalizeConfig', () => { tracingYamlPath, `tracing: ignore-endpoints: - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); @@ -871,7 +871,7 @@ describe('util.normalizeConfig', () => { comInstanaTracingYamlPath, `com.instana.tracing: ignore-endpoints: - kafka: + kafka: - methods: ["consume","publish"] endpoints: ["topic1","topic2"]` ); diff --git a/packages/google-cloud-run/src/activate.js b/packages/google-cloud-run/src/activate.js index 2262e1acac..cae6cea53e 100644 --- a/packages/google-cloud-run/src/activate.js +++ b/packages/google-cloud-run/src/activate.js @@ -6,32 +6,40 @@ 'use strict'; const instanaCore = require('@instana/core'); -const { backendConnector, consoleLogger: log } = require('@instana/serverless'); +const { backendConnector, consoleLogger: serverlessLogger } = require('@instana/serverless'); const identityProvider = require('./identity_provider'); const metrics = require('./metrics'); -const { tracing, util: coreUtil } = instanaCore; -const { normalizeConfig } = coreUtil; +const { tracing, coreUtils, coreConfig } = instanaCore; +const instanaCtr = new instanaCore.InstanaCtr(); -const logger = log.init(); -const config = normalizeConfig({}, logger); +coreUtils.init(instanaCtr); +coreConfig.init(instanaCtr); +serverlessLogger.init(instanaCtr); + +instanaCtr.set('utils', coreUtils.create()); +instanaCtr.set('config', coreConfig.create()); +instanaCtr.set('logger', serverlessLogger.create()); function init() { if (!process.env.K_REVISION) { - logger.error( - 'Initializing @instana/google-cloud-run failed. The environment variable K_REVISION is not set. This container ' + - 'instance will not be monitored.' - ); + instanaCtr + .logger() + .error( + 'Initializing @instana/google-cloud-run failed. ' + + 'The environment variable K_REVISION is not set. This container ' + + 'instance will not be monitored.' + ); return; } - instanaCore.preInit(config); + instanaCore.preInit(instanaCtr.config(), instanaCtr.utils()); - metrics.init(config, function onReady(err, serviceRevisionPayload) { + metrics.init(instanaCtr.config(), function onReady(err, serviceRevisionPayload) { if (err) { - logger.error( - `Initializing @instana/google-cloud-run failed. This container instance will not be monitored. + instanaCtr.logger().error( + `Initializing @instana/google-cloud-run failed. This container instance will not be monitored. Error: ${err?.message} ${err?.stack}` ); metrics.deactivate(); @@ -41,10 +49,12 @@ function init() { const containerInstanceId = serviceRevisionPayload && serviceRevisionPayload.data ? serviceRevisionPayload.data.instanceId : null; if (!containerInstanceId) { - logger.error( - 'Initializing @instana/google-cloud-run failed, the metadata did not have an instance ID. This Cloud Run ' + - 'container instance will not be monitored.' - ); + instanaCtr + .logger() + .error( + 'Initializing @instana/google-cloud-run failed, the metadata did not have an instance ID. This Cloud Run ' + + 'container instance will not be monitored.' + ); metrics.deactivate(); return; } @@ -53,21 +63,21 @@ function init() { identityProvider.init(containerInstanceId); backendConnector.init({ - config, + config: instanaCtr.config(), identityProvider, defaultTimeout: 950 }); - instanaCore.init(config, backendConnector, identityProvider); + instanaCore.init(instanaCtr.config(), instanaCtr.utils(), backendConnector, identityProvider); metrics.activate(backendConnector); tracing.activate(); - logger.debug('@instana/google-cloud-run initialized.'); + instanaCtr.logger().debug('@instana/google-cloud-run initialized.'); // eslint-disable-next-line no-unused-expressions process.send && process.send('instana.google-cloud-run.initialized'); } catch (e) { - logger.error( + instanaCtr.logger().error( `Initializing @instana/google-cloud-run failed. This Cloud Run container instance will not be monitored. ${e?.message} ${e?.stack}` ); @@ -85,7 +95,7 @@ exports.sdk = tracing.sdk; // NOTE: this is the external interface for the customer. They can set a custom logger. exports.setLogger = function setLogger(_logger) { - log.init({ logger: _logger }); + instanaCtr.logger().setLogger(_logger); }; exports.opentracing = tracing.opentracing; diff --git a/packages/google-cloud-run/test/Control.js b/packages/google-cloud-run/test/Control.js index 2480d4846f..2b0db31b3e 100644 --- a/packages/google-cloud-run/test/Control.js +++ b/packages/google-cloud-run/test/Control.js @@ -12,7 +12,7 @@ const fetch = require('node-fetch-v2'); const portfinder = require('@instana/collector/test/test_util/portfinder'); const config = require('@instana/core/test/config'); const AbstractServerlessControl = require('../../serverless/test/util/AbstractServerlessControl'); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; const PATH_TO_INSTANA_GOOGLE_CLOUD_RUN_PACKAGE = path.join(__dirname, '..'); function Control(opts) { diff --git a/packages/serverless-collector/src/activate.js b/packages/serverless-collector/src/activate.js index 18a5146dc3..7f68420391 100644 --- a/packages/serverless-collector/src/activate.js +++ b/packages/serverless-collector/src/activate.js @@ -5,15 +5,21 @@ 'use strict'; const instanaCore = require('@instana/core'); -const { backendConnector, consoleLogger: log } = require('@instana/serverless'); +const { backendConnector, consoleLogger: serverlessLogger } = require('@instana/serverless'); const identityProvider = require('./identity_provider'); -const { tracing, util: coreUtil } = instanaCore; -const { normalizeConfig } = coreUtil; +const { tracing, coreUtils, coreConfig } = instanaCore; const customMetrics = require('./metrics'); -const logger = log.init(); -const config = normalizeConfig({}, logger); +const instanaCtr = new instanaCore.InstanaCtr(); + +coreUtils.init(instanaCtr); +coreConfig.init(instanaCtr); +serverlessLogger.init(instanaCtr); + +instanaCtr.set('utils', coreUtils.create()); +instanaCtr.set('config', coreConfig.create()); +instanaCtr.set('logger', serverlessLogger.create()); async function init() { // NOTE: This package does not support autotracing. @@ -23,32 +29,34 @@ async function init() { // NOTE: We have to call pre-init because we are running an async call to get the service name. // The goal is to register our instrumentations as early as possible. // Otherwise we can easily run into errors e.g. from `hasThePackageBeenInitializedTooLate`. - instanaCore.preInit(config); + instanaCore.preInit(instanaCtr.config(), instanaCtr.utils()); - const serviceName = await customMetrics.name(config); + const serviceName = await customMetrics.name(instanaCtr.config()); if (serviceName) { - config.serviceName = serviceName; + instanaCtr.config().serviceName = serviceName; } identityProvider.init(); backendConnector.init({ - config, + config: instanaCtr.config(), identityProvider, defaultTimeout: 950 }); - instanaCore.init(config, backendConnector, identityProvider); + instanaCore.init(instanaCtr.config(), instanaCtr.utils(), backendConnector, identityProvider); tracing.activate(); - logger.info('@instana/serverless-collector initialized.'); + instanaCtr.logger().info('@instana/serverless-collector initialized.'); // eslint-disable-next-line no-unused-expressions process.send && process.send('instana.serverless-collector.initialized'); } catch (e) { - logger.error( - `Initializing @instana/serverless-collector failed. This process will not be traced. ${e?.message} ${e?.stack}` - ); + instanaCtr + .logger() + .error( + `Initializing @instana/serverless-collector failed. This process will not be traced. ${e?.message} ${e?.stack}` + ); } } @@ -64,7 +72,7 @@ exports.sdk = tracing.sdk; // NOTE: this is the external interface for the customer. They can set a custom logger. exports.setLogger = function setLogger(_logger) { - log.init(_logger); + instanaCtr.logger().setLogger(_logger); }; exports.opentracing = tracing.opentracing; diff --git a/packages/serverless-collector/src/index.js b/packages/serverless-collector/src/index.js index a9be73135f..adf2c958d2 100644 --- a/packages/serverless-collector/src/index.js +++ b/packages/serverless-collector/src/index.js @@ -15,7 +15,7 @@ if (isNodeJsTooOld()) { return; } -const { util: coreUtil } = require('@instana/core'); +const excludedFromInstrumentation = require('@instana/core/src/util/excludedFromInstrumentation'); const { environment: environmentUtil, consoleLogger: log } = require('@instana/serverless'); // TODO: we currently call "log.init()" twice. Once here @@ -23,7 +23,7 @@ const { environment: environmentUtil, consoleLogger: log } = require('@instana/s const logger = log.init(); environmentUtil.init({ logger }); -const isExcludedFromInstrumentation = coreUtil.excludedFromInstrumentation && coreUtil.excludedFromInstrumentation(); +const isExcludedFromInstrumentation = excludedFromInstrumentation && excludedFromInstrumentation(); if (!isExcludedFromInstrumentation) { environmentUtil.validate(); diff --git a/packages/serverless-collector/test/Control.js b/packages/serverless-collector/test/Control.js index 97fd9d1d91..ee585841a9 100644 --- a/packages/serverless-collector/test/Control.js +++ b/packages/serverless-collector/test/Control.js @@ -10,7 +10,7 @@ const fetch = require('node-fetch-v2'); const portfinder = require('@instana/collector/test/test_util/portfinder'); const config = require('@instana/core/test/config'); const AbstractServerlessControl = require('../../serverless/test/util/AbstractServerlessControl'); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; const SERVERLESS_COLLECTOR_PATH = path.join(__dirname, '..'); let execArg; diff --git a/packages/serverless/src/logger.js b/packages/serverless/src/logger.js index b93ebd734a..8ef9a24d42 100644 --- a/packages/serverless/src/logger.js +++ b/packages/serverless/src/logger.js @@ -73,35 +73,41 @@ class InstanaServerlessLogger { trace = (...args) => this.logger?.trace?.(...args); } -exports.init = function init(config = {}) { +/** + * @param {import('@instana/core/src/instanaCtr').InstanaCtrType} [_instanaCtr] + */ +// eslint-disable-next-line no-unused-vars +exports.init = _instanaCtr => {}; + +exports.create = customConfig => { let parentLogger; - // CASE: prevent circular references - if (config.logger && config.logger instanceof InstanaServerlessLogger && config.logger.logger) { - config.logger = config.logger.logger; + // CASE: prevent circular references. This is our own logger. + if (customConfig.logger && customConfig.logger instanceof InstanaServerlessLogger && customConfig.logger.logger) { + customConfig.logger = customConfig.logger.logger; } // CASE: customer overrides logger in serverless land. - if (config.logger && typeof config.logger.child === 'function') { + if (customConfig.logger && typeof customConfig.logger.child === 'function') { // A bunyan or pino logger has been provided via config. In either case we create a child logger directly under the // given logger which serves as the parent for all loggers we create later on. // BUG: Winston does not support child logger levels! Neither in `.child` nor with `level()` // Setting INSTANA_DEBUG=true has no affect in the child winston logger. // It takes the parent logger level. - parentLogger = config.logger.child({ + parentLogger = customConfig.logger.child({ module: 'instana-nodejs-serverless-logger' }); - } else if (config.logger && hasLoggingFunctions(config.logger)) { + } else if (customConfig.logger && hasLoggingFunctions(customConfig.logger)) { // A custom non-bunyan/non-pino logger has been provided via config. We use it as is. - parentLogger = config.logger; + parentLogger = customConfig.logger; } else { parentLogger = consoleLogger; } // NOTE: We accept for `process.env.INSTANA_DEBUG` any string value - does not have to be "true". - if (process.env.INSTANA_DEBUG || config.level || process.env.INSTANA_LOG_LEVEL) { - setLoggerLevel(process.env.INSTANA_DEBUG ? 'debug' : config.level || process.env.INSTANA_LOG_LEVEL); + if (process.env.INSTANA_DEBUG || customConfig.level || process.env.INSTANA_LOG_LEVEL) { + setLoggerLevel(process.env.INSTANA_DEBUG ? 'debug' : customConfig.level || process.env.INSTANA_LOG_LEVEL); } if (!instanaServerlessLogger) { diff --git a/packages/shared-metrics/src/dependencies.js b/packages/shared-metrics/src/dependencies.js index f92aa3b291..9603ba4fd5 100644 --- a/packages/shared-metrics/src/dependencies.js +++ b/packages/shared-metrics/src/dependencies.js @@ -6,7 +6,7 @@ 'use strict'; const path = require('path'); -const { util, uninstrumentedFs: fs } = require('@instana/core'); +const { uninstrumentedFs: fs } = require('@instana/core'); const CountDownLatch = require('./util/CountDownLatch'); const { DependencyDistanceCalculator, MAX_DEPTH } = require('./util/DependencyDistanceCalculator'); @@ -14,10 +14,15 @@ const { DependencyDistanceCalculator, MAX_DEPTH } = require('./util/DependencyDi /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -exports.init = function init(config) { +exports.init = function init(config, utils) { + coreUtils = utils; logger = config.logger; }; @@ -43,7 +48,7 @@ exports.activate = function activate() { attempts++; const started = Date.now(); - util.applicationUnderMonitoring.getMainPackageJsonPathStartingAtMainModule((err, mainPackageJsonPath) => { + coreUtils.applicationUnderMonitoring.getMainPackageJsonPathStartingAtMainModule((err, mainPackageJsonPath) => { if (err) { return logger.warn(`Failed to determine main package.json. Reason: ${err?.message}, ${err?.stack}`); } else if (!mainPackageJsonPath && attempts < exports.MAX_ATTEMPTS) { @@ -54,7 +59,8 @@ exports.activate = function activate() { logger.info( `Main package.json could not be found after ${attempts} retries. Looking for node_modules folder now.` ); - util.applicationUnderMonitoring.findNodeModulesFolder((errNodeModules, nodeModulesFolder) => { + + coreUtils.applicationUnderMonitoring.findNodeModulesFolder((errNodeModules, nodeModulesFolder) => { if (errNodeModules) { return logger.warn(`Failed to determine node_modules folder. Reason: ${err?.message}, ${err?.stack}`); } else if (!nodeModulesFolder) { @@ -69,7 +75,7 @@ exports.activate = function activate() { } let dependencyDir; - if (util.applicationUnderMonitoring.isAppInstalledIntoNodeModules()) { + if (coreUtils.applicationUnderMonitoring.isAppInstalledIntoNodeModules()) { dependencyDir = path.join(path.dirname(mainPackageJsonPath), '..', '..', 'node_modules'); } else { dependencyDir = path.join(path.dirname(mainPackageJsonPath), 'node_modules'); @@ -199,7 +205,7 @@ function addDependency(dependency, dependencyDirPath, countDownLatch) { } } catch (parseErr) { return logger.info( - `Failed to identify version of ${dependency} dependency due to: ${parseErr?.message}. + `Failed to identify version of ${dependency} dependency due to: ${parseErr?.message}. This means that you will not be able to see details about this dependency within Instana.` ); } diff --git a/packages/shared-metrics/src/description.js b/packages/shared-metrics/src/description.js index 564a952abe..b34c0ac3a9 100644 --- a/packages/shared-metrics/src/description.js +++ b/packages/shared-metrics/src/description.js @@ -5,16 +5,19 @@ 'use strict'; -const { applicationUnderMonitoring } = require('@instana/core').util; - /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -exports.init = function init(config) { +exports.init = function init(config, utils) { logger = config.logger; + coreUtils = utils; }; exports.payloadPrefix = 'description'; @@ -28,7 +31,7 @@ let attempts = 0; exports.activate = function activate() { attempts++; - applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { + coreUtils.applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { if (err) { return logger.warn(`Failed to determine main package json. Reason: ${err?.message} ${err?.stack}`); } else if (!packageJson && attempts < MAX_ATTEMPTS) { diff --git a/packages/shared-metrics/src/directDependencies.js b/packages/shared-metrics/src/directDependencies.js index f3017524a7..6505a5dcb6 100644 --- a/packages/shared-metrics/src/directDependencies.js +++ b/packages/shared-metrics/src/directDependencies.js @@ -5,16 +5,21 @@ 'use strict'; -const { util, uninstrumentedFs: fs } = require('@instana/core'); +const { uninstrumentedFs: fs } = require('@instana/core'); /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -exports.init = function init(config) { +exports.init = function init(config, utils) { logger = config.logger; + coreUtils = utils; }; exports.payloadPrefix = 'directDependencies'; @@ -36,10 +41,10 @@ exports.deactivate = function deactivate() { exports.activate = function activate() { attempts++; - util.applicationUnderMonitoring.getMainPackageJsonPathStartingAtMainModule((err, packageJsonPath) => { + coreUtils.applicationUnderMonitoring.getMainPackageJsonPathStartingAtMainModule((err, packageJsonPath) => { if (err) { return logger.info( - `Failed to determine main package.json for analysis of direct dependencies. + `Failed to determine main package.json for analysis of direct dependencies. Reason: ${err?.message} ${err?.stack}` ); } else if (!packageJsonPath && attempts < MAX_ATTEMPTS) { diff --git a/packages/shared-metrics/src/gc.js b/packages/shared-metrics/src/gc.js index d2191e5230..87c97dc922 100644 --- a/packages/shared-metrics/src/gc.js +++ b/packages/shared-metrics/src/gc.js @@ -6,7 +6,7 @@ 'use strict'; const path = require('path'); -const slidingWindow = require('@instana/core').util.slidingWindow; +const slidingWindow = require('@instana/core').coreUtils.slidingWindow; const nativeModuleRetry = require('./util/nativeModuleRetry'); const windowOpts = { duration: 1000 }; diff --git a/packages/shared-metrics/src/healthchecks.js b/packages/shared-metrics/src/healthchecks.js index e210d8041e..ee98c87045 100644 --- a/packages/shared-metrics/src/healthchecks.js +++ b/packages/shared-metrics/src/healthchecks.js @@ -5,13 +5,13 @@ 'use strict'; -const { hook } = require('@instana/core').util; +const { hook } = require('@instana/core').coreUtils; /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; @@ -39,7 +39,7 @@ hook.onModuleLoad( ); /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.activate = function activate(config) { timeBetweenHealthcheckCalls = config.metrics.timeBetweenHealthcheckCalls; diff --git a/packages/shared-metrics/src/index.js b/packages/shared-metrics/src/index.js index 3165ef3fab..83be92725d 100644 --- a/packages/shared-metrics/src/index.js +++ b/packages/shared-metrics/src/index.js @@ -44,18 +44,17 @@ const allMetrics = [ ]; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -const init = function (config) { - util.init(config); - dependencies.init(config); - description.init(config); - directDependencies.init(config); +const init = function (config, utils) { + dependencies.init(config, utils); + description.init(config, utils); + directDependencies.init(config, utils); healthchecks.init(config); - keywords.init(config); - name.init(config); - version.init(config); - name.init(config); + keywords.init(config, utils); + name.init(config, utils); + version.init(config, utils); gc.init(); libuv.init(); }; @@ -64,7 +63,7 @@ const init = function (config) { * @typedef {Object} InstanaSharedMetrics * @property {Array.} allMetrics * @property {import('./util')} util - * @property {(config: import('@instana/core/src/util/normalizeConfig').InstanaConfig) => void} init + * @property {(config: import('@instana/core/src/config/normalizeConfig').InstanaConfig) => void} init * @property {(logger: import('@instana/core/src/core').GenericLogger) => void} setLogger */ diff --git a/packages/shared-metrics/src/keywords.js b/packages/shared-metrics/src/keywords.js index c0a8596eb6..d7496f0dd6 100644 --- a/packages/shared-metrics/src/keywords.js +++ b/packages/shared-metrics/src/keywords.js @@ -5,16 +5,19 @@ 'use strict'; -const { applicationUnderMonitoring } = require('@instana/core').util; - /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -exports.init = function init(config) { +exports.init = function init(config, utils) { logger = config.logger; + coreUtils = utils; }; exports.payloadPrefix = 'keywords'; @@ -29,7 +32,7 @@ let attempts = 0; exports.activate = function activate() { attempts++; - applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { + coreUtils.applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { if (err) { return logger.warn(`Failed to determine main package json. Reason: ${err?.message} ${err?.stack}`); } else if (!packageJson && attempts < MAX_ATTEMPTS) { diff --git a/packages/shared-metrics/src/name.js b/packages/shared-metrics/src/name.js index e8601d5180..a2d99dd04d 100644 --- a/packages/shared-metrics/src/name.js +++ b/packages/shared-metrics/src/name.js @@ -5,16 +5,19 @@ 'use strict'; -const { applicationUnderMonitoring } = require('@instana/core').util; - /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils */ -exports.init = function init(config) { +exports.init = function init(config, utils) { logger = config.logger; + coreUtils = utils; }; exports.payloadPrefix = 'name'; @@ -28,7 +31,7 @@ let attempts = 0; exports.activate = function activate() { attempts++; - applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { + coreUtils.applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { if (err) { return logger.warn(`Failed to determine main package json. Reason: ${err?.message} ${err?.stack}`); } else if (!packageJson && attempts < exports.MAX_ATTEMPTS) { diff --git a/packages/shared-metrics/src/util/DependencyDistanceCalculator.js b/packages/shared-metrics/src/util/DependencyDistanceCalculator.js index 90d59a862f..3353aa2223 100644 --- a/packages/shared-metrics/src/util/DependencyDistanceCalculator.js +++ b/packages/shared-metrics/src/util/DependencyDistanceCalculator.js @@ -15,7 +15,7 @@ const CountDownLatch = require('./CountDownLatch'); let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ const init = config => { logger = config.logger; @@ -89,7 +89,7 @@ class DependencyDistanceCalculator { parsedPackageJson = JSON.parse(contents); } catch (parseErr) { logger.debug( - `Failed to calculate transitive distances for some dependencies, could not parse package.json file at + `Failed to calculate transitive distances for some dependencies, could not parse package.json file at ${packageJsonPath}: ${parseErr?.message}.` ); this.globalCountDownLatchAllPackages.countDown(3); @@ -106,7 +106,7 @@ class DependencyDistanceCalculator { // This catch-block is for synchronous errors from fs.readFile, which can also happen in addition to the callback // being called with an error. logger.debug( - `Failed to calculate transitive distances for some dependencies, synchronous error from fs.readFile for + `Failed to calculate transitive distances for some dependencies, synchronous error from fs.readFile for ${packageJsonPath}: ${fsReadFileErr?.message}` ); this.globalCountDownLatchAllPackages.countDown(3); diff --git a/packages/shared-metrics/src/util/index.js b/packages/shared-metrics/src/util/index.js index 729e00e2f3..80817d6f5c 100644 --- a/packages/shared-metrics/src/util/index.js +++ b/packages/shared-metrics/src/util/index.js @@ -9,7 +9,7 @@ const nativeModuleRetry = require('./nativeModuleRetry'); const dependencyDistanceCalculator = require('./DependencyDistanceCalculator'); /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ const init = config => { nativeModuleRetry.init(config); diff --git a/packages/shared-metrics/src/util/nativeModuleRetry.js b/packages/shared-metrics/src/util/nativeModuleRetry.js index d705145a13..651fb74ac5 100644 --- a/packages/shared-metrics/src/util/nativeModuleRetry.js +++ b/packages/shared-metrics/src/util/nativeModuleRetry.js @@ -16,7 +16,7 @@ const detectLibc = require('detect-libc'); let logger; /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config */ exports.init = function init(config) { logger = config.logger; @@ -178,7 +178,7 @@ function copyPrecompiled(opts, loaderEmitter, callback) { return; } else if (statsErr) { logger.warn( - `Looking for a precompiled version for ${opts.nativeModuleName} ${label} failed. + `Looking for a precompiled version for ${opts.nativeModuleName} ${label} failed. ${statsErr?.message} ${statsErr?.stack}` ); callback(false); @@ -235,7 +235,7 @@ function copyPrecompiled(opts, loaderEmitter, callback) { }); }) .catch(tarErr => { - logger.warn(`Unpacking the precompiled build for ${opts.nativeModuleName} ${label} failed. + logger.warn(`Unpacking the precompiled build for ${opts.nativeModuleName} ${label} failed. ${tarErr?.message} ${tarErr?.stack}`); callback(false); }); diff --git a/packages/shared-metrics/src/version.js b/packages/shared-metrics/src/version.js index 5bb56dd6a6..8ceb63bf17 100644 --- a/packages/shared-metrics/src/version.js +++ b/packages/shared-metrics/src/version.js @@ -5,16 +5,20 @@ 'use strict'; -const { applicationUnderMonitoring } = require('@instana/core').util; - /** @type {import('@instana/core/src/core').GenericLogger} */ let logger; +/** @type {import('@instana/core/src/util').CoreUtilsType} */ +let coreUtils; + /** - * @param {import('@instana/core/src/util/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/config/normalizeConfig').InstanaConfig} config + * @param {import('@instana/core/src/util').CoreUtilsType} utils + * */ -exports.init = function init(config) { +exports.init = function init(config, utils) { logger = config.logger; + coreUtils = utils; }; exports.payloadPrefix = 'version'; @@ -28,7 +32,7 @@ let attempts = 0; exports.activate = function activate() { attempts++; - applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { + coreUtils.applicationUnderMonitoring.getMainPackageJsonStartingAtMainModule((err, packageJson) => { if (err) { return logger.warn(`Failed to determine main package json. Reason: ${err?.message} ${err?.stack}`); } else if (!packageJson && attempts < MAX_ATTEMPTS) { diff --git a/packages/shared-metrics/test/esm-loader/test.js b/packages/shared-metrics/test/esm-loader/test.js index eaa05498b0..be0fe5df0c 100644 --- a/packages/shared-metrics/test/esm-loader/test.js +++ b/packages/shared-metrics/test/esm-loader/test.js @@ -10,7 +10,7 @@ const expect = require('chai').expect; const { supportedVersion } = require('@instana/core').tracing; const testUtils = require('@instana/core/test/test_util'); const config = require('@instana/core/test/config'); -const isLatestEsmSupportedVersion = require('@instana/core').util.esm.isLatestEsmSupportedVersion; +const isLatestEsmSupportedVersion = require('@instana/core').coreUtils.esm.isLatestEsmSupportedVersion; const ProcessControls = require('../../../collector/test/test_util/ProcessControls'); const loaderPath = isLatestEsmSupportedVersion(process.versions.node) diff --git a/packages/shared-metrics/test/name_test.js b/packages/shared-metrics/test/name_test.js index 00fc772cef..1167c40476 100644 --- a/packages/shared-metrics/test/name_test.js +++ b/packages/shared-metrics/test/name_test.js @@ -10,7 +10,7 @@ const sinon = require('sinon'); const path = require('path'); const testUtils = require('../../core/test/test_util'); const name = require('../src/name'); -const { applicationUnderMonitoring } = require('@instana/core').util; +const { applicationUnderMonitoring } = require('@instana/core').coreUtils; describe('metrics.name', () => { before(() => {