From 4464e66276f1421d12e02fea91373d3b631ee7a3 Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Fri, 22 Nov 2024 12:18:49 +0100 Subject: [PATCH 1/8] Remove iast-log and review ASM log messages (#4919) * Remove iast-log and review ASM log messages * Update packages/dd-trace/src/appsec/iast/iast-plugin.js Co-authored-by: Ugaitz Urien * Update packages/dd-trace/src/appsec/rasp/fs-plugin.js Co-authored-by: Carles Capell <107924659+CarlesDD@users.noreply.github.com> * remove template literal --------- Co-authored-by: Ugaitz Urien Co-authored-by: Carles Capell <107924659+CarlesDD@users.noreply.github.com> --- .../src/appsec/api_security_sampler.js | 2 +- packages/dd-trace/src/appsec/blocking.js | 2 +- .../appsec/iast/analyzers/cookie-analyzer.js | 4 +- packages/dd-trace/src/appsec/iast/iast-log.js | 86 ---------------- .../dd-trace/src/appsec/iast/iast-plugin.js | 8 +- .../taint-tracking/operations-taint-object.js | 4 +- .../appsec/iast/taint-tracking/rewriter.js | 13 +-- .../taint-tracking/taint-tracking-impl.js | 18 ++-- .../src/appsec/iast/telemetry/namespaces.js | 5 +- .../command-sensitive-analyzer.js | 4 +- .../ldap-sensitive-analyzer.js | 4 +- .../sql-sensitive-analyzer.js | 4 +- .../url-sensitive-analyzer.js | 4 +- .../evidence-redaction/sensitive-handler.js | 6 +- packages/dd-trace/src/appsec/index.js | 5 +- packages/dd-trace/src/appsec/passport.js | 2 +- .../dd-trace/src/appsec/rasp/fs-plugin.js | 4 +- packages/dd-trace/src/appsec/rasp/utils.js | 2 +- .../src/appsec/remote_config/manager.js | 4 +- packages/dd-trace/src/appsec/sdk/set_user.js | 4 +- .../dd-trace/src/appsec/sdk/track_event.js | 10 +- .../dd-trace/src/appsec/sdk/user_blocking.js | 8 +- packages/dd-trace/src/appsec/waf/index.js | 4 +- .../src/appsec/waf/waf_context_wrapper.js | 5 +- .../dd-trace/src/appsec/waf/waf_manager.js | 2 +- .../dd-trace/test/appsec/blocking.spec.js | 2 +- .../analyzers/sql-injection-analyzer.spec.js | 6 +- .../test/appsec/iast/iast-log.spec.js | 98 ------------------- .../test/appsec/iast/iast-plugin.spec.js | 8 +- .../taint-tracking-operations.spec.js | 10 +- .../sensitive-handler.spec.js | 14 +-- packages/dd-trace/test/appsec/index.spec.js | 6 +- .../dd-trace/test/appsec/passport.spec.js | 6 +- .../test/appsec/remote_config/manager.spec.js | 7 +- .../dd-trace/test/appsec/sdk/set_user.spec.js | 6 +- .../test/appsec/sdk/track_event.spec.js | 24 +++-- .../test/appsec/sdk/user_blocking.spec.js | 11 ++- .../appsec/waf/waf_context_wrapper.spec.js | 2 +- 38 files changed, 112 insertions(+), 302 deletions(-) delete mode 100644 packages/dd-trace/src/appsec/iast/iast-log.js delete mode 100644 packages/dd-trace/test/appsec/iast/iast-log.spec.js diff --git a/packages/dd-trace/src/appsec/api_security_sampler.js b/packages/dd-trace/src/appsec/api_security_sampler.js index c95ec820f1c..1e15b67a260 100644 --- a/packages/dd-trace/src/appsec/api_security_sampler.js +++ b/packages/dd-trace/src/appsec/api_security_sampler.js @@ -64,7 +64,7 @@ function computeKey (req, res) { const status = res.statusCode if (!method || !status) { - log.warn('Unsupported groupkey for API security') + log.warn('[ASM] Unsupported groupkey for API security') return null } return method + route + status diff --git a/packages/dd-trace/src/appsec/blocking.js b/packages/dd-trace/src/appsec/blocking.js index cdf92f7023a..d831b310eb3 100644 --- a/packages/dd-trace/src/appsec/blocking.js +++ b/packages/dd-trace/src/appsec/blocking.js @@ -101,7 +101,7 @@ function getBlockingData (req, specificType, actionParameters) { function block (req, res, rootSpan, abortController, actionParameters = defaultBlockingActionParameters) { if (res.headersSent) { - log.warn('Cannot send blocking response when headers have already been sent') + log.warn('[ASM] Cannot send blocking response when headers have already been sent') return } diff --git a/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js b/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js index 2b125b88403..a898a0a379c 100644 --- a/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js @@ -2,7 +2,7 @@ const Analyzer = require('./vulnerability-analyzer') const { getNodeModulesPaths } = require('../path-line') -const iastLog = require('../iast-log') +const log = require('../../../log') const EXCLUDED_PATHS = getNodeModulesPaths('express/lib/response.js') @@ -16,7 +16,7 @@ class CookieAnalyzer extends Analyzer { try { this.cookieFilterRegExp = new RegExp(config.iast.cookieFilterPattern) } catch { - iastLog.error('Invalid regex in cookieFilterPattern') + log.error('[ASM] Invalid regex in cookieFilterPattern') this.cookieFilterRegExp = /.{32,}/ } diff --git a/packages/dd-trace/src/appsec/iast/iast-log.js b/packages/dd-trace/src/appsec/iast/iast-log.js deleted file mode 100644 index c126729f965..00000000000 --- a/packages/dd-trace/src/appsec/iast/iast-log.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict' - -const dc = require('dc-polyfill') -const log = require('../../log') - -const telemetryLog = dc.channel('datadog:telemetry:log') - -function getTelemetryLog (data, level) { - try { - data = typeof data === 'function' ? data() : data - - let message - if (typeof data !== 'object' || !data) { - message = String(data) - } else { - message = String(data.message || data) - } - - const logEntry = { - message, - level - } - if (data.stack) { - logEntry.stack_trace = data.stack - } - return logEntry - } catch (e) { - log.error(e) - } -} - -const iastLog = { - debug (data) { - log.debug(data) - return this - }, - - info (data) { - log.info(data) - return this - }, - - warn (data) { - log.warn(data) - return this - }, - - error (data) { - log.error(data) - return this - }, - - publish (data, level) { - if (telemetryLog.hasSubscribers) { - telemetryLog.publish(getTelemetryLog(data, level)) - } - return this - }, - - debugAndPublish (data) { - this.debug(data) - return this.publish(data, 'DEBUG') - }, - - /** - * forward 'INFO' log level to 'DEBUG' telemetry log level - * see also {@link ../../telemetry/logs#isLevelEnabled } method - */ - infoAndPublish (data) { - this.info(data) - return this.publish(data, 'DEBUG') - }, - - warnAndPublish (data) { - this.warn(data) - return this.publish(data, 'WARN') - }, - - errorAndPublish (data) { - this.error(data) - // publish is done automatically by log.error() - return this - } -} - -module.exports = iastLog diff --git a/packages/dd-trace/src/appsec/iast/iast-plugin.js b/packages/dd-trace/src/appsec/iast/iast-plugin.js index 5eb6e00410d..9c728a189b0 100644 --- a/packages/dd-trace/src/appsec/iast/iast-plugin.js +++ b/packages/dd-trace/src/appsec/iast/iast-plugin.js @@ -2,7 +2,6 @@ const { channel } = require('dc-polyfill') -const iastLog = require('./iast-log') const Plugin = require('../../plugins/plugin') const iastTelemetry = require('./telemetry') const { getInstrumentedMetric, getExecutedMetric, TagKey, EXECUTED_SOURCE, formatTags } = @@ -10,6 +9,7 @@ const { getInstrumentedMetric, getExecutedMetric, TagKey, EXECUTED_SOURCE, forma const { storage } = require('../../../../datadog-core') const { getIastContext } = require('./iast-context') const instrumentations = require('../../../../datadog-instrumentations/src/helpers/instrumentations') +const log = require('../../log') /** * Used by vulnerability sources and sinks to subscribe diagnostic channel events @@ -65,7 +65,7 @@ class IastPlugin extends Plugin { try { handler(message, name) } catch (e) { - iastLog.errorAndPublish(e) + log.error('[ASM] Error executing IAST plugin handler', e) } } } @@ -76,7 +76,7 @@ class IastPlugin extends Plugin { const iastContext = getIastContext(storage.getStore()) iastSub.increaseExecuted(iastContext) } catch (e) { - iastLog.errorAndPublish(e) + log.error('[ASM] Error increasing handler executed metrics', e) } } } @@ -93,7 +93,7 @@ class IastPlugin extends Plugin { } return result } catch (e) { - iastLog.errorAndPublish(e) + log.error('[ASM] Error executing handler or increasing metrics', e) } } diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js b/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js index f678767394a..d8580061b9e 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js @@ -2,7 +2,7 @@ const TaintedUtils = require('@datadog/native-iast-taint-tracking') const { IAST_TRANSACTION_ID } = require('../iast-context') -const iastLog = require('../iast-log') +const log = require('../../../log') function taintObject (iastContext, object, type) { let result = object @@ -33,7 +33,7 @@ function taintObject (iastContext, object, type) { } } } catch (e) { - iastLog.error(`Error visiting property : ${property}`).errorAndPublish(e) + log.error('[ASM] Error in taintObject when visiting property : %s', property, e) } } } diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js index cad8e5d6b18..168408d5261 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js @@ -2,12 +2,12 @@ const Module = require('module') const shimmer = require('../../../../../datadog-shimmer') -const iastLog = require('../iast-log') const { isPrivateModule, isNotLibraryFile } = require('./filter') const { csiMethods } = require('./csi-methods') const { getName } = require('../telemetry/verbosity') const { getRewriteFunction } = require('./rewriter-telemetry') const dc = require('dc-polyfill') +const log = require('../../../log') const hardcodedSecretCh = dc.channel('datadog:secrets:result') let rewriter @@ -60,8 +60,7 @@ function getRewriter (telemetryVerbosity) { chainSourceMap }) } catch (e) { - iastLog.error('Unable to initialize TaintTracking Rewriter') - .errorAndPublish(e) + log.error('[ASM] Unable to initialize TaintTracking Rewriter', e) } } return rewriter @@ -99,8 +98,7 @@ function getCompileMethodFn (compileMethod) { } } } catch (e) { - iastLog.error(`Error rewriting ${filename}`) - .errorAndPublish(e) + log.error('[ASM] Error rewriting file %s', filename, e) } return compileMethod.apply(this, [content, filename]) } @@ -117,8 +115,7 @@ function enableRewriter (telemetryVerbosity) { shimmer.wrap(Module.prototype, '_compile', compileMethod => getCompileMethodFn(compileMethod)) } } catch (e) { - iastLog.error('Error enabling TaintTracking Rewriter') - .errorAndPublish(e) + log.error('[ASM] Error enabling TaintTracking Rewriter', e) } } @@ -132,7 +129,7 @@ function disableRewriter () { Error.prepareStackTrace = originalPrepareStackTrace } catch (e) { - iastLog.warn(e) + log.warn('[ASM] Error disabling TaintTracking rewriter', e) } } diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js b/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js index 5fa16d00d77..6b1554d6449 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js @@ -4,10 +4,10 @@ const dc = require('dc-polyfill') const TaintedUtils = require('@datadog/native-iast-taint-tracking') const { storage } = require('../../../../../datadog-core') const iastContextFunctions = require('../iast-context') -const iastLog = require('../iast-log') const { EXECUTED_PROPAGATION } = require('../telemetry/iast-metric') const { isDebugAllowed } = require('../telemetry/verbosity') const { taintObject } = require('./operations-taint-object') +const log = require('../../../log') const mathRandomCallCh = dc.channel('datadog:random:call') const evalCallCh = dc.channel('datadog:eval:call') @@ -60,8 +60,7 @@ function getFilteredCsiFn (cb, filter, getContext) { return cb(transactionId, res, target, ...rest) } } catch (e) { - iastLog.error(`Error invoking CSI ${target}`) - .errorAndPublish(e) + log.error('[ASM] Error invoking CSI %s', target, e) } return res } @@ -112,8 +111,7 @@ function csiMethodsOverrides (getContext) { return TaintedUtils.concat(transactionId, res, op1, op2) } } catch (e) { - iastLog.error('Error invoking CSI plusOperator') - .errorAndPublish(e) + log.error('[ASM] Error invoking CSI plusOperator', e) } return res }, @@ -126,8 +124,7 @@ function csiMethodsOverrides (getContext) { return TaintedUtils.concat(transactionId, res, ...rest) } } catch (e) { - iastLog.error('Error invoking CSI tplOperator') - .errorAndPublish(e) + log.error('[ASM] Error invoking CSI tplOperator', e) } return res }, @@ -178,7 +175,7 @@ function csiMethodsOverrides (getContext) { } } } catch (e) { - iastLog.error(e) + log.error('[ASM] Error invoking CSI JSON.parse', e) } } @@ -194,7 +191,7 @@ function csiMethodsOverrides (getContext) { res = TaintedUtils.arrayJoin(transactionId, res, target, separator) } } catch (e) { - iastLog.error(e) + log.error('[ASM] Error invoking CSI join', e) } } @@ -250,8 +247,7 @@ function lodashTaintTrackingHandler (message) { message.result = getLodashTaintedUtilFn(message.operation)(transactionId, message.result, ...message.arguments) } } catch (e) { - iastLog.error(`Error invoking CSI lodash ${message.operation}`) - .errorAndPublish(e) + log.error('[ASM] Error invoking CSI lodash %s', message.operation, e) } } diff --git a/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js b/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js index 77a0db04604..de460270405 100644 --- a/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +++ b/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js @@ -4,7 +4,6 @@ const log = require('../../../log') const { Namespace } = require('../../../telemetry/metrics') const { addMetricsToSpan } = require('./span-tags') const { IAST_TRACE_METRIC_PREFIX } = require('../tags') -const iastLog = require('../iast-log') const DD_IAST_METRICS_NAMESPACE = Symbol('_dd.iast.request.metrics.namespace') @@ -31,7 +30,7 @@ function finalizeRequestNamespace (context, rootSpan) { namespace.clear() } catch (e) { - log.error(e) + log.error('[ASM] Error merging request metrics', e) } finally { if (context) { delete context[DD_IAST_METRICS_NAMESPACE] @@ -79,7 +78,7 @@ class IastNamespace extends Namespace { if (metrics.size === this.maxMetricTagsSize) { metrics.clear() - iastLog.warnAndPublish(`Tags cache max size reached for metric ${name}`) + log.error('[ASM] Tags cache max size reached for metric %s', name) } metrics.set(tags, metric) diff --git a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js index abf341a1a1f..eb9e550b00e 100644 --- a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js @@ -1,6 +1,6 @@ 'use strict' -const iastLog = require('../../../iast-log') +const log = require('../../../../../log') const COMMAND_PATTERN = '^(?:\\s*(?:sudo|doas)\\s+)?\\b\\S+\\b\\s(.*)' const pattern = new RegExp(COMMAND_PATTERN, 'gmi') @@ -16,7 +16,7 @@ module.exports = function extractSensitiveRanges (evidence) { return [{ start, end }] } } catch (e) { - iastLog.debug(e) + log.debug('[ASM] Error extracting sensitive ranges', e) } return [] } diff --git a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js index 93497465afe..cb14b2816f8 100644 --- a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js @@ -1,6 +1,6 @@ 'use strict' -const iastLog = require('../../../iast-log') +const log = require('../../../../../log') const LDAP_PATTERN = '\\(.*?(?:~=|=|<=|>=)(?[^)]+)\\)' const pattern = new RegExp(LDAP_PATTERN, 'gmi') @@ -22,7 +22,7 @@ module.exports = function extractSensitiveRanges (evidence) { } return tokens } catch (e) { - iastLog.debug(e) + log.debug('[ASM] Error extracting sensitive ranges', e) } return [] } diff --git a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js index 15580b11869..0a3a389fd60 100644 --- a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js @@ -1,6 +1,6 @@ 'use strict' -const iastLog = require('../../../iast-log') +const log = require('../../../../../log') const STRING_LITERAL = '\'(?:\'\'|[^\'])*\'' const POSTGRESQL_ESCAPED_LITERAL = '\\$([^$]*)\\$.*?\\$\\1\\$' @@ -106,7 +106,7 @@ module.exports = function extractSensitiveRanges (evidence) { } return tokens } catch (e) { - iastLog.debug(e) + log.debug('[ASM] Error extracting sensitive ranges', e) } return [] } diff --git a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js index 6f43008d2c3..e945ed62539 100644 --- a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js @@ -1,6 +1,6 @@ 'use strict' -const iastLog = require('../../../iast-log') +const log = require('../../../../../log') const AUTHORITY = '^(?:[^:]+:)?//([^@]+)@' const QUERY_FRAGMENT = '[?#&]([^=&;]+)=([^?#&]+)' @@ -33,7 +33,7 @@ module.exports = function extractSensitiveRanges (evidence) { return ranges } catch (e) { - iastLog.debug(e) + log.debug('[ASM] Error extracting sensitive ranges', e) } return [] diff --git a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js index 13716aea1db..9c6c48dbf54 100644 --- a/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +++ b/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js @@ -1,6 +1,6 @@ 'use strict' -const iastLog = require('../../iast-log') +const log = require('../../../../log') const vulnerabilities = require('../../vulnerabilities') const { contains, intersects, remove } = require('./range-utils') @@ -282,7 +282,7 @@ class SensitiveHandler { try { this._namePattern = new RegExp(redactionNamePattern, 'gmi') } catch (e) { - iastLog.warn('Redaction name pattern is not valid') + log.warn('[ASM] Redaction name pattern is not valid') } } @@ -290,7 +290,7 @@ class SensitiveHandler { try { this._valuePattern = new RegExp(redactionValuePattern, 'gmi') } catch (e) { - iastLog.warn('Redaction value pattern is not valid') + log.warn('[ASM] Redaction value pattern is not valid') } } } diff --git a/packages/dd-trace/src/appsec/index.js b/packages/dd-trace/src/appsec/index.js index 0a4f6fbb992..be5273f815f 100644 --- a/packages/dd-trace/src/appsec/index.js +++ b/packages/dd-trace/src/appsec/index.js @@ -78,8 +78,7 @@ function enable (_config) { isEnabled = true config = _config } catch (err) { - log.error('Unable to start AppSec') - log.error(err) + log.error('[ASM] Unable to start AppSec', err) disable() } @@ -186,7 +185,7 @@ function onPassportVerify ({ credentials, user }) { const rootSpan = store?.req && web.root(store.req) if (!rootSpan) { - log.warn('No rootSpan found in onPassportVerify') + log.warn('[ASM] No rootSpan found in onPassportVerify') return } diff --git a/packages/dd-trace/src/appsec/passport.js b/packages/dd-trace/src/appsec/passport.js index 2093b7b1fdc..0cbcb4b51bc 100644 --- a/packages/dd-trace/src/appsec/passport.js +++ b/packages/dd-trace/src/appsec/passport.js @@ -86,7 +86,7 @@ function passportTrackEvent (credentials, passportUser, rootSpan, mode) { const user = parseUser(getLogin(credentials), passportUser, mode) if (user['usr.id'] === undefined) { - log.warn('No user ID found in authentication instrumentation') + log.warn('[ASM] No user ID found in authentication instrumentation') return } diff --git a/packages/dd-trace/src/appsec/rasp/fs-plugin.js b/packages/dd-trace/src/appsec/rasp/fs-plugin.js index a283b4f1a61..71f9cf3c6b5 100644 --- a/packages/dd-trace/src/appsec/rasp/fs-plugin.js +++ b/packages/dd-trace/src/appsec/rasp/fs-plugin.js @@ -70,7 +70,7 @@ function enable (mod) { fsPlugin.enable() } - log.info(`Enabled AppsecFsPlugin for ${mod}`) + log.info('[ASM] Enabled AppsecFsPlugin for %s', mod) } function disable (mod) { @@ -85,7 +85,7 @@ function disable (mod) { fsPlugin = undefined } - log.info(`Disabled AppsecFsPlugin for ${mod}`) + log.info('[ASM] Disabled AppsecFsPlugin for %s', mod) } module.exports = { diff --git a/packages/dd-trace/src/appsec/rasp/utils.js b/packages/dd-trace/src/appsec/rasp/utils.js index bdf3596209e..a454a71b8c6 100644 --- a/packages/dd-trace/src/appsec/rasp/utils.js +++ b/packages/dd-trace/src/appsec/rasp/utils.js @@ -8,7 +8,7 @@ const log = require('../../log') const abortOnUncaughtException = process.execArgv?.includes('--abort-on-uncaught-exception') if (abortOnUncaughtException) { - log.warn('The --abort-on-uncaught-exception flag is enabled. The RASP module will not block operations.') + log.warn('[ASM] The --abort-on-uncaught-exception flag is enabled. The RASP module will not block operations.') } const RULE_TYPES = { diff --git a/packages/dd-trace/src/appsec/remote_config/manager.js b/packages/dd-trace/src/appsec/remote_config/manager.js index 8f2aa44cea2..75c72690503 100644 --- a/packages/dd-trace/src/appsec/remote_config/manager.js +++ b/packages/dd-trace/src/appsec/remote_config/manager.js @@ -134,7 +134,7 @@ class RemoteConfigManager extends EventEmitter { if (statusCode === 404) return cb() if (err) { - log.error(err) + log.error('[RC] Error in request', err) return cb() } @@ -148,7 +148,7 @@ class RemoteConfigManager extends EventEmitter { try { this.parseConfig(JSON.parse(data)) } catch (err) { - log.error(`Could not parse remote config response: ${err}`) + log.error('[RC] Could not parse remote config response', err) this.state.client.state.has_error = true this.state.client.state.error = err.toString() diff --git a/packages/dd-trace/src/appsec/sdk/set_user.js b/packages/dd-trace/src/appsec/sdk/set_user.js index 81b0e3ec7ad..6efe44ebd41 100644 --- a/packages/dd-trace/src/appsec/sdk/set_user.js +++ b/packages/dd-trace/src/appsec/sdk/set_user.js @@ -11,13 +11,13 @@ function setUserTags (user, rootSpan) { function setUser (tracer, user) { if (!user || !user.id) { - log.warn('Invalid user provided to setUser') + log.warn('[ASM] Invalid user provided to setUser') return } const rootSpan = getRootSpan(tracer) if (!rootSpan) { - log.warn('Root span not available in setUser') + log.warn('[ASM] Root span not available in setUser') return } diff --git a/packages/dd-trace/src/appsec/sdk/track_event.js b/packages/dd-trace/src/appsec/sdk/track_event.js index e95081314de..0c1ef9c2bd9 100644 --- a/packages/dd-trace/src/appsec/sdk/track_event.js +++ b/packages/dd-trace/src/appsec/sdk/track_event.js @@ -11,13 +11,13 @@ const { keepTrace } = require('../../priority_sampler') function trackUserLoginSuccessEvent (tracer, user, metadata) { // TODO: better user check here and in _setUser() ? if (!user || !user.id) { - log.warn('Invalid user provided to trackUserLoginSuccessEvent') + log.warn('[ASM] Invalid user provided to trackUserLoginSuccessEvent') return } const rootSpan = getRootSpan(tracer) if (!rootSpan) { - log.warn('Root span not available in trackUserLoginSuccessEvent') + log.warn('[ASM] Root span not available in trackUserLoginSuccessEvent') return } @@ -28,7 +28,7 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) { function trackUserLoginFailureEvent (tracer, userId, exists, metadata) { if (!userId || typeof userId !== 'string') { - log.warn('Invalid userId provided to trackUserLoginFailureEvent') + log.warn('[ASM] Invalid userId provided to trackUserLoginFailureEvent') return } @@ -43,7 +43,7 @@ function trackUserLoginFailureEvent (tracer, userId, exists, metadata) { function trackCustomEvent (tracer, eventName, metadata) { if (!eventName || typeof eventName !== 'string') { - log.warn('Invalid eventName provided to trackCustomEvent') + log.warn('[ASM] Invalid eventName provided to trackCustomEvent') return } @@ -52,7 +52,7 @@ function trackCustomEvent (tracer, eventName, metadata) { function trackEvent (eventName, fields, sdkMethodName, rootSpan, mode) { if (!rootSpan) { - log.warn(`Root span not available in ${sdkMethodName}`) + log.warn('[ASM] Root span not available in %s', sdkMethodName) return } diff --git a/packages/dd-trace/src/appsec/sdk/user_blocking.js b/packages/dd-trace/src/appsec/sdk/user_blocking.js index 19997d3ff9c..8af54ccbec1 100644 --- a/packages/dd-trace/src/appsec/sdk/user_blocking.js +++ b/packages/dd-trace/src/appsec/sdk/user_blocking.js @@ -15,7 +15,7 @@ function isUserBlocked (user) { function checkUserAndSetUser (tracer, user) { if (!user || !user.id) { - log.warn('Invalid user provided to isUserBlocked') + log.warn('[ASM] Invalid user provided to isUserBlocked') return false } @@ -25,7 +25,7 @@ function checkUserAndSetUser (tracer, user) { setUserTags(user, rootSpan) } } else { - log.warn('Root span not available in isUserBlocked') + log.warn('[ASM] Root span not available in isUserBlocked') } return isUserBlocked(user) @@ -41,13 +41,13 @@ function blockRequest (tracer, req, res) { } if (!req || !res) { - log.warn('Requests or response object not available in blockRequest') + log.warn('[ASM] Requests or response object not available in blockRequest') return false } const rootSpan = getRootSpan(tracer) if (!rootSpan) { - log.warn('Root span not available in blockRequest') + log.warn('[ASM] Root span not available in blockRequest') return false } diff --git a/packages/dd-trace/src/appsec/waf/index.js b/packages/dd-trace/src/appsec/waf/index.js index 8aa30fabbb4..3b2bc9e2a13 100644 --- a/packages/dd-trace/src/appsec/waf/index.js +++ b/packages/dd-trace/src/appsec/waf/index.js @@ -41,7 +41,7 @@ function update (newRules) { try { waf.wafManager.update(newRules) } catch (err) { - log.error('Could not apply rules from remote config') + log.error('[ASM] Could not apply rules from remote config') throw err } } @@ -50,7 +50,7 @@ function run (data, req, raspRuleType) { if (!req) { const store = storage.getStore() if (!store || !store.req) { - log.warn('Request object not available in waf.run') + log.warn('[ASM] Request object not available in waf.run') return } diff --git a/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js b/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js index a2dae737a86..6a90b8f89bb 100644 --- a/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +++ b/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js @@ -23,7 +23,7 @@ class WAFContextWrapper { run ({ persistent, ephemeral }, raspRuleType) { if (this.ddwafContext.disposed) { - log.warn('Calling run on a disposed context') + log.warn('[ASM] Calling run on a disposed context') return } @@ -101,8 +101,7 @@ class WAFContextWrapper { return result.actions } catch (err) { - log.error('Error while running the AppSec WAF') - log.error(err) + log.error('[ASM] Error while running the AppSec WAF', err) } } diff --git a/packages/dd-trace/src/appsec/waf/waf_manager.js b/packages/dd-trace/src/appsec/waf/waf_manager.js index b3cc91e6104..520438d8a20 100644 --- a/packages/dd-trace/src/appsec/waf/waf_manager.js +++ b/packages/dd-trace/src/appsec/waf/waf_manager.js @@ -25,7 +25,7 @@ class WAFManager { const { obfuscatorKeyRegex, obfuscatorValueRegex } = this.config return new DDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex }) } catch (err) { - log.error('AppSec could not load native package. In-app WAF features will not be available.') + log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.') throw err } diff --git a/packages/dd-trace/test/appsec/blocking.spec.js b/packages/dd-trace/test/appsec/blocking.spec.js index 04a3c496b46..8a5496b4ecf 100644 --- a/packages/dd-trace/test/appsec/blocking.spec.js +++ b/packages/dd-trace/test/appsec/blocking.spec.js @@ -58,7 +58,7 @@ describe('blocking', () => { block(req, res, rootSpan) expect(log.warn).to.have.been - .calledOnceWithExactly('Cannot send blocking response when headers have already been sent') + .calledOnceWithExactly('[ASM] Cannot send blocking response when headers have already been sent') expect(rootSpan.addTags).to.not.have.been.called expect(res.setHeader).to.not.have.been.called expect(res.end).to.not.have.been.called diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js index 7716f0ae478..de662075cf3 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js @@ -2,7 +2,7 @@ const proxyquire = require('proxyquire') -const iastLog = require('../../../../src/appsec/iast/iast-log') +const log = require('../../../../src/log') const dc = require('dc-polyfill') describe('sql-injection-analyzer', () => { @@ -103,11 +103,11 @@ describe('sql-injection-analyzer', () => { }) it('should not report an error when context is not initialized', () => { - sinon.stub(iastLog, 'errorAndPublish') + sinon.stub(log, 'error') sqlInjectionAnalyzer.configure(true) dc.channel('datadog:sequelize:query:finish').publish() sqlInjectionAnalyzer.configure(false) - expect(iastLog.errorAndPublish).not.to.be.called + expect(log.error).not.to.be.called }) describe('analyze', () => { diff --git a/packages/dd-trace/test/appsec/iast/iast-log.spec.js b/packages/dd-trace/test/appsec/iast/iast-log.spec.js deleted file mode 100644 index bd62a45e06c..00000000000 --- a/packages/dd-trace/test/appsec/iast/iast-log.spec.js +++ /dev/null @@ -1,98 +0,0 @@ -const { expect } = require('chai') -const proxyquire = require('proxyquire') - -describe('IAST log', () => { - let iastLog - let telemetryLog - let log - - beforeEach(() => { - log = { - debug: sinon.stub(), - info: sinon.stub(), - warn: sinon.stub(), - error: sinon.stub() - } - - telemetryLog = { - hasSubscribers: true, - publish: sinon.stub() - } - - iastLog = proxyquire('../../../src/appsec/iast/iast-log', { - 'dc-polyfill': { - channel: () => telemetryLog - }, - '../../log': log - }) - }) - - afterEach(() => { - sinon.reset() - }) - - describe('debug', () => { - it('should call log.debug', () => { - iastLog.debug('debug') - - expect(log.debug).to.be.calledOnceWith('debug') - }) - - it('should call log.debug and publish msg via telemetry', () => { - iastLog.debugAndPublish('debug') - - expect(log.debug).to.be.calledOnceWith('debug') - expect(telemetryLog.publish).to.be.calledOnceWith({ message: 'debug', level: 'DEBUG' }) - }) - }) - - describe('warn', () => { - it('should call log.warn', () => { - iastLog.warn('warn') - - expect(log.warn).to.be.calledOnceWith('warn') - }) - - it('should call log.warn and publish msg via telemetry', () => { - iastLog.warnAndPublish('warn') - - expect(log.warn).to.be.calledOnceWith('warn') - expect(telemetryLog.publish).to.be.calledOnceWith({ message: 'warn', level: 'WARN' }) - }) - - it('should chain multiple warn calls', () => { - iastLog.warn('warn').warnAndPublish('warnAndPublish').warn('warn2') - - expect(log.warn).to.be.calledThrice - expect(log.warn.getCall(0).args[0]).to.be.eq('warn') - expect(log.warn.getCall(1).args[0]).to.be.eq('warnAndPublish') - expect(log.warn.getCall(2).args[0]).to.be.eq('warn2') - expect(telemetryLog.publish).to.be.calledOnceWith({ message: 'warnAndPublish', level: 'WARN' }) - }) - }) - - describe('error', () => { - it('should call log.error', () => { - iastLog.error('error') - - expect(log.error).to.be.calledOnceWith('error') - }) - - it('should call log.error and publish msg via telemetry', () => { - iastLog.errorAndPublish('error') - - expect(log.error).to.be.calledOnceWith('error') - expect(telemetryLog.publish).to.not.be.called // handled by log.error() - }) - - it('should chain multiple error calls', () => { - iastLog.error('error').errorAndPublish('errorAndPublish').error('error2') - - expect(log.error).to.be.calledThrice - expect(log.error.getCall(0).args[0]).to.be.eq('error') - expect(log.error.getCall(1).args[0]).to.be.eq('errorAndPublish') - expect(log.error.getCall(2).args[0]).to.be.eq('error2') - expect(telemetryLog.publish).to.not.be.called // handled by log.error() - }) - }) -}) diff --git a/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js b/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js index 1c3af349794..caa4e91bf8b 100644 --- a/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js @@ -51,8 +51,8 @@ describe('IAST Plugin', () => { const iastPluginMod = proxyquire('../../../src/appsec/iast/iast-plugin', { '../../plugins/plugin': PluginClass, - './iast-log': { - errorAndPublish: logError + '../../log': { + error: logError }, './iast-context': { getIastContext @@ -205,8 +205,8 @@ describe('IAST Plugin', () => { } const IastPlugin = proxyquire('../../../src/appsec/iast/iast-plugin', { '../../plugins/plugin': PluginClass, - './iast-log': { - errorAndPublish: logError + '../../log': { + error: logError }, './telemetry': iastTelemetry, '../../../../datadog-instrumentations/src/helpers/instrumentations': {} diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js index c105eb5b97c..68023dc710e 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js @@ -169,15 +169,14 @@ describe('IAST TaintTracking Operations', () => { trim: id => id } - const iastLogStub = { - error (data) { return this }, - errorAndPublish (data) { return this } + const logStub = { + error (data) { return this } } - const logSpy = sinon.spy(iastLogStub) + const logSpy = sinon.spy(logStub) const operationsTaintObject = proxyquire('../../../../src/appsec/iast/taint-tracking/operations-taint-object', { '@datadog/native-iast-taint-tracking': taintedUtils, - '../iast-log': logSpy + '../../../log': logSpy }) const taintTrackingOperations = proxyquire('../../../../src/appsec/iast/taint-tracking/operations', { '../../../../../datadog-core': datadogCore, @@ -188,7 +187,6 @@ describe('IAST TaintTracking Operations', () => { taintTrackingOperations.createTransaction(transactionId, iastContext) const result = taintTrackingOperations.taintObject(iastContext, obj, null) expect(logSpy.error).to.have.been.calledOnce - expect(logSpy.errorAndPublish).to.have.been.calledOnce expect(result).to.equal(obj) }) }) diff --git a/packages/dd-trace/test/appsec/iast/vulnerability-formatter/evidence-redaction/sensitive-handler.spec.js b/packages/dd-trace/test/appsec/iast/vulnerability-formatter/evidence-redaction/sensitive-handler.spec.js index a9c1ae465ce..20ddeb75cfc 100644 --- a/packages/dd-trace/test/appsec/iast/vulnerability-formatter/evidence-redaction/sensitive-handler.spec.js +++ b/packages/dd-trace/test/appsec/iast/vulnerability-formatter/evidence-redaction/sensitive-handler.spec.js @@ -48,10 +48,10 @@ describe('Sensitive handler', () => { }) describe('Not valid custom patterns', () => { - const iastLog = require('../../../../../src/appsec/iast/iast-log') + const log = require('../../../../../src/log') beforeEach(() => { - sinon.stub(iastLog, 'warn') + sinon.stub(log, 'warn') }) afterEach(() => { @@ -63,9 +63,9 @@ describe('Sensitive handler', () => { expect(sensitiveHandler._namePattern.source).to.be.equals(DEFAULT_IAST_REDACTION_NAME_PATTERN) expect(sensitiveHandler._valuePattern.source).to.be.equals(DEFAULT_IAST_REDACTION_VALUE_PATTERN) - expect(iastLog.warn).to.have.been.calledTwice - expect(iastLog.warn.firstCall.args[0]).to.be.equals('Redaction name pattern is not valid') - expect(iastLog.warn.secondCall.args[0]).to.be.equals('Redaction value pattern is not valid') + expect(log.warn).to.have.been.calledTwice + expect(log.warn.firstCall.args[0]).to.be.equals('[ASM] Redaction name pattern is not valid') + expect(log.warn.secondCall.args[0]).to.be.equals('[ASM] Redaction value pattern is not valid') }) it('should use default name pattern when custom name pattern is not valid', () => { @@ -74,7 +74,7 @@ describe('Sensitive handler', () => { expect(sensitiveHandler._namePattern.source).to.be.equals(DEFAULT_IAST_REDACTION_NAME_PATTERN) expect(sensitiveHandler._valuePattern.source).to.be.equals(customValuePattern) - expect(iastLog.warn).to.have.been.calledOnceWithExactly('Redaction name pattern is not valid') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Redaction name pattern is not valid') }) it('should use default value pattern when custom value pattern is not valid', () => { @@ -83,7 +83,7 @@ describe('Sensitive handler', () => { expect(sensitiveHandler._namePattern.source).to.be.equals(customNamePattern) expect(sensitiveHandler._valuePattern.source).to.be.equals(DEFAULT_IAST_REDACTION_VALUE_PATTERN) - expect(iastLog.warn).to.have.been.calledOnceWithExactly('Redaction value pattern is not valid') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Redaction value pattern is not valid') }) }) diff --git a/packages/dd-trace/test/appsec/index.spec.js b/packages/dd-trace/test/appsec/index.spec.js index 5d79c5ae569..26a1c709cd9 100644 --- a/packages/dd-trace/test/appsec/index.spec.js +++ b/packages/dd-trace/test/appsec/index.spec.js @@ -165,9 +165,7 @@ describe('AppSec Index', function () { AppSec.enable(config) - expect(log.error).to.have.been.calledTwice - expect(log.error.firstCall).to.have.been.calledWithExactly('Unable to start AppSec') - expect(log.error.secondCall).to.have.been.calledWithExactly(err) + expect(log.error).to.have.been.calledOnceWithExactly('[ASM] Unable to start AppSec', err) expect(incomingHttpRequestStart.subscribe).to.not.have.been.called expect(incomingHttpRequestEnd.subscribe).to.not.have.been.called }) @@ -828,7 +826,7 @@ describe('AppSec Index', function () { passportVerify.publish({ credentials, user }) - expect(log.warn).to.have.been.calledOnceWithExactly('No rootSpan found in onPassportVerify') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No rootSpan found in onPassportVerify') expect(passport.passportTrackEvent).not.to.have.been.called }) }) diff --git a/packages/dd-trace/test/appsec/passport.spec.js b/packages/dd-trace/test/appsec/passport.spec.js index 7a3db36798c..fcfeb9549f1 100644 --- a/packages/dd-trace/test/appsec/passport.spec.js +++ b/packages/dd-trace/test/appsec/passport.spec.js @@ -41,7 +41,7 @@ describe('Passport', () => { it('should call log when credentials is undefined', () => { passportModule.passportTrackEvent(undefined, undefined, undefined, 'safe') - expect(log.warn).to.have.been.calledOnceWithExactly('No user ID found in authentication instrumentation') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No user ID found in authentication instrumentation') }) it('should call log when type is not known', () => { @@ -49,7 +49,7 @@ describe('Passport', () => { passportModule.passportTrackEvent(credentials, undefined, undefined, 'safe') - expect(log.warn).to.have.been.calledOnceWithExactly('No user ID found in authentication instrumentation') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No user ID found in authentication instrumentation') }) it('should call log when type is known but username not present', () => { @@ -57,7 +57,7 @@ describe('Passport', () => { passportModule.passportTrackEvent(credentials, undefined, undefined, 'safe') - expect(log.warn).to.have.been.calledOnceWithExactly('No user ID found in authentication instrumentation') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No user ID found in authentication instrumentation') }) it('should report login failure when passportUser is not present', () => { diff --git a/packages/dd-trace/test/appsec/remote_config/manager.spec.js b/packages/dd-trace/test/appsec/remote_config/manager.spec.js index f9aea97ce08..2a32e834e06 100644 --- a/packages/dd-trace/test/appsec/remote_config/manager.spec.js +++ b/packages/dd-trace/test/appsec/remote_config/manager.spec.js @@ -212,7 +212,7 @@ describe('RemoteConfigManager', () => { rc.poll(() => { expect(request).to.have.been.calledOnceWith(payload, expectedPayload) - expect(log.error).to.have.been.calledOnceWithExactly(err) + expect(log.error).to.have.been.calledOnceWithExactly('[RC] Error in request', err) expect(rc.parseConfig).to.not.have.been.called cb() }) @@ -232,10 +232,11 @@ describe('RemoteConfigManager', () => { }) it('should catch exceptions, update the error state, and clear the error state at next request', (cb) => { + const error = new Error('Unable to parse config') request .onFirstCall().yieldsRight(null, '{"a":"b"}', 200) .onSecondCall().yieldsRight(null, null, 200) - rc.parseConfig.onFirstCall().throws(new Error('Unable to parse config')) + rc.parseConfig.onFirstCall().throws(error) const payload = JSON.stringify(rc.state) @@ -243,7 +244,7 @@ describe('RemoteConfigManager', () => { expect(request).to.have.been.calledOnceWith(payload, expectedPayload) expect(rc.parseConfig).to.have.been.calledOnceWithExactly({ a: 'b' }) expect(log.error).to.have.been - .calledOnceWithExactly('Could not parse remote config response: Error: Unable to parse config') + .calledOnceWithExactly('[RC] Could not parse remote config response', error) expect(rc.state.client.state.has_error).to.be.true expect(rc.state.client.state.error).to.equal('Error: Unable to parse config') diff --git a/packages/dd-trace/test/appsec/sdk/set_user.spec.js b/packages/dd-trace/test/appsec/sdk/set_user.spec.js index 9327a88afcd..29eb25560a1 100644 --- a/packages/dd-trace/test/appsec/sdk/set_user.spec.js +++ b/packages/dd-trace/test/appsec/sdk/set_user.spec.js @@ -32,14 +32,14 @@ describe('set_user', () => { describe('setUser', () => { it('should not call setTag when no user is passed', () => { setUser(tracer) - expect(log.warn).to.have.been.calledOnceWithExactly('Invalid user provided to setUser') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Invalid user provided to setUser') expect(rootSpan.setTag).to.not.have.been.called }) it('should not call setTag when user is empty', () => { const user = {} setUser(tracer, user) - expect(log.warn).to.have.been.calledOnceWithExactly('Invalid user provided to setUser') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Invalid user provided to setUser') expect(rootSpan.setTag).to.not.have.been.called }) @@ -48,7 +48,7 @@ describe('set_user', () => { setUser(tracer, { id: 'user' }) expect(getRootSpan).to.be.calledOnceWithExactly(tracer) - expect(log.warn).to.have.been.calledOnceWithExactly('Root span not available in setUser') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Root span not available in setUser') expect(rootSpan.setTag).to.not.have.been.called }) diff --git a/packages/dd-trace/test/appsec/sdk/track_event.spec.js b/packages/dd-trace/test/appsec/sdk/track_event.spec.js index fca01030c03..97f1ac07bd7 100644 --- a/packages/dd-trace/test/appsec/sdk/track_event.spec.js +++ b/packages/dd-trace/test/appsec/sdk/track_event.spec.js @@ -75,9 +75,10 @@ describe('track_event', () => { trackUserLoginSuccessEvent(tracer, {}, { key: 'value' }) expect(log.warn).to.have.been.calledTwice - expect(log.warn.firstCall).to.have.been.calledWithExactly('Invalid user provided to trackUserLoginSuccessEvent') + expect(log.warn.firstCall) + .to.have.been.calledWithExactly('[ASM] Invalid user provided to trackUserLoginSuccessEvent') expect(log.warn.secondCall) - .to.have.been.calledWithExactly('Invalid user provided to trackUserLoginSuccessEvent') + .to.have.been.calledWithExactly('[ASM] Invalid user provided to trackUserLoginSuccessEvent') expect(setUserTags).to.not.have.been.called expect(rootSpan.addTags).to.not.have.been.called }) @@ -87,7 +88,8 @@ describe('track_event', () => { trackUserLoginSuccessEvent(tracer, { id: 'user_id' }, { key: 'value' }) - expect(log.warn).to.have.been.calledOnceWithExactly('Root span not available in trackUserLoginSuccessEvent') + expect(log.warn) + .to.have.been.calledOnceWithExactly('[ASM] Root span not available in trackUserLoginSuccessEvent') expect(setUserTags).to.not.have.been.called }) @@ -147,9 +149,9 @@ describe('track_event', () => { expect(log.warn).to.have.been.calledTwice expect(log.warn.firstCall) - .to.have.been.calledWithExactly('Invalid userId provided to trackUserLoginFailureEvent') + .to.have.been.calledWithExactly('[ASM] Invalid userId provided to trackUserLoginFailureEvent') expect(log.warn.secondCall) - .to.have.been.calledWithExactly('Invalid userId provided to trackUserLoginFailureEvent') + .to.have.been.calledWithExactly('[ASM] Invalid userId provided to trackUserLoginFailureEvent') expect(setUserTags).to.not.have.been.called expect(rootSpan.addTags).to.not.have.been.called }) @@ -159,7 +161,8 @@ describe('track_event', () => { trackUserLoginFailureEvent(tracer, 'user_id', false) - expect(log.warn).to.have.been.calledOnceWithExactly('Root span not available in trackUserLoginFailureEvent') + expect(log.warn) + .to.have.been.calledOnceWithExactly('[ASM] Root span not available in %s', 'trackUserLoginFailureEvent') expect(setUserTags).to.not.have.been.called }) @@ -233,8 +236,10 @@ describe('track_event', () => { trackCustomEvent(tracer, { name: 'name' }) expect(log.warn).to.have.been.calledTwice - expect(log.warn.firstCall).to.have.been.calledWithExactly('Invalid eventName provided to trackCustomEvent') - expect(log.warn.secondCall).to.have.been.calledWithExactly('Invalid eventName provided to trackCustomEvent') + expect(log.warn.firstCall) + .to.have.been.calledWithExactly('[ASM] Invalid eventName provided to trackCustomEvent') + expect(log.warn.secondCall) + .to.have.been.calledWithExactly('[ASM] Invalid eventName provided to trackCustomEvent') expect(setUserTags).to.not.have.been.called expect(rootSpan.addTags).to.not.have.been.called }) @@ -244,7 +249,8 @@ describe('track_event', () => { trackCustomEvent(tracer, 'custom_event') - expect(log.warn).to.have.been.calledOnceWithExactly('Root span not available in trackCustomEvent') + expect(log.warn) + .to.have.been.calledOnceWithExactly('[ASM] Root span not available in %s', 'trackCustomEvent') expect(setUserTags).to.not.have.been.called }) diff --git a/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js b/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js index 6df68104e85..3a361eb382a 100644 --- a/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js +++ b/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js @@ -64,13 +64,13 @@ describe('user_blocking', () => { it('should return false and log warn when passed no user', () => { const ret = userBlocking.checkUserAndSetUser() expect(ret).to.be.false - expect(log.warn).to.have.been.calledOnceWithExactly('Invalid user provided to isUserBlocked') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Invalid user provided to isUserBlocked') }) it('should return false and log warn when passed invalid user', () => { const ret = userBlocking.checkUserAndSetUser({}) expect(ret).to.be.false - expect(log.warn).to.have.been.calledOnceWithExactly('Invalid user provided to isUserBlocked') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Invalid user provided to isUserBlocked') }) it('should set user when not already set', () => { @@ -97,7 +97,7 @@ describe('user_blocking', () => { const ret = userBlocking.checkUserAndSetUser(tracer, { id: 'user' }) expect(ret).to.be.true expect(getRootSpan).to.have.been.calledOnceWithExactly(tracer) - expect(log.warn).to.have.been.calledOnceWithExactly('Root span not available in isUserBlocked') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Root span not available in isUserBlocked') expect(rootSpan.setTag).to.not.have.been.called }) @@ -122,7 +122,8 @@ describe('user_blocking', () => { const ret = userBlocking.blockRequest(tracer) expect(ret).to.be.false expect(storage.getStore).to.have.been.calledOnce - expect(log.warn).to.have.been.calledOnceWithExactly('Requests or response object not available in blockRequest') + expect(log.warn) + .to.have.been.calledOnceWithExactly('[ASM] Requests or response object not available in blockRequest') expect(block).to.not.have.been.called }) @@ -131,7 +132,7 @@ describe('user_blocking', () => { const ret = userBlocking.blockRequest(tracer, {}, {}) expect(ret).to.be.false - expect(log.warn).to.have.been.calledOnceWithExactly('Root span not available in blockRequest') + expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] Root span not available in blockRequest') expect(block).to.not.have.been.called }) diff --git a/packages/dd-trace/test/appsec/waf/waf_context_wrapper.spec.js b/packages/dd-trace/test/appsec/waf/waf_context_wrapper.spec.js index cffe9718ee2..436f6c093d4 100644 --- a/packages/dd-trace/test/appsec/waf/waf_context_wrapper.spec.js +++ b/packages/dd-trace/test/appsec/waf/waf_context_wrapper.spec.js @@ -151,7 +151,7 @@ describe('WAFContextWrapper', () => { wafContextWrapper.run(payload) sinon.assert.notCalled(ddwafContext.run) - sinon.assert.calledOnceWithExactly(log.warn, 'Calling run on a disposed context') + sinon.assert.calledOnceWithExactly(log.warn, '[ASM] Calling run on a disposed context') }) }) }) From dd3ac497b58978a18ef00f18d8ff6af69a4e7e28 Mon Sep 17 00:00:00 2001 From: simon-id Date: Fri, 22 Nov 2024 15:08:03 +0100 Subject: [PATCH 2/8] Revert log change to avoid a conflict (#4931) * Update passport.js * update tests --- packages/dd-trace/src/appsec/passport.js | 2 +- packages/dd-trace/test/appsec/passport.spec.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/dd-trace/src/appsec/passport.js b/packages/dd-trace/src/appsec/passport.js index 0cbcb4b51bc..2093b7b1fdc 100644 --- a/packages/dd-trace/src/appsec/passport.js +++ b/packages/dd-trace/src/appsec/passport.js @@ -86,7 +86,7 @@ function passportTrackEvent (credentials, passportUser, rootSpan, mode) { const user = parseUser(getLogin(credentials), passportUser, mode) if (user['usr.id'] === undefined) { - log.warn('[ASM] No user ID found in authentication instrumentation') + log.warn('No user ID found in authentication instrumentation') return } diff --git a/packages/dd-trace/test/appsec/passport.spec.js b/packages/dd-trace/test/appsec/passport.spec.js index fcfeb9549f1..7a3db36798c 100644 --- a/packages/dd-trace/test/appsec/passport.spec.js +++ b/packages/dd-trace/test/appsec/passport.spec.js @@ -41,7 +41,7 @@ describe('Passport', () => { it('should call log when credentials is undefined', () => { passportModule.passportTrackEvent(undefined, undefined, undefined, 'safe') - expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No user ID found in authentication instrumentation') + expect(log.warn).to.have.been.calledOnceWithExactly('No user ID found in authentication instrumentation') }) it('should call log when type is not known', () => { @@ -49,7 +49,7 @@ describe('Passport', () => { passportModule.passportTrackEvent(credentials, undefined, undefined, 'safe') - expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No user ID found in authentication instrumentation') + expect(log.warn).to.have.been.calledOnceWithExactly('No user ID found in authentication instrumentation') }) it('should call log when type is known but username not present', () => { @@ -57,7 +57,7 @@ describe('Passport', () => { passportModule.passportTrackEvent(credentials, undefined, undefined, 'safe') - expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No user ID found in authentication instrumentation') + expect(log.warn).to.have.been.calledOnceWithExactly('No user ID found in authentication instrumentation') }) it('should report login failure when passportUser is not present', () => { From 6ec233f2f59eeed989c82c4404088c636640d01d Mon Sep 17 00:00:00 2001 From: Sam Brenner <106700075+sabrenner@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:10:53 -0500 Subject: [PATCH 3/8] fix(langchain): do not throw when result is undefined (#4933) * do not throw when result is undefined * remove `expect` require --- .../handlers/language_models/chat_model.js | 2 +- .../src/handlers/language_models/llm.js | 2 +- .../test/index.spec.js | 108 ++++++++++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-) diff --git a/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js b/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js index 681e5deb050..56fabeecfc0 100644 --- a/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +++ b/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js @@ -46,7 +46,7 @@ class LangChainChatModelHandler extends LangChainLanguageModelHandler { this.extractTokenMetrics(ctx.currentStore?.span, result) - for (const messageSetIdx in result.generations) { + for (const messageSetIdx in result?.generations) { const messageSet = result.generations[messageSetIdx] for (const chatCompletionIdx in messageSet) { diff --git a/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js b/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js index acd4967fd8d..d7c489bbc0f 100644 --- a/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +++ b/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js @@ -37,7 +37,7 @@ class LangChainLLMHandler extends LangChainLanguageModelHandler { this.extractTokenMetrics(ctx.currentStore?.span, result) - for (const completionIdx in result.generations) { + for (const completionIdx in result?.generations) { const completion = result.generations[completionIdx] if (this.isPromptCompletionSampled()) { tags[`langchain.response.completions.${completionIdx}.text`] = this.normalize(completion[0].text) || '' diff --git a/packages/datadog-plugin-langchain/test/index.spec.js b/packages/datadog-plugin-langchain/test/index.spec.js index 77f61da3688..24500b09c3b 100644 --- a/packages/datadog-plugin-langchain/test/index.spec.js +++ b/packages/datadog-plugin-langchain/test/index.spec.js @@ -137,6 +137,33 @@ describe('Plugin', () => { }) describe('llm', () => { + it('does not tag output on error', async () => { + nock('https://api.openai.com').post('/v1/completions').reply(403) + + const checkTraces = agent + .use(traces => { + expect(traces[0].length).to.equal(1) + + const span = traces[0][0] + + const langchainResponseRegex = /^langchain\.response\.completions\./ + const hasMatching = Object.keys(span.meta).some(key => langchainResponseRegex.test(key)) + + expect(hasMatching).to.be.false + + expect(span.meta).to.have.property('error.message') + expect(span.meta).to.have.property('error.type') + expect(span.meta).to.have.property('error.stack') + }) + + try { + const llm = new langchainOpenai.OpenAI({ model: 'gpt-3.5-turbo-instruct', maxRetries: 0 }) + await llm.generate(['what is 2 + 2?']) + } catch {} + + await checkTraces + }) + it('instruments a langchain llm call for a single prompt', async () => { stubCall({ ...openAiBaseCompletionInfo, @@ -270,6 +297,32 @@ describe('Plugin', () => { }) describe('chat model', () => { + it('does not tag output on error', async () => { + nock('https://api.openai.com').post('/v1/chat/completions').reply(403) + + const checkTraces = agent + .use(traces => { + expect(traces[0].length).to.equal(1) + + const span = traces[0][0] + + const langchainResponseRegex = /^langchain\.response\.completions\./ + const hasMatching = Object.keys(span.meta).some(key => langchainResponseRegex.test(key)) + expect(hasMatching).to.be.false + + expect(span.meta).to.have.property('error.message') + expect(span.meta).to.have.property('error.type') + expect(span.meta).to.have.property('error.stack') + }) + + try { + const chatModel = new langchainOpenai.ChatOpenAI({ model: 'gpt-4', maxRetries: 0 }) + await chatModel.invoke('Hello!') + } catch {} + + await checkTraces + }) + it('instruments a langchain openai chat model call for a single string prompt', async () => { stubCall({ ...openAiBaseChatInfo, @@ -546,6 +599,37 @@ describe('Plugin', () => { }) describe('chain', () => { + it('does not tag output on error', async () => { + nock('https://api.openai.com').post('/v1/chat/completions').reply(403) + + const checkTraces = agent + .use(traces => { + expect(traces[0].length).to.equal(2) + + const chainSpan = traces[0][0] + + const langchainResponseRegex = /^langchain\.response\.outputs\./ + + const hasMatching = Object.keys(chainSpan.meta).some(key => langchainResponseRegex.test(key)) + expect(hasMatching).to.be.false + + expect(chainSpan.meta).to.have.property('error.message') + expect(chainSpan.meta).to.have.property('error.type') + expect(chainSpan.meta).to.have.property('error.stack') + }) + + try { + const model = new langchainOpenai.ChatOpenAI({ model: 'gpt-4', maxRetries: 0 }) + const parser = new langchainOutputParsers.StringOutputParser() + + const chain = model.pipe(parser) + + await chain.invoke('Hello!') + } catch {} + + await checkTraces + }) + it('instruments a langchain chain with a single openai chat model call', async () => { stubCall({ ...openAiBaseChatInfo, @@ -790,6 +874,30 @@ describe('Plugin', () => { describe('embeddings', () => { describe('@langchain/openai', () => { + it('does not tag output on error', async () => { + nock('https://api.openai.com').post('/v1/embeddings').reply(403) + + const checkTraces = agent + .use(traces => { + expect(traces[0].length).to.equal(1) + + const span = traces[0][0] + + expect(span.meta).to.not.have.property('langchain.response.outputs.embedding_length') + + expect(span.meta).to.have.property('error.message') + expect(span.meta).to.have.property('error.type') + expect(span.meta).to.have.property('error.stack') + }) + + try { + const embeddings = new langchainOpenai.OpenAIEmbeddings() + await embeddings.embedQuery('Hello, world!') + } catch {} + + await checkTraces + }) + it('instruments a langchain openai embedQuery call', async () => { stubCall({ ...openAiBaseEmbeddingInfo, From a4e2182143a154012184828de2fc09770b55460d Mon Sep 17 00:00:00 2001 From: Duncan Harvey <35278470+duncanpharvey@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:20:18 -0500 Subject: [PATCH 4/8] Update Azure Functions operation name to azure.functions.invoke (#4914) --- packages/datadog-instrumentations/src/azure-functions.js | 2 +- packages/datadog-plugin-azure-functions/src/index.js | 2 +- .../test/integration-test/client.spec.js | 2 +- packages/dd-trace/src/service-naming/schemas/v0/serverless.js | 2 +- packages/dd-trace/src/service-naming/schemas/v1/serverless.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/datadog-instrumentations/src/azure-functions.js b/packages/datadog-instrumentations/src/azure-functions.js index 2527d9afb3f..791d3a9025f 100644 --- a/packages/datadog-instrumentations/src/azure-functions.js +++ b/packages/datadog-instrumentations/src/azure-functions.js @@ -6,7 +6,7 @@ const { const shimmer = require('../../datadog-shimmer') const dc = require('dc-polyfill') -const azureFunctionsChannel = dc.tracingChannel('datadog:azure-functions:invoke') +const azureFunctionsChannel = dc.tracingChannel('datadog:azure:functions:invoke') addHook({ name: '@azure/functions', versions: ['>=4'] }, azureFunction => { const { app } = azureFunction diff --git a/packages/datadog-plugin-azure-functions/src/index.js b/packages/datadog-plugin-azure-functions/src/index.js index 2c85403906c..c2f9783c039 100644 --- a/packages/datadog-plugin-azure-functions/src/index.js +++ b/packages/datadog-plugin-azure-functions/src/index.js @@ -20,7 +20,7 @@ class AzureFunctionsPlugin extends TracingPlugin { static get kind () { return 'server' } static get type () { return 'serverless' } - static get prefix () { return 'tracing:datadog:azure-functions:invoke' } + static get prefix () { return 'tracing:datadog:azure:functions:invoke' } bindStart (ctx) { const { functionName, methodName } = ctx diff --git a/packages/datadog-plugin-azure-functions/test/integration-test/client.spec.js b/packages/datadog-plugin-azure-functions/test/integration-test/client.spec.js index 8d5a0d43fdb..51dd4aba5fd 100644 --- a/packages/datadog-plugin-azure-functions/test/integration-test/client.spec.js +++ b/packages/datadog-plugin-azure-functions/test/integration-test/client.spec.js @@ -47,7 +47,7 @@ describe('esm', () => { assert.strictEqual(payload.length, 1) assert.isArray(payload[0]) assert.strictEqual(payload[0].length, 1) - assert.propertyVal(payload[0][0], 'name', 'azure-functions.invoke') + assert.propertyVal(payload[0][0], 'name', 'azure.functions.invoke') }) }).timeout(50000) }) diff --git a/packages/dd-trace/src/service-naming/schemas/v0/serverless.js b/packages/dd-trace/src/service-naming/schemas/v0/serverless.js index fcccdcb465a..64202b11873 100644 --- a/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +++ b/packages/dd-trace/src/service-naming/schemas/v0/serverless.js @@ -3,7 +3,7 @@ const { identityService } = require('../util') const serverless = { server: { 'azure-functions': { - opName: () => 'azure-functions.invoke', + opName: () => 'azure.functions.invoke', serviceName: identityService } } diff --git a/packages/dd-trace/src/service-naming/schemas/v1/serverless.js b/packages/dd-trace/src/service-naming/schemas/v1/serverless.js index fcccdcb465a..64202b11873 100644 --- a/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +++ b/packages/dd-trace/src/service-naming/schemas/v1/serverless.js @@ -3,7 +3,7 @@ const { identityService } = require('../util') const serverless = { server: { 'azure-functions': { - opName: () => 'azure-functions.invoke', + opName: () => 'azure.functions.invoke', serviceName: identityService } } From bddba1a8907b9c0da4aa19496ffa95bdbe3fed7c Mon Sep 17 00:00:00 2001 From: Bryan English Date: Mon, 25 Nov 2024 12:51:22 -0500 Subject: [PATCH 5/8] make SSI not crash on node 12.0.0, 18.0.0, et.c (#4934) * make it not crash on 12.0.0 * wider ranged test matrix for init.spec.js * make 18.0.0 not crash, even though ESM can't be supported in it * isolate old/weird node version tests to the init test --- .github/workflows/project.yml | 4 ++-- init.js | 6 ++++-- initialize.mjs | 9 ++++++-- integration-tests/init.spec.js | 39 +++++++++++++++++++++++++++++----- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index 38c43297947..92a97c56457 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -18,7 +18,7 @@ jobs: # setting fail-fast to false in an attempt to prevent this from happening fail-fast: false matrix: - version: [18, 20, latest] + version: [18, 20, 22, latest] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -34,7 +34,7 @@ jobs: integration-guardrails: strategy: matrix: - version: [12, 14, 16] + version: [12.0.0, 12, 14.0.0, 14, 16.0.0, 16, 18.0.0, 18.1.0, 20.0.0, 22.0.0] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/init.js b/init.js index 8b183fc17ab..d9286b0307f 100644 --- a/init.js +++ b/init.js @@ -2,7 +2,9 @@ /* eslint-disable no-var */ -var NODE_MAJOR = require('./version').NODE_MAJOR +var nodeVersion = require('./version') +var NODE_MAJOR = nodeVersion.NODE_MAJOR +var NODE_MINOR = nodeVersion.NODE_MINOR // We use several things that are not supported by older versions of Node: // - AsyncLocalStorage @@ -11,7 +13,7 @@ var NODE_MAJOR = require('./version').NODE_MAJOR // - Mocha (for testing) // and probably others. // TODO: Remove all these dependencies so that we can report telemetry. -if (NODE_MAJOR >= 12) { +if ((NODE_MAJOR === 12 && NODE_MINOR >= 17) || NODE_MAJOR > 12) { var path = require('path') var Module = require('module') var semver = require('semver') diff --git a/initialize.mjs b/initialize.mjs index 777f45cc046..104e253d22d 100644 --- a/initialize.mjs +++ b/initialize.mjs @@ -31,11 +31,16 @@ ${result.source}` return result } +const [NODE_MAJOR, NODE_MINOR] = process.versions.node.split('.').map(x => +x) + +const brokenLoaders = NODE_MAJOR === 18 && NODE_MINOR === 0 + export async function load (...args) { - return insertInit(await origLoad(...args)) + const loadHook = brokenLoaders ? args[args.length - 1] : origLoad + return insertInit(await loadHook(...args)) } -export const resolve = origResolve +export const resolve = brokenLoaders ? undefined : origResolve export const getFormat = origGetFormat diff --git a/integration-tests/init.spec.js b/integration-tests/init.spec.js index 571179276e1..3c37004f607 100644 --- a/integration-tests/init.spec.js +++ b/integration-tests/init.spec.js @@ -20,6 +20,7 @@ const telemetryGood = ['complete', 'injection_forced:false'] const { engines } = require('../package.json') const supportedRange = engines.node const currentVersionIsSupported = semver.satisfies(process.versions.node, supportedRange) +const currentVersionCanLog = semver.satisfies(process.versions.node, '>=12.17.0') // These are on by default in release tests, so we'll turn them off for // more fine-grained control of these variables in these tests. @@ -83,7 +84,30 @@ function testRuntimeVersionChecks (arg, filename) { } } - if (!currentVersionIsSupported) { + if (!currentVersionCanLog) { + context('when node version is too low for AsyncLocalStorage', () => { + useEnv({ NODE_OPTIONS }) + + it('should initialize the tracer, if no DD_INJECTION_ENABLED', () => + doTest('false\n')) + context('with DD_INJECTION_ENABLED', () => { + useEnv({ DD_INJECTION_ENABLED }) + + context('without debug', () => { + it('should not initialize the tracer', () => doTest('false\n')) + it('should not, if DD_INJECT_FORCE', () => doTestForced('false\n')) + }) + context('with debug', () => { + useEnv({ DD_TRACE_DEBUG }) + + it('should not initialize the tracer', () => + doTest('false\n')) + it('should initialize the tracer, if DD_INJECT_FORCE', () => + doTestForced('false\n')) + }) + }) + }) + } else if (!currentVersionIsSupported) { context('when node version is less than engines field', () => { useEnv({ NODE_OPTIONS }) @@ -165,17 +189,22 @@ describe('init.js', () => { testRuntimeVersionChecks('require', 'init.js') }) -// ESM is not supportable prior to Node.js 12 -if (semver.satisfies(process.versions.node, '>=12')) { +// ESM is not supportable prior to Node.js 12.17.0, 14.13.1 on the 14.x line, +// or on 18.0.0 in particular. +if ( + semver.satisfies(process.versions.node, '>=12.17.0') && + semver.satisfies(process.versions.node, '>=14.13.1') +) { describe('initialize.mjs', () => { useSandbox() stubTracerIfNeeded() context('as --loader', () => { - testInjectionScenarios('loader', 'initialize.mjs', true) + testInjectionScenarios('loader', 'initialize.mjs', + process.versions.node !== '18.0.0') testRuntimeVersionChecks('loader', 'initialize.mjs') }) - if (Number(process.versions.node.split('.')[0]) >= 18) { + if (semver.satisfies(process.versions.node, '>=20.6.0')) { context('as --import', () => { testInjectionScenarios('import', 'initialize.mjs', true) testRuntimeVersionChecks('loader', 'initialize.mjs') From a415f8c6f0ee524f1ac2c58cfe4b833afbef858d Mon Sep 17 00:00:00 2001 From: Roch Devost Date: Mon, 25 Nov 2024 20:13:43 -0500 Subject: [PATCH 6/8] fix oracledb ci job using a node version incompatible with container (#4943) --- .github/workflows/plugins.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index b9b4b387e4a..5e1c3ac3017 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -802,7 +802,11 @@ jobs: # TODO: Figure out why nyc stopped working with EACCESS errors. oracledb: runs-on: ubuntu-latest - container: bengl/node-12-with-oracle-client + container: + image: bengl/node-12-with-oracle-client + volumes: + - /node20217:/node20217:rw,rshared + - /node20217:/__e/node20:ro,rshared services: oracledb: image: gvenzl/oracle-xe:18-slim @@ -827,6 +831,11 @@ jobs: # Needed to fix issue with `actions/checkout@v3: https://github.com/actions/checkout/issues/1590 ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true steps: + # https://github.com/actions/runner/issues/2906#issuecomment-2109514798 + - name: Install Node for runner (with glibc 2.17 compatibility) + run: | + curl -LO https://unofficial-builds.nodejs.org/download/release/v20.9.0/node-v20.9.0-linux-x64-glibc-217.tar.xz + tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217 - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: From 8b481be4d680a392ef90c3e7c59554c1efbc28c9 Mon Sep 17 00:00:00 2001 From: Roch Devost Date: Mon, 25 Nov 2024 21:06:59 -0500 Subject: [PATCH 7/8] fix race condition in initialization file on latest node (#4942) --- initialize.mjs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/initialize.mjs b/initialize.mjs index 104e253d22d..b7303848430 100644 --- a/initialize.mjs +++ b/initialize.mjs @@ -12,6 +12,7 @@ import { isMainThread } from 'worker_threads' +import * as Module from 'node:module' import { fileURLToPath } from 'node:url' import { load as origLoad, @@ -49,12 +50,9 @@ export async function getSource (...args) { } if (isMainThread) { - // Need this IIFE for versions of Node.js without top-level await. - (async () => { - await import('./init.js') - const { register } = await import('node:module') - if (register) { - register('./loader-hook.mjs', import.meta.url) - } - })() + const require = Module.createRequire(import.meta.url) + require('./init.js') + if (Module.register) { + Module.register('./loader-hook.mjs', import.meta.url) + } } From 34cdb933f7ee4fd2a5369fea4ccc397c52bd3ccf Mon Sep 17 00:00:00 2001 From: rochdev Date: Mon, 25 Nov 2024 21:20:35 -0500 Subject: [PATCH 8/8] v5.28.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d9477b3cc79..a4f31e0c580 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dd-trace", - "version": "5.27.1", + "version": "5.28.0", "description": "Datadog APM tracing client for JavaScript", "main": "index.js", "typings": "index.d.ts",