@instana/core
Advanced tools
Comparing version 3.21.0 to 5.0.0
@@ -6,2 +6,72 @@ # Change Log | ||
# [5.0.0](https://github.com/instana/nodejs/compare/v3.21.0...v5.0.0) (2024-10-23) | ||
### Bug Fixes | ||
- deprecated kafka-avro ([#1337](https://github.com/instana/nodejs/issues/1337)) ([5647c3f](https://github.com/instana/nodejs/commit/5647c3fc8383329b187b6edd54dcbbfd5a90f021)) | ||
- dropped support for disabling AWS SDK instrumentation in old syntax ([#1383](https://github.com/instana/nodejs/issues/1383)) ([48bebf3](https://github.com/instana/nodejs/commit/48bebf3d2342a2dbe1f9c06ab0a5a3ad10a26c29)) | ||
- dropped support for node v14 and v16 ([#1348](https://github.com/instana/nodejs/issues/1348)) ([aaa9ad4](https://github.com/instana/nodejs/commit/aaa9ad41ebf82b11eedcf913afc31d3addd53868)) | ||
- dropped support for q library ([#1377](https://github.com/instana/nodejs/issues/1377)) ([c7f1fa5](https://github.com/instana/nodejs/commit/c7f1fa57f76a0cb8faefafaa0a30eb45a898b53a)) | ||
- dropped support for x-instana-service header ([#1355](https://github.com/instana/nodejs/issues/1355)) ([7aa5f4b](https://github.com/instana/nodejs/commit/7aa5f4b87e07fc5d1d804aeae1eaea173fdb33c6)) | ||
- **kafka:** enforced string format for Kafka trace headers and dropped binary support ([#1296](https://github.com/instana/nodejs/issues/1296)) ([2c822d3](https://github.com/instana/nodejs/commit/2c822d3c68966737a1e83d4141bd5a5ac3958cc8)) | ||
### Features | ||
- added support for root exit spans ([#1297](https://github.com/instana/nodejs/issues/1297)) ([f1e1f30](https://github.com/instana/nodejs/commit/f1e1f30b87983bf9109a0ac097ec10458edd3643)) | ||
### BREAKING CHANGES | ||
- - Removed the ability to disable AWS SDK instrumentation using the old syntax disabledTracers: ['aws-sdk/v2/index']. | ||
* Migrate to the new syntax for disabling instrumentation: disabledTracers: ['aws-sdk/v2']. | ||
- - Migration: Please configure the Instana agent to capture the X-Instana-Service header in the agent's configuration file. | ||
* For details, see: https://www.ibm.com/docs/en/instana-observability/current?topic=applications-services#specify-the-x-instana-service-http-header. | ||
- - Dropped support for Node.js versions 14 and 16. | ||
* Reason: These versions have reached their end of life. | ||
* More info: https://github.com/nodejs/Release?tab=readme-ov-file#end-of-life-releases | ||
- **kafka:** - Removed the ability to configure the header format; headers will always be sent in 'string' format. | ||
* Removed support for 'binary' format and code related to sending headers in 'binary' or 'both' formats. | ||
refs INSTA-809 | ||
# [4.0.0](https://github.com/instana/nodejs/compare/v3.21.0...v4.0.0) (2024-10-23) | ||
### Bug Fixes | ||
- deprecated kafka-avro ([#1337](https://github.com/instana/nodejs/issues/1337)) ([5647c3f](https://github.com/instana/nodejs/commit/5647c3fc8383329b187b6edd54dcbbfd5a90f021)) | ||
- dropped support for disabling AWS SDK instrumentation in old syntax ([#1383](https://github.com/instana/nodejs/issues/1383)) ([48bebf3](https://github.com/instana/nodejs/commit/48bebf3d2342a2dbe1f9c06ab0a5a3ad10a26c29)) | ||
- dropped support for node v14 and v16 ([#1348](https://github.com/instana/nodejs/issues/1348)) ([aaa9ad4](https://github.com/instana/nodejs/commit/aaa9ad41ebf82b11eedcf913afc31d3addd53868)) | ||
- dropped support for q library ([#1377](https://github.com/instana/nodejs/issues/1377)) ([c7f1fa5](https://github.com/instana/nodejs/commit/c7f1fa57f76a0cb8faefafaa0a30eb45a898b53a)) | ||
- dropped support for x-instana-service header ([#1355](https://github.com/instana/nodejs/issues/1355)) ([7aa5f4b](https://github.com/instana/nodejs/commit/7aa5f4b87e07fc5d1d804aeae1eaea173fdb33c6)) | ||
- **kafka:** enforced string format for Kafka trace headers and dropped binary support ([#1296](https://github.com/instana/nodejs/issues/1296)) ([2c822d3](https://github.com/instana/nodejs/commit/2c822d3c68966737a1e83d4141bd5a5ac3958cc8)) | ||
### Features | ||
- added support for root exit spans ([#1297](https://github.com/instana/nodejs/issues/1297)) ([f1e1f30](https://github.com/instana/nodejs/commit/f1e1f30b87983bf9109a0ac097ec10458edd3643)) | ||
### BREAKING CHANGES | ||
- - Removed the ability to disable AWS SDK instrumentation using the old syntax disabledTracers: ['aws-sdk/v2/index']. | ||
* Migrate to the new syntax for disabling instrumentation: disabledTracers: ['aws-sdk/v2']. | ||
- - Migration: Please configure the Instana agent to capture the X-Instana-Service header in the agent's configuration file. | ||
* For details, see: https://www.ibm.com/docs/en/instana-observability/current?topic=applications-services#specify-the-x-instana-service-http-header. | ||
- - Dropped support for Node.js versions 14 and 16. | ||
* Reason: These versions have reached their end of life. | ||
* More info: https://github.com/nodejs/Release?tab=readme-ov-file#end-of-life-releases | ||
- **kafka:** - Removed the ability to configure the header format; headers will always be sent in 'string' format. | ||
* Removed support for 'binary' format and code related to sending headers in 'binary' or 'both' formats. | ||
refs INSTA-809 | ||
# [3.21.0](https://github.com/instana/nodejs/compare/v3.20.2...v3.21.0) (2024-10-17) | ||
@@ -8,0 +78,0 @@ |
{ | ||
"name": "@instana/core", | ||
"version": "3.21.0", | ||
"version": "5.0.0", | ||
"description": "Core library for Instana's Node.js packages", | ||
@@ -75,3 +75,3 @@ "main": "src/index.js", | ||
}, | ||
"gitHead": "88f34c35252f7f71028456f408e668d7ab624e96" | ||
"gitHead": "209e1ac4c64c5224c99bffcc82a172c3d22e4438" | ||
} |
@@ -31,2 +31,4 @@ /* | ||
let processIdentityProvider = null; | ||
/** @type {Boolean} */ | ||
let allowRootExitSpan; | ||
@@ -52,2 +54,3 @@ /* | ||
processIdentityProvider = _processIdentityProvider; | ||
allowRootExitSpan = config?.tracing?.allowRootExitSpan; | ||
} | ||
@@ -248,4 +251,3 @@ | ||
if (traceId) { | ||
// The incoming trace ID/span ID from an upstream tracer could be shorter than the standard length. Some of our code | ||
// (in particular, the binary Kafka trace correlation header X_INSTANA_C) assumes the standard length. We normalize | ||
// The incoming trace ID/span ID from an upstream tracer could be shorter than the standard length. We normalize | ||
// both IDs here by left-padding with 0 characters. | ||
@@ -506,2 +508,6 @@ | ||
* | skipIsTracing | Instrumentation wants to handle `cls.isTracing` on it's own (e.g db2) | ||
* | checkReducedSpan | If no active entry span is present, there is an option for | ||
* | | falling back to the most recent parent span stored as reduced span | ||
* | | by setting checkReducedSpan attribute to true. | ||
* | skipAllowRootExitSpanPresence | An instrumentation can ignore this feature to reduce noise. | ||
* | ||
@@ -516,3 +522,5 @@ * @param {Object.<string, *>} options | ||
skipParentSpanCheck: false, | ||
skipIsTracing: false | ||
skipIsTracing: false, | ||
checkReducedSpan: false, | ||
skipAllowRootExitSpanPresence: false | ||
}, | ||
@@ -522,5 +530,19 @@ options | ||
const parentSpan = getCurrentSpan(); | ||
let isReducedSpan = false; | ||
let parentSpan = getCurrentSpan(); | ||
// If there is no active entry span, we fall back to the reduced span of the most recent entry span. | ||
// See comment in packages/core/src/tracing/clsHooked/unset.js#storeReducedSpan. | ||
if (opts.checkReducedSpan && !parentSpan) { | ||
parentSpan = getReducedSpan(); | ||
// We need to remember if a reduced span was used, because for reduced spans | ||
// we do NOT trace anymore. The async context got already closed. | ||
if (parentSpan) { | ||
isReducedSpan = true; | ||
} | ||
} | ||
const suppressed = tracingSuppressed(); | ||
const isExitSpanResult = isExitSpan(parentSpan); | ||
const isParentSpanAnExitSpan = isExitSpan(parentSpan); | ||
@@ -530,16 +552,47 @@ // CASE: first ask for suppressed, because if we skip the entry span, we won't have a parentSpan | ||
if (suppressed) { | ||
if (opts.extendedResponse) return { skip: true, suppressed, isExitSpan: isExitSpanResult }; | ||
if (opts.extendedResponse) { | ||
return { skip: true, suppressed, isExitSpan: isParentSpanAnExitSpan, parentSpan, allowRootExitSpan }; | ||
} | ||
return true; | ||
} | ||
if (!opts.skipParentSpanCheck && (!parentSpan || isExitSpanResult)) { | ||
if (opts.extendedResponse) return { skip: true, suppressed, isExitSpan: isExitSpanResult }; | ||
else return true; | ||
// DESC: If `allowRootExitSpan` is true, then we have to ignore if there is a parent or not. | ||
// NOTE: The feature completely ignores the state of `isTracing`, because | ||
// every exit span would be a separate trace. `isTracing` is always false, | ||
// because we don't have a parent span. The http server span also does not check of `isTracing`, | ||
// because it's the root span. | ||
// CASE: Instrumentations can disable the `allowRootExitSpan` feature e.g. loggers. | ||
if (!opts.skipAllowRootExitSpanPresence && allowRootExitSpan) { | ||
if (opts.extendedResponse) { | ||
return { skip: false, suppressed, isExitSpan: isParentSpanAnExitSpan, parentSpan, allowRootExitSpan }; | ||
} | ||
return false; | ||
} | ||
// Parent span check is required skipParentSpanCheck and no parent is present but an exit span only | ||
if (!opts.skipParentSpanCheck && (!parentSpan || isParentSpanAnExitSpan)) { | ||
if (opts.extendedResponse) { | ||
return { skip: true, suppressed, isExitSpan: isParentSpanAnExitSpan, parentSpan, allowRootExitSpan }; | ||
} | ||
return true; | ||
} | ||
const skipIsActive = opts.isActive === false; | ||
const skipIsTracing = !opts.skipIsTracing ? !isTracing() : false; | ||
let skipIsTracing = !opts.skipIsTracing ? !isTracing() : false; | ||
// See comment on top. | ||
if (isReducedSpan) { | ||
skipIsTracing = false; | ||
} | ||
const skip = skipIsActive || skipIsTracing; | ||
if (opts.extendedResponse) return { skip, suppressed, isExitSpan: isExitSpanResult }; | ||
else return skip; | ||
if (opts.extendedResponse) { | ||
return { skip, suppressed, isExitSpan: isParentSpanAnExitSpan, parentSpan, allowRootExitSpan }; | ||
} | ||
return skip; | ||
} | ||
@@ -546,0 +599,0 @@ |
@@ -10,21 +10,16 @@ /* | ||
const semver = require('semver'); | ||
/** | ||
* In order to increase Node.js version support, this loads an implementation of a CLS (continuation local storage) API | ||
* which is appropriate for the version of on Node.js that is running. | ||
* - Node.js 14.0 - 16.6: AsyncLocalStorage | ||
* - Node.js 16.7 - 16.6: our vendored-in fork of cls-hooked (based on async_hooks) (see below for reasons) | ||
* - Node.js >= 16.14: AsyncLocalStorage | ||
* which is appropriate for the version of Node.js that is running. | ||
* If 'INSTANA_FORCE_LEGACY_CLS' is set to 'true', the legacy implementation will be used. | ||
* | ||
* There is a bug introduced in Node 16.7 which breaks AsyncLocalStorage: https://github.com/nodejs/node/issues/40693 | ||
* - AsyncLocalStorage fix introduced in v17.2: https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V17.md#commits-5 | ||
* - AsyncLocalStorage fix introduced in v16.14: https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V16.md#commits | ||
* Previous known Issues: | ||
* - Node.js 16.7 introduced a bug that breaks AsyncLocalStorage: | ||
* https://github.com/nodejs/node/issues/40693 | ||
* This bug affected the functionality of AsyncLocalStorage until it was fixed in: | ||
* - Node.js 16.14: https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V16.md#commits | ||
* - Node.js 17.2: https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V17.md#commits-5 | ||
* | ||
*/ | ||
const includePrerelease = process.env.NODE_ENV === 'test'; | ||
if ( | ||
process.env.INSTANA_FORCE_LEGACY_CLS !== 'true' && | ||
semver.satisfies(process.versions.node, '14.0 - 16.6 || ^16.14 || >=17.2', { includePrerelease }) | ||
) { | ||
if (process.env.INSTANA_FORCE_LEGACY_CLS !== 'true') { | ||
module.exports = require('./async_local_storage_context'); | ||
@@ -31,0 +26,0 @@ } else { |
@@ -20,11 +20,6 @@ /* | ||
// legacy kafka trace correlation (binary values) | ||
exports.kafkaLegacyTraceContextHeaderName = 'X_INSTANA_C'; | ||
exports.kafkaLegacyTraceLevelHeaderName = 'X_INSTANA_L'; | ||
exports.kafkaLegacyTraceLevelValueSuppressed = Buffer.from([0]); | ||
exports.kafkaLegacyTraceLevelValueInherit = Buffer.from([1]); | ||
// New Kafka trace correlation (string values) was introduced as an opt-in feature in 2021-10. Initially, it was sent | ||
// out along with the legacy binary headers by default starting in 2022-10. However, as of 2024-10, only string headers | ||
// are supported, and the legacy binary headers are no longer supported. | ||
// New kafka trace correlation (string values). Available as opt-in since 2021-10, and send out together with the legacy | ||
// binary headers by default starting in 2022-10. We will switch over to these headers completely (omitting the legacy | ||
// headers approximately in 2023-10. | ||
exports.kafkaTraceIdHeaderName = 'X_INSTANA_T'; | ||
@@ -34,10 +29,2 @@ exports.kafkaSpanIdHeaderName = 'X_INSTANA_S'; | ||
/** | ||
* @typedef {'binary' | 'string' | 'both'} KafkaTraceCorrelationFormat | ||
*/ | ||
// With the current phase 1 of the Kafka header format migration, 'both', is the default. | ||
// With phase 2 (starting approximately October 2023) it will no longer be configurable and will always use 'string'. | ||
/** @type {KafkaTraceCorrelationFormat} */ | ||
exports.kafkaHeaderFormatDefault = 'both'; | ||
exports.kafkaTraceCorrelationDefault = true; | ||
@@ -48,5 +35,3 @@ | ||
exports.kafkaSpanIdHeaderName, | ||
exports.kafkaTraceLevelHeaderName, | ||
exports.kafkaLegacyTraceContextHeaderName, | ||
exports.kafkaLegacyTraceLevelHeaderName | ||
exports.kafkaTraceLevelHeaderName | ||
]; | ||
@@ -59,5 +44,2 @@ | ||
exports.serviceNameHeaderName = 'X-Instana-Service'; | ||
exports.serviceNameHeaderNameLowerCase = exports.serviceNameHeaderName.toLowerCase(); | ||
exports.ENTRY = 1; | ||
@@ -64,0 +46,0 @@ exports.EXIT = 2; |
@@ -18,8 +18,3 @@ /* | ||
const { otelInstrumentations } = require('./opentelemetry-instrumentations'); | ||
const { | ||
esmSupportedVersion, | ||
isLatestEsmSupportedVersion, | ||
hasExperimentalLoaderFlag, | ||
isESMApp | ||
} = require('../util/esm'); | ||
const { isLatestEsmSupportedVersion, hasExperimentalLoaderFlag, isESMApp } = require('../util/esm'); | ||
const iitmHook = require('../util/iitmHook'); | ||
@@ -50,4 +45,4 @@ const { getPreloadFlags } = require('../util/getPreloadFlags'); | ||
let instrumentations = [ | ||
'./instrumentation/cloud/aws-sdk/v2/index', | ||
'./instrumentation/cloud/aws-sdk/v3/index', | ||
'./instrumentation/cloud/aws-sdk/v2', | ||
'./instrumentation/cloud/aws-sdk/v3', | ||
'./instrumentation/cloud/aws-sdk/v2/sdk', | ||
@@ -61,3 +56,2 @@ './instrumentation/cloud/aws-sdk/v2/sqs', | ||
'./instrumentation/control_flow/graphqlSubscriptions', | ||
'./instrumentation/control_flow/q', | ||
'./instrumentation/database/elasticsearch', | ||
@@ -129,3 +123,2 @@ './instrumentation/database/ioredis', | ||
* @property {boolean} [traceCorrelation] | ||
* @property {string} [headerFormat] | ||
*/ | ||
@@ -145,3 +138,2 @@ | ||
exports.util = tracingUtil; | ||
exports.esmSupportedVersion = esmSupportedVersion; | ||
exports.isLatestEsmSupportedVersion = isLatestEsmSupportedVersion; | ||
@@ -196,3 +188,3 @@ | ||
// Consider removing this in the next major release(v4.x) of the @instana package. | ||
// Consider removing this in the next major release of the @instana package. | ||
if (hasExperimentalLoaderFlag()) { | ||
@@ -199,0 +191,0 @@ // eslint-disable-next-line no-console |
@@ -30,4 +30,2 @@ /* | ||
exports.instrumentationName = 'aws-sdk/v2'; | ||
exports.isActive = function () { | ||
@@ -34,0 +32,0 @@ return isActive; |
@@ -34,4 +34,2 @@ /* | ||
exports.instrumentationName = 'aws-sdk/v3'; | ||
exports.init = function init() { | ||
@@ -88,8 +86,7 @@ sqsConsumer.init(); | ||
} else { | ||
// This code can be removed once all AWS SDK v3 instrumentations have been refactored to use the new approach | ||
// introduced in https://github.com/instana/nodejs/pull/838 for kinesis. That is: Do not use an explicit | ||
// operationsInfo/operationsMap map that restricts the traced operations to a subset of possible operations, but | ||
// instead allow _all_ operations to be traced, using the operation name from `command.constructor.name` for | ||
// span.data.$spanName.op. We plan to finish this refactoring before or with the next major release (4.x) of the | ||
// @instana packages. | ||
// This logic should not be used in AWS SDK v4. All AWS SDK v4 instrumentations must use the new approach | ||
// introduced in https://github.com/instana/nodejs/pull/838 for Kinesis. That is: Do not use an explicit | ||
// operationsInfo/operationsMap that restricts the traced operations to a subset of possible operations. | ||
// Instead, allow all operations to be traced using the operation name from `command.constructor.name` | ||
// for span.data.$spanName.op. | ||
awsProduct = operationMap[smithySendArgs[0].constructor.name]; | ||
@@ -96,0 +93,0 @@ if (awsProduct) { |
@@ -51,8 +51,27 @@ /* | ||
/** | ||
* We need to set `skipIsTracing` check for db2, because of e.g. prepare | ||
* statements or transactions. We don't always know if we are tracing or not. | ||
*/ | ||
function skipTracing(ignoreClsTracing = false) { | ||
// CASES: instrumentation is disabled, db call is disabled via suppress header | ||
return ( | ||
cls.skipExitTracing({ isActive, skipIsTracing: true, skipParentSpanCheck: true }) || | ||
(ignoreClsTracing ? false : !cls.isTracing()) | ||
); | ||
const skipExitResult = cls.skipExitTracing({ | ||
isActive, | ||
skipIsTracing: true, | ||
skipParentSpanCheck: true, | ||
extendedResponse: true | ||
}); | ||
const isTracing = cls.isTracing(); | ||
// CASE: `cls.skipExitTracing` decided to skip, respect that | ||
if (skipExitResult.skip) return true; | ||
// CASE: the target parent function wants us to ignore cls.isTracing | ||
// because e.g. we don't know if we trace (parent got lost) | ||
if (ignoreClsTracing) return false; | ||
// CASE: We ignore if tracing or not for `allowRootExitSpan`. See cls file. | ||
if (skipExitResult.allowRootExitSpan) return false; | ||
return !isTracing; | ||
} | ||
@@ -105,3 +124,7 @@ | ||
// NOTE: See function description | ||
cls.setCurrentSpan(parentSpan); | ||
// NOTE: We need to ensure that there is a parentSpan, see 'allowRootExitSpan: true'. | ||
if (parentSpan) { | ||
cls.setCurrentSpan(parentSpan); | ||
} | ||
return originalCallback.apply(this, arguments); | ||
@@ -335,4 +358,8 @@ }); | ||
// cls.isTracing is false when `execute` is minimum called twice | ||
// then parentSpan is undefined, because there is no current span and no remembered span yet | ||
// CASE 1: `cls.isTracing` is false when `execute` is minimum called twice, because | ||
// because there is NO current span and no remembered span. | ||
// We skip checking `cls.isTracing` because we want to trace the second call. | ||
// | ||
// CASE 2: `allowRootExitSpan: true` is set, we might not have an entry span at all on | ||
// the first execute call. | ||
if (skipTracing(!parentSpan || !!prepareCallParentSpan)) { | ||
@@ -348,4 +375,7 @@ return false; | ||
* - prepare call happens in http context, we need to remember it | ||
* | ||
* CASE: When setting `allowRootExitSpan: true`, the parentSpan might be null. | ||
*/ | ||
cls.setCurrentSpan(rememberedParentSpan || parentSpan); | ||
const parentToSetAsCurrent = rememberedParentSpan || parentSpan; | ||
if (parentToSetAsCurrent) cls.setCurrentSpan(parentToSetAsCurrent); | ||
return true; | ||
@@ -352,0 +382,0 @@ }; |
@@ -47,10 +47,9 @@ /* | ||
const client = this; | ||
const parentSpan = cls.getCurrentSpan(); | ||
// We need to skip parentSpan condition because the parentSpan check is too specific in this fn | ||
const skipExitTracingResult = cls.skipExitTracing({ isActive, skipParentSpanCheck: true, extendedResponse: true }); | ||
const parentSpan = skipExitTracingResult.parentSpan; | ||
let callback; | ||
if ( | ||
command.promise == null || | ||
typeof command.name !== 'string' || | ||
cls.skipExitTracing({ isActive, skipParentSpanCheck: true }) | ||
) { | ||
if (command.promise == null || typeof command.name !== 'string' || skipExitTracingResult.skip) { | ||
return original.apply(this, arguments); | ||
@@ -64,2 +63,3 @@ } | ||
if ( | ||
parentSpan && | ||
parentSpan.n === exports.spanName && | ||
@@ -71,4 +71,8 @@ (parentSpan.data.redis.command === 'multi' || parentSpan.data.redis.command === 'pipeline') && | ||
parentSpanSubCommands.push(command.name); | ||
} else if (constants.isExitSpan(parentSpan)) { | ||
// Apart from the special case of multi/pipeline calls, redis exits can't be child spans of other exits. | ||
} else if ( | ||
// If allowRootExitSpan is not enabled then an EXIT SPAN can't exist alone | ||
(!skipExitTracingResult.allowRootExitSpan && parentSpan && constants.isExitSpan(parentSpan)) || | ||
!parentSpan | ||
) { | ||
// Apart from the special case of multi/pipeline calls, redis exits can't be child spans of other exits | ||
return original.apply(this, arguments); | ||
@@ -132,6 +136,13 @@ } | ||
const client = this; | ||
const parentSpan = cls.getCurrentSpan(); | ||
const skipExitTracingResult = cls.skipExitTracing({ isActive, skipParentSpanCheck: true, extendedResponse: true }); | ||
const parentSpan = skipExitTracingResult.parentSpan; | ||
// NOTE: multiple redis transaction can have a parent ioredis call | ||
if (cls.skipExitTracing({ isActive, skipParentSpanCheck: true }) || constants.isExitSpan(parentSpan)) { | ||
// If cls.skipExitTracing wants to skip the tracing then skip it | ||
// Also if allowRootExitSpan is not enabled then an EXIT SPAN can't exist alone | ||
if ( | ||
skipExitTracingResult.skip || | ||
(!skipExitTracingResult.allowRootExitSpan && parentSpan && constants.isExitSpan(parentSpan)) || | ||
(!skipExitTracingResult.allowRootExitSpan && !parentSpan) | ||
) { | ||
return original.apply(this, arguments); | ||
@@ -138,0 +149,0 @@ } |
@@ -70,3 +70,3 @@ /* | ||
const wrapExec = execOriginalFn => { | ||
return function instrumentedExecAsPipelineInstana() { | ||
return function instrumentedExecAsMultiInstana() { | ||
return instrumentMultiExec(this, arguments, execOriginalFn, addressUrl, true, false, selfMadeQueue); | ||
@@ -92,2 +92,3 @@ }; | ||
shimmer.wrap(result, 'addCommand', wrapAddCommand); | ||
shimmer.wrap(result, 'exec', wrapExec); | ||
@@ -306,10 +307,19 @@ | ||
function instrumentMultiExec(origCtx, origArgs, original, address, isAtomic, cbStyle, queue) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
const skipExitResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipExitResult.skip) { | ||
return original.apply(origCtx, origArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
const parentSpan = skipExitResult.parentSpan; | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan(exports.spanName, constants.EXIT, parentSpan.t, parentSpan.s); | ||
let span; | ||
if (skipExitResult.allowRootExitSpan) { | ||
span = cls.startSpan(exports.spanName, constants.EXIT); | ||
} else { | ||
span = cls.startSpan(exports.spanName, constants.EXIT, parentSpan.t, parentSpan.s); | ||
} | ||
span.stack = tracingUtil.getStackTrace(instrumentMultiExec); | ||
@@ -316,0 +326,0 @@ span.data.redis = { |
@@ -39,3 +39,3 @@ /* | ||
if (cls.skipExitTracing({ isActive })) { | ||
if (cls.skipExitTracing({ isActive, skipAllowRootExitSpanPresence: true })) { | ||
return originalLog.apply(this, arguments); | ||
@@ -42,0 +42,0 @@ } |
@@ -32,3 +32,3 @@ /* | ||
if (cls.skipExitTracing({ isActive })) { | ||
if (cls.skipExitTracing({ isActive, skipAllowRootExitSpanPresence: true })) { | ||
return originalLog.apply(this, arguments); | ||
@@ -35,0 +35,0 @@ } |
@@ -37,3 +37,3 @@ /* | ||
return function (level) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
if (cls.skipExitTracing({ isActive, skipAllowRootExitSpanPresence: true })) { | ||
return originalLog.apply(this, arguments); | ||
@@ -40,0 +40,0 @@ } |
@@ -38,3 +38,3 @@ /* | ||
return function log(mergingObject, message) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
if (cls.skipExitTracing({ isActive, skipAllowRootExitSpanPresence: true })) { | ||
return originalLoggingFunction.apply(this, arguments); | ||
@@ -41,0 +41,0 @@ } |
@@ -71,3 +71,3 @@ /* | ||
return function (message) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
if (cls.skipExitTracing({ isActive, skipAllowRootExitSpanPresence: true })) { | ||
return originalMethod.apply(this, arguments); | ||
@@ -74,0 +74,0 @@ } |
@@ -57,3 +57,4 @@ /* | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true, skipParentSpanCheck: true }); | ||
const parentSpan = cls.getCurrentSpan(); | ||
const parentSpan = skipTracingResult.parentSpan; | ||
const isExitSpan = skipTracingResult.isExitSpan; | ||
@@ -70,3 +71,3 @@ | ||
// allow rabbitmq parent exit spans, this is actually the span started in instrumentedChannelModelPublish | ||
if (!parentSpan || (isExitSpan && parentSpan.n !== 'rabbitmq')) { | ||
if (!skipTracingResult.allowRootExitSpan && (!parentSpan || (isExitSpan && parentSpan.n !== 'rabbitmq'))) { | ||
return originalSendMessage.apply(ctx, originalArgs); | ||
@@ -73,0 +74,0 @@ } |
@@ -40,3 +40,4 @@ /* | ||
const skipIsTracing = !!repeatableJob; | ||
const parentSpan = cls.getCurrentSpan(); | ||
// We need to skip parentSpan condition because the parentSpan check is too specific in this fn | ||
const skipTracingResult = cls.skipExitTracing({ | ||
@@ -46,5 +47,7 @@ isActive, | ||
skipParentSpanCheck: true, | ||
skipIsTracing | ||
skipIsTracing, | ||
checkReducedSpan: false | ||
}); | ||
// NOTE: it makes sense to skip EXIT span tracing only if skipTracingResult.allowRootExitSpan is not enabled | ||
/** | ||
@@ -57,4 +60,4 @@ * Repeatable jobs cannot be persisted to a parent span, since we don't know for how long they will run. | ||
skipTracingResult.skip || | ||
skipTracingResult.isExitSpan || | ||
(!parentSpan && !repeatableJob) || | ||
(!skipTracingResult.allowRootExitSpan && skipTracingResult.isExitSpan) || | ||
(!skipTracingResult.allowRootExitSpan && !skipTracingResult.parentSpan && !repeatableJob) || | ||
repeatableJobIsSuppressed | ||
@@ -61,0 +64,0 @@ ) { |
@@ -21,3 +21,2 @@ /* | ||
let traceCorrelationEnabled = constants.kafkaTraceCorrelationDefault; | ||
let headerFormat = constants.kafkaHeaderFormatDefault; | ||
@@ -29,5 +28,3 @@ let isActive = false; | ||
hook.onFileLoad(/\/kafkajs\/src\/consumer\/runner\.js/, instrumentConsumer); | ||
hook.onModuleLoad('kafkajs', logWarningForKafkaHeaderFormat); | ||
traceCorrelationEnabled = config.tracing.kafka.traceCorrelation; | ||
headerFormat = config.tracing.kafka.headerFormat; | ||
}; | ||
@@ -37,3 +34,2 @@ | ||
traceCorrelationEnabled = config.tracing.kafka.traceCorrelation; | ||
headerFormat = config.tracing.kafka.headerFormat; | ||
}; | ||
@@ -46,5 +42,2 @@ | ||
} | ||
if (typeof extraConfig.tracing.kafka.headerFormat === 'string') { | ||
headerFormat = extraConfig.tracing.kafka.headerFormat; | ||
} | ||
} | ||
@@ -261,15 +254,2 @@ isActive = true; | ||
} | ||
// Only fall back to legacy binary trace correlation headers if no new header is present. | ||
if (traceId == null && parentSpanId == null && level == null) { | ||
// The newer string header format has not been found, fall back to legacy binary headers. | ||
if (message.headers[constants.kafkaLegacyTraceContextHeaderName]) { | ||
const traceContextBuffer = message.headers[constants.kafkaLegacyTraceContextHeaderName]; | ||
if (Buffer.isBuffer(traceContextBuffer) && traceContextBuffer.length === 24) { | ||
const traceContext = tracingUtil.readTraceContextFromBuffer(traceContextBuffer); | ||
traceId = traceContext.t; | ||
parentSpanId = traceContext.s; | ||
} | ||
} | ||
level = readTraceLevelBinary(message); | ||
} | ||
} | ||
@@ -357,23 +337,2 @@ | ||
if (traceId == null && parentSpanId == null && level == null) { | ||
// The newer string header format has not been found, fall back to legacy binary headers. | ||
for (let msgIdx = 0; msgIdx < batch.messages.length; msgIdx++) { | ||
if ( | ||
batch.messages[msgIdx].headers && | ||
batch.messages[msgIdx].headers[constants.kafkaLegacyTraceContextHeaderName] | ||
) { | ||
const traceContextBuffer = batch.messages[msgIdx].headers[constants.kafkaLegacyTraceContextHeaderName]; | ||
if (Buffer.isBuffer(traceContextBuffer) && traceContextBuffer.length === 24) { | ||
const traceContext = tracingUtil.readTraceContextFromBuffer(traceContextBuffer); | ||
traceId = traceContext.t; | ||
parentSpanId = traceContext.s; | ||
} | ||
} | ||
level = readTraceLevelBinary(batch.messages[msgIdx]); | ||
if (traceId != null || parentSpanId != null || level != null) { | ||
break; | ||
} | ||
} | ||
} | ||
for (let msgIdx = 0; msgIdx < batch.messages.length; msgIdx++) { | ||
@@ -420,12 +379,2 @@ removeInstanaHeadersFromMessage(batch.messages[msgIdx]); | ||
function readTraceLevelBinary(message) { | ||
if (message.headers[constants.kafkaLegacyTraceLevelHeaderName]) { | ||
const traceLevelBuffer = message.headers[constants.kafkaLegacyTraceLevelHeaderName]; | ||
if (Buffer.isBuffer(traceLevelBuffer) && traceLevelBuffer.length >= 1) { | ||
return String(traceLevelBuffer.readInt8()); | ||
} | ||
} | ||
return '1'; | ||
} | ||
function addTraceContextHeaderToAllMessages(messages, span) { | ||
@@ -435,35 +384,7 @@ if (!traceCorrelationEnabled) { | ||
} | ||
switch (headerFormat) { | ||
case 'binary': | ||
addLegacyTraceContextHeaderToAllMessages(messages, span); | ||
break; | ||
case 'string': | ||
addTraceIdSpanIdToAllMessages(messages, span); | ||
break; | ||
case 'both': | ||
// fall through (both is the default) | ||
default: | ||
addLegacyTraceContextHeaderToAllMessages(messages, span); | ||
addTraceIdSpanIdToAllMessages(messages, span); | ||
} | ||
// Add trace ID and span ID headers to all Kafka messages for trace correlation. | ||
// 'string' headers are used by default starting from v4. | ||
addTraceIdSpanIdToAllMessages(messages, span); | ||
} | ||
function addLegacyTraceContextHeaderToAllMessages(messages, span) { | ||
if (Array.isArray(messages)) { | ||
for (let msgIdx = 0; msgIdx < messages.length; msgIdx++) { | ||
if (messages[msgIdx].headers == null) { | ||
messages[msgIdx].headers = { | ||
[constants.kafkaLegacyTraceContextHeaderName]: tracingUtil.renderTraceContextToBuffer(span), | ||
[constants.kafkaLegacyTraceLevelHeaderName]: constants.kafkaLegacyTraceLevelValueInherit | ||
}; | ||
} else if (messages[msgIdx].headers && typeof messages[msgIdx].headers === 'object') { | ||
messages[msgIdx].headers[constants.kafkaLegacyTraceContextHeaderName] = | ||
tracingUtil.renderTraceContextToBuffer(span); | ||
messages[msgIdx].headers[constants.kafkaLegacyTraceLevelHeaderName] = | ||
constants.kafkaLegacyTraceLevelValueInherit; | ||
} | ||
} | ||
} | ||
} | ||
function addTraceIdSpanIdToAllMessages(messages, span) { | ||
@@ -492,32 +413,6 @@ if (Array.isArray(messages)) { | ||
} | ||
switch (headerFormat) { | ||
case 'binary': | ||
addTraceLevelSuppressionToAllMessagesBinary(messages); | ||
break; | ||
case 'string': | ||
addTraceLevelSuppressionToAllMessagesString(messages); | ||
break; | ||
case 'both': | ||
// fall through (both is the default) | ||
default: | ||
addTraceLevelSuppressionToAllMessagesBinary(messages); | ||
addTraceLevelSuppressionToAllMessagesString(messages); | ||
} | ||
// Since v4, only 'string' format is supported by default. | ||
addTraceLevelSuppressionToAllMessagesString(messages); | ||
} | ||
function addTraceLevelSuppressionToAllMessagesBinary(messages) { | ||
if (Array.isArray(messages)) { | ||
for (let msgIdx = 0; msgIdx < messages.length; msgIdx++) { | ||
if (messages[msgIdx].headers == null) { | ||
messages[msgIdx].headers = { | ||
[constants.kafkaLegacyTraceLevelHeaderName]: constants.kafkaLegacyTraceLevelValueSuppressed | ||
}; | ||
} else if (messages[msgIdx].headers && typeof messages[msgIdx].headers === 'object') { | ||
messages[msgIdx].headers[constants.kafkaLegacyTraceLevelHeaderName] = | ||
constants.kafkaLegacyTraceLevelValueSuppressed; | ||
} | ||
} | ||
} | ||
} | ||
function addTraceLevelSuppressionToAllMessagesString(messages) { | ||
@@ -545,11 +440,1 @@ if (Array.isArray(messages)) { | ||
} | ||
// Note: This function can be removed as soon as we finish the Kafka header migration phase2. | ||
// Might happen in major release v4. | ||
function logWarningForKafkaHeaderFormat() { | ||
logger.warn( | ||
'[Deprecation Warning] The configuration option for specifying the Kafka header format will be removed in the ' + | ||
'next major release as the format will no longer be configurable and Instana tracers will only send string ' + | ||
'headers. More details see: https://ibm.biz/kafka-trace-correlation-header.' | ||
); | ||
} |
@@ -15,4 +15,2 @@ /* | ||
const { getFunctionArguments } = require('../../../util/function_arguments'); | ||
let traceCorrelationEnabled = constants.kafkaTraceCorrelationDefault; | ||
let logger; | ||
@@ -23,2 +21,3 @@ logger = require('../../../logger').getLogger('tracing/rdkafka', newLogger => { | ||
let traceCorrelationEnabled = constants.kafkaTraceCorrelationDefault; | ||
let isActive = false; | ||
@@ -30,4 +29,4 @@ | ||
hook.onModuleLoad('node-rdkafka', instrumentConsumer); | ||
hook.onModuleLoad('node-rdkafka', logWarningForKafkaHeaderFormat); | ||
hook.onModuleLoad('kafka-avro', logDeprecationKafkaAvroMessage); | ||
traceCorrelationEnabled = config.tracing.kafka.traceCorrelation; | ||
@@ -46,3 +45,2 @@ }; | ||
} | ||
isActive = true; | ||
@@ -55,13 +53,2 @@ }; | ||
// Note: This function can be removed as soon as we finish the Kafka header migration phase 2 and remove the ability to | ||
// configure the header format. Might happen in major release v4. | ||
function logWarningForKafkaHeaderFormat() { | ||
logger.warn( | ||
'[Deprecation Warning] The Kafka header format configuration will be removed in the next major release. ' + | ||
'Instana tracers will only support string headers, as binary headers are not compatible with node-rdkafka. ' + | ||
'For more information, see the GitHub issue: https://github.com/Blizzard/node-rdkafka/pull/968, and review our ' + | ||
'official documentation on Kafka header configuration: https://ibm.biz/kafka-trace-correlation-header.' | ||
); | ||
} | ||
function instrumentProducer(ProducerClass) { | ||
@@ -320,12 +307,2 @@ shimmer.wrap(ProducerClass.prototype, 'produce', shimProduce); | ||
function readTraceLevelBinary(instanaHeadersAsObject) { | ||
if (instanaHeadersAsObject[constants.kafkaLegacyTraceLevelHeaderName]) { | ||
const traceLevelBuffer = instanaHeadersAsObject[constants.kafkaLegacyTraceLevelHeaderName]; | ||
if (Buffer.isBuffer(traceLevelBuffer) && traceLevelBuffer.length >= 1) { | ||
return String(traceLevelBuffer.readInt8()); | ||
} | ||
} | ||
return '1'; | ||
} | ||
function addTraceContextHeader(headers, span) { | ||
@@ -378,3 +355,3 @@ if (!traceCorrelationEnabled) { | ||
// CASE: Look for the the newer string header format first. | ||
// Since v4, only 'string' format is supported. | ||
if (instanaHeadersAsObject[constants.kafkaTraceIdHeaderName]) { | ||
@@ -395,19 +372,10 @@ traceId = String(instanaHeadersAsObject[constants.kafkaTraceIdHeaderName]); | ||
// CASE: Only fall back to legacy binary trace correlation headers if no new header is present. | ||
if (traceId == null && parentSpanId == null && level == null) { | ||
// The newer string header format has not been found, fall back to legacy binary headers. | ||
if (instanaHeadersAsObject[constants.kafkaLegacyTraceContextHeaderName]) { | ||
const traceContextBuffer = instanaHeadersAsObject[constants.kafkaLegacyTraceContextHeaderName]; | ||
if (Buffer.isBuffer(traceContextBuffer) && traceContextBuffer.length === 24) { | ||
const traceContext = tracingUtil.readTraceContextFromBuffer(traceContextBuffer); | ||
traceId = traceContext.t; | ||
parentSpanId = traceContext.s; | ||
} | ||
} | ||
level = readTraceLevelBinary(instanaHeadersAsObject); | ||
} | ||
return { level, traceId, longTraceId, parentSpanId }; | ||
} | ||
function logDeprecationKafkaAvroMessage() { | ||
logger.warn( | ||
// eslint-disable-next-line max-len | ||
'[Deprecation Warning] The support for kafka-avro library is deprecated and might be removed in the next major release. See https://github.com/waldophotos/kafka-avro/issues/120' | ||
); | ||
} |
@@ -170,6 +170,11 @@ /* | ||
// We pass `fallbackToSharedContext: true` to getCurrentSpan to access the GraphQL query context, which then | ||
// WE DO NOT MAKE USE OF `cls.skipExitTracing` in the graphql instrumentation, | ||
// because we have a special usage of `cls.getReducedSpan(true)`. Feel free to refactor this. | ||
// CASE 1: We pass `fallbackToSharedContext: true` to getCurrentSpan to access the GraphQL query context, which then | ||
// triggered this subscription query. We need to connect them. | ||
// Additionally, if there is no active entry span, we fall back to the reduced span of the most recent entry span. See | ||
// CASE 2: If there is no active entry span, we fall back to the reduced span of the most recent entry span. See | ||
// comment in packages/core/src/tracing/clsHooked/unset.js#storeReducedSpan. | ||
// CASE 3: We can ignore `allowRootExitSpan` is enabled, because subscriptions only work with the | ||
// apollo-server-express and it doesn't make sense to enable `allowRootExitSpan` for this case. | ||
const parentSpan = cls.getCurrentSpan(true) || cls.getReducedSpan(true); | ||
@@ -312,3 +317,5 @@ | ||
} | ||
const activeEntrySpan = cls.getCurrentSpan(); | ||
if (activeEntrySpan && activeEntrySpan.k === constants.ENTRY) { | ||
@@ -315,0 +322,0 @@ // Most of the heavy lifting to trace Apollo Federation gateways (implemented by @apollo/gateway) is done by our |
@@ -67,9 +67,10 @@ /* | ||
let w3cTraceContext = cls.getW3cTraceContext(); | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true, skipParentSpanCheck: true }); | ||
// If there is no active entry span, we fall back to the reduced span of the most recent entry span. See comment in | ||
// packages/core/src/tracing/clsHooked/unset.js#storeReducedSpan. | ||
const parentSpan = cls.getCurrentSpan() || cls.getReducedSpan(); | ||
const skipTracingResult = cls.skipExitTracing({ | ||
isActive, | ||
extendedResponse: true, | ||
checkReducedSpan: true | ||
}); | ||
if (skipTracingResult.skip || !parentSpan || constants.isExitSpan(parentSpan)) { | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
@@ -76,0 +77,0 @@ addTraceLevelHeader(headers, '0', w3cTraceContext); |
@@ -134,8 +134,2 @@ /* | ||
const incomingServiceName = | ||
span.data.http.header && span.data.http.header[constants.serviceNameHeaderNameLowerCase]; | ||
if (incomingServiceName != null) { | ||
span.data.service = incomingServiceName; | ||
} | ||
if (!headers['x-instana-t']) { | ||
@@ -142,0 +136,0 @@ // In cases where we have started a fresh trace (that is, there is no X-INSTANA-T in the incoming request |
@@ -181,16 +181,8 @@ /* | ||
extendedResponse: true, | ||
skipParentSpanCheck: true, | ||
skipIsTracing: true | ||
checkReducedSpan: true | ||
}); | ||
// If there is no active entry span, we fall back to the reduced span of the most recent entry span. See comment in | ||
// packages/core/src/tracing/clsHooked/unset.js#storeReducedSpan. | ||
const parentSpan = cls.getCurrentSpan() || cls.getReducedSpan(); | ||
const parentSpan = skipTracingResult.parentSpan; | ||
if ( | ||
skipTracingResult.skip || | ||
!parentSpan || | ||
constants.isExitSpan(parentSpan) || | ||
shouldBeBypassed(parentSpan, options) | ||
) { | ||
if (skipTracingResult.skip || shouldBeBypassed(skipTracingResult.parentSpan, options)) { | ||
let traceLevelHeaderHasBeenAdded = false; | ||
@@ -211,3 +203,4 @@ if (skipTracingResult.suppressed) { | ||
cls.ns.run(() => { | ||
const span = cls.startSpan('node.http.client', constants.EXIT, parentSpan.t, parentSpan.s); | ||
// NOTE: Check for parentSpan existence, because of allowRootExitSpan is being enabled | ||
const span = cls.startSpan('node.http.client', constants.EXIT, parentSpan?.t, parentSpan?.s); | ||
@@ -214,0 +207,0 @@ // startSpan updates the W3C trace context and writes it back to CLS, so we have to refetch the updated context |
@@ -107,8 +107,2 @@ /* | ||
const incomingServiceName = | ||
span.data.http.header && span.data.http.header[constants.serviceNameHeaderNameLowerCase]; | ||
if (incomingServiceName != null) { | ||
span.data.service = incomingServiceName; | ||
} | ||
if (!req.headers['x-instana-t']) { | ||
@@ -115,0 +109,0 @@ // In cases where we have started a fresh trace (that is, there is no X-INSTANA-T in the incoming request |
@@ -86,9 +86,6 @@ /* | ||
extendedResponse: true, | ||
skipParentSpanCheck: true, | ||
skipIsTracing: true | ||
checkReducedSpan: true | ||
}); | ||
// If there is no active entry span, we fall back to the reduced span of the most recent entry span. See comment in | ||
// packages/core/src/tracing/clsHooked/unset.js#storeReducedSpan. | ||
const parentSpan = cls.getCurrentSpan() || cls.getReducedSpan(); | ||
const parentSpan = skipTracingResult.parentSpan; | ||
@@ -101,6 +98,8 @@ const originalThis = this; | ||
if (skipTracingResult.skip || !parentSpan || constants.isExitSpan(parentSpan)) { | ||
// If allowRootExitSpan is not enabled, then an exit span can't be traced alone | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
injectSuppressionHeader(originalArgs, w3cTraceContext); | ||
} | ||
return originalFetch.apply(originalThis, originalArgs); | ||
@@ -110,3 +109,4 @@ } | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan('node.http.client', constants.EXIT, parentSpan.t, parentSpan.s); | ||
// NOTE: Check for parentSpan existence, because of allowRootExitSpan is being enabled | ||
const span = cls.startSpan('node.http.client', constants.EXIT, parentSpan?.t, parentSpan?.s); | ||
@@ -113,0 +113,0 @@ // startSpan updates the W3C trace context and writes it back to CLS, so we have to refetch the updated context |
@@ -8,3 +8,2 @@ /* | ||
const semver = require('semver'); | ||
const { AsyncHooksContextManager } = require('@opentelemetry/context-async-hooks'); | ||
@@ -14,2 +13,3 @@ const api = require('@opentelemetry/api'); | ||
const constants = require('../constants'); | ||
const supportedVersion = require('../supportedVersion'); | ||
@@ -28,4 +28,2 @@ // NOTE: Please refrain from utilizing third-party instrumentations. | ||
module.exports.minimumNodeJsVersion = '14.0.0'; | ||
// NOTE: using a logger might create a recursive execution | ||
@@ -35,5 +33,3 @@ // logger.debug -> creates fs call -> calls transformToInstanaSpan -> calls logger.debug | ||
module.exports.init = (_config, cls) => { | ||
// CASE: otel offically does not support Node < 14 | ||
// https://github.com/open-telemetry/opentelemetry-js/tree/main#supported-runtimes | ||
if (semver.lt(process.versions.node, module.exports.minimumNodeJsVersion)) { | ||
if (!supportedVersion(process.versions.node)) { | ||
return; | ||
@@ -40,0 +36,0 @@ } |
@@ -9,2 +9,3 @@ /* | ||
const semver = require('semver'); | ||
const { minimumNodeJsVersion } = require('../util/nodeJsVersionCheck'); | ||
@@ -14,3 +15,3 @@ /** @type {(version: string) => boolean} */ | ||
const includePrerelease = process.env.NODE_ENV === 'test'; | ||
return semver.satisfies(version, '>=14.0.0', { includePrerelease }); | ||
return semver.satisfies(version, `>=${minimumNodeJsVersion}`, { includePrerelease }); | ||
}; |
@@ -10,11 +10,2 @@ /* | ||
/** | ||
* Check if the given Node.js version supports ESM. | ||
* @param {string} version - The Node.js version to check. | ||
* @returns {boolean} - True if ESM is supported, false otherwise. | ||
*/ | ||
exports.esmSupportedVersion = function esmSupportedVersion(version) { | ||
return semver.gte(version, '14.0.0'); | ||
}; | ||
/** | ||
* Check if the given Node.js version is the latest version that supports ESM. | ||
@@ -21,0 +12,0 @@ * @param {string} version - The Node.js version to check. |
@@ -22,3 +22,3 @@ /* | ||
* | ||
* Note: In the next major release (4.x), we plan to transition all CJS modules in ESM applications to be | ||
* Note: In the next major release, we might transition all CJS modules in ESM applications to be | ||
* supported with iitmHook. For now, this approach is chosen to minimize risk. | ||
@@ -25,0 +25,0 @@ */ |
@@ -11,3 +11,2 @@ /* | ||
atMostOnce: require('./atMostOnce'), | ||
buffer: require('./buffer'), | ||
clone: require('./clone'), | ||
@@ -14,0 +13,0 @@ compression: require('./compression'), |
@@ -72,4 +72,3 @@ /* | ||
/\/request\/index.js/, | ||
/\/@apollo\/federation\/dist\//, | ||
/\/q\/q.js/ | ||
/\/@apollo\/federation\/dist\// | ||
]; | ||
@@ -76,0 +75,0 @@ |
@@ -10,3 +10,3 @@ /* | ||
*/ | ||
exports.minimumNodeJsVersion = 14; | ||
exports.minimumNodeJsVersion = 18; | ||
@@ -13,0 +13,0 @@ /** |
@@ -29,2 +29,3 @@ /* | ||
* @property {KafkaTracingOptions} [kafka] | ||
* @property {boolean} [allowRootExitSpan] | ||
*/ | ||
@@ -40,3 +41,2 @@ | ||
* @property {boolean} [traceCorrelation] | ||
* @property {import('../tracing/constants').KafkaTraceCorrelationFormat} [headerFormat] | ||
*/ | ||
@@ -86,3 +86,2 @@ | ||
* @property {boolean} [traceCorrelation] | ||
* @property {string} [headerFormat] | ||
*/ | ||
@@ -109,2 +108,3 @@ | ||
useOpentelemetry: true, | ||
allowRootExitSpan: false, | ||
automaticTracingEnabled: true, | ||
@@ -123,4 +123,3 @@ activateImmediately: false, | ||
kafka: { | ||
traceCorrelation: true, | ||
headerFormat: constants.kafkaHeaderFormatDefault | ||
traceCorrelation: true | ||
} | ||
@@ -134,4 +133,2 @@ }, | ||
const validKafkaHeaderFormats = ['binary', 'string', 'both']; | ||
const validSecretsMatcherModes = ['equals-ignore-case', 'equals', 'contains-ignore-case', 'contains', 'regex', 'none']; | ||
@@ -229,2 +226,3 @@ | ||
normalizeTracingKafka(config); | ||
normalizeAllowRootExitSpan(config); | ||
} | ||
@@ -257,2 +255,24 @@ | ||
*/ | ||
function normalizeAllowRootExitSpan(config) { | ||
if (config.tracing.allowRootExitSpan === false) { | ||
return; | ||
} | ||
if (config.tracing.allowRootExitSpan === true) { | ||
return; | ||
} | ||
const INSTANA_ALLOW_ROOT_EXIT_SPAN = process.env['INSTANA_ALLOW_ROOT_EXIT_SPAN']?.toLowerCase(); | ||
config.tracing.allowRootExitSpan = | ||
INSTANA_ALLOW_ROOT_EXIT_SPAN === '1' || | ||
INSTANA_ALLOW_ROOT_EXIT_SPAN === 'true' || | ||
defaults.tracing.allowRootExitSpan; | ||
return; | ||
} | ||
/** | ||
* | ||
* @param {InstanaConfig} config | ||
*/ | ||
function normalizeUseOpentelemetry(config) { | ||
@@ -559,29 +579,2 @@ if (config.tracing.useOpentelemetry === false) { | ||
} | ||
// @ts-ignore | ||
config.tracing.kafka.headerFormat = | ||
config.tracing.kafka.headerFormat || process.env.INSTANA_KAFKA_HEADER_FORMAT || defaults.tracing.kafka.headerFormat; | ||
if (typeof config.tracing.kafka.headerFormat !== 'string') { | ||
logger.warn( | ||
`The value of config.tracing.kafka.headerFormat ("${config.tracing.kafka.headerFormat}") is not a string. ` + | ||
`Assuming the default value "${defaults.tracing.kafka.headerFormat}".` | ||
); | ||
config.tracing.kafka.headerFormat = defaults.tracing.kafka.headerFormat; | ||
return; | ||
} | ||
// @ts-ignore | ||
config.tracing.kafka.headerFormat = config.tracing.kafka.headerFormat.toLowerCase(); | ||
if (validKafkaHeaderFormats.indexOf(config.tracing.kafka.headerFormat) < 0) { | ||
logger.warn( | ||
'The value of config.tracing.kafka.headerFormat (or the value of INSTANA_KAFKA_HEADER_FORMAT) ' + | ||
`("${config.tracing.kafka.headerFormat}") is not a supported header format. Assuming the default ` + | ||
`value "${defaults.tracing.kafka.headerFormat}".` | ||
); | ||
config.tracing.kafka.headerFormat = defaults.tracing.kafka.headerFormat; | ||
return; | ||
} | ||
if (config.tracing.kafka.headerFormat !== defaults.tracing.kafka.headerFormat) { | ||
logger.info(`Kafka trace correlation header format has been set to "${config.tracing.kafka.headerFormat}".`); | ||
} | ||
} | ||
@@ -588,0 +581,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
54
788094
139
20050