dd-trace 5.25.0 → 5.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +2 -0
- package/index.d.ts +10 -8
- package/init.js +60 -47
- package/package.json +5 -2
- package/packages/datadog-core/index.js +1 -3
- package/packages/datadog-core/src/storage.js +21 -0
- package/packages/datadog-instrumentations/src/express.js +1 -1
- package/packages/datadog-instrumentations/src/handlebars.js +40 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/jest.js +6 -2
- package/packages/datadog-instrumentations/src/pug.js +23 -0
- package/packages/datadog-instrumentations/src/router.js +2 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -7
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +34 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +10 -9
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +59 -45
- package/packages/datadog-plugin-cypress/src/support.js +1 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-grpc/src/server.js +2 -1
- package/packages/datadog-plugin-http/src/client.js +42 -1
- package/packages/datadog-plugin-http2/src/client.js +26 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -1
- package/packages/datadog-plugin-mocha/src/index.js +1 -1
- package/packages/datadog-plugin-moleculer/src/server.js +2 -2
- package/packages/datadog-plugin-rhea/src/consumer.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +2 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +33 -16
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +18 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +6 -6
- package/packages/dd-trace/src/appsec/recommended.json +353 -155
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +0 -7
- package/packages/dd-trace/src/appsec/reporter.js +1 -0
- package/packages/dd-trace/src/config.js +13 -4
- package/packages/dd-trace/src/constants.js +6 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +98 -0
- package/packages/dd-trace/src/crashtracking/index.js +15 -0
- package/packages/dd-trace/src/crashtracking/noop.js +8 -0
- package/packages/dd-trace/src/llmobs/sdk.js +1 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +3 -0
- package/packages/dd-trace/src/log/index.js +10 -13
- package/packages/dd-trace/src/log/log.js +52 -0
- package/packages/dd-trace/src/log/writer.js +50 -19
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +15 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -22
- package/packages/dd-trace/src/opentracing/span.js +14 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/tracing.js +3 -3
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +121 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +0 -1
- package/packages/dd-trace/src/plugins/util/web.js +39 -11
- package/packages/dd-trace/src/proxy.js +5 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +16 -11
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -8
- package/packages/dd-trace/src/telemetry/metrics.js +6 -1
- package/packages/dd-trace/src/util.js +16 -1
- package/version.js +4 -2
- /package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/{code-injection-sensitive-analyzer.js → tainted-range-based-sensitive-analyzer.js} +0 -0
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Component,Origin,License,Copyright
|
|
2
|
+
require,@datadog/libdatadog,Apache license 2.0,Copyright 2024 Datadog Inc.
|
|
2
3
|
require,@datadog/native-appsec,Apache license 2.0,Copyright 2018 Datadog Inc.
|
|
3
4
|
require,@datadog/native-metrics,Apache license 2.0,Copyright 2018 Datadog Inc.
|
|
4
5
|
require,@datadog/native-iast-rewriter,Apache license 2.0,Copyright 2018 Datadog Inc.
|
|
@@ -7,6 +8,7 @@ require,@datadog/pprof,Apache license 2.0,Copyright 2019 Google Inc.
|
|
|
7
8
|
require,@datadog/sketches-js,Apache license 2.0,Copyright 2020 Datadog Inc.
|
|
8
9
|
require,@opentelemetry/api,Apache license 2.0,Copyright OpenTelemetry Authors
|
|
9
10
|
require,@opentelemetry/core,Apache license 2.0,Copyright OpenTelemetry Authors
|
|
11
|
+
require,@isaacs/ttlcache,ISC,Copyright (c) 2022-2023 - Isaac Z. Schlueter and Contributors
|
|
10
12
|
require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
|
|
11
13
|
require,dc-polyfill,MIT,Copyright 2023 Datadog Inc.
|
|
12
14
|
require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
|
package/index.d.ts
CHANGED
|
@@ -662,19 +662,13 @@ declare namespace tracer {
|
|
|
662
662
|
mode?: 'safe' | 'extended' | 'disabled'
|
|
663
663
|
},
|
|
664
664
|
/**
|
|
665
|
-
* Configuration for Api Security
|
|
665
|
+
* Configuration for Api Security
|
|
666
666
|
*/
|
|
667
667
|
apiSecurity?: {
|
|
668
668
|
/** Whether to enable Api Security.
|
|
669
|
-
* @default
|
|
669
|
+
* @default true
|
|
670
670
|
*/
|
|
671
671
|
enabled?: boolean,
|
|
672
|
-
|
|
673
|
-
/** Controls the request sampling rate (between 0 and 1) in which Api Security is triggered.
|
|
674
|
-
* The value will be coerced back if it's outside of the 0-1 range.
|
|
675
|
-
* @default 0.1
|
|
676
|
-
*/
|
|
677
|
-
requestSampling?: number
|
|
678
672
|
},
|
|
679
673
|
/**
|
|
680
674
|
* Configuration for RASP
|
|
@@ -1043,6 +1037,14 @@ declare namespace tracer {
|
|
|
1043
1037
|
* @default code => code < 500
|
|
1044
1038
|
*/
|
|
1045
1039
|
validateStatus?: (code: number) => boolean;
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Enable injection of tracing headers into requests signed with AWS IAM headers.
|
|
1043
|
+
* Disable this if you get AWS signature errors (HTTP 403).
|
|
1044
|
+
*
|
|
1045
|
+
* @default false
|
|
1046
|
+
*/
|
|
1047
|
+
enablePropagationWithAmazonHeaders?: boolean;
|
|
1046
1048
|
}
|
|
1047
1049
|
|
|
1048
1050
|
/** @hidden */
|
package/init.js
CHANGED
|
@@ -1,58 +1,71 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const Module = require('module')
|
|
5
|
-
const semver = require('semver')
|
|
6
|
-
const log = require('./packages/dd-trace/src/log')
|
|
7
|
-
const { isTrue } = require('./packages/dd-trace/src/util')
|
|
8
|
-
const telemetry = require('./packages/dd-trace/src/telemetry/init-telemetry')
|
|
3
|
+
/* eslint-disable no-var */
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
let clobberBailout = false
|
|
12
|
-
const forced = isTrue(process.env.DD_INJECT_FORCE)
|
|
5
|
+
var NODE_MAJOR = require('./version').NODE_MAJOR
|
|
13
6
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
7
|
+
// We use several things that are not supported by older versions of Node:
|
|
8
|
+
// - AsyncLocalStorage
|
|
9
|
+
// - The `semver` module
|
|
10
|
+
// - dc-polyfill
|
|
11
|
+
// - Mocha (for testing)
|
|
12
|
+
// and probably others.
|
|
13
|
+
// TODO: Remove all these dependencies so that we can report telemetry.
|
|
14
|
+
if (NODE_MAJOR >= 12) {
|
|
15
|
+
var path = require('path')
|
|
16
|
+
var Module = require('module')
|
|
17
|
+
var semver = require('semver')
|
|
18
|
+
var log = require('./packages/dd-trace/src/log')
|
|
19
|
+
var isTrue = require('./packages/dd-trace/src/util').isTrue
|
|
20
|
+
var telemetry = require('./packages/dd-trace/src/telemetry/init-telemetry')
|
|
21
|
+
|
|
22
|
+
var initBailout = false
|
|
23
|
+
var clobberBailout = false
|
|
24
|
+
var forced = isTrue(process.env.DD_INJECT_FORCE)
|
|
25
|
+
|
|
26
|
+
if (process.env.DD_INJECTION_ENABLED) {
|
|
27
|
+
// If we're running via single-step install, and we're not in the app's
|
|
28
|
+
// node_modules, then we should not initialize the tracer. This prevents
|
|
29
|
+
// single-step-installed tracer from clobbering the manually-installed tracer.
|
|
30
|
+
var resolvedInApp
|
|
31
|
+
var entrypoint = process.argv[1]
|
|
32
|
+
try {
|
|
33
|
+
resolvedInApp = Module.createRequire(entrypoint).resolve('dd-trace')
|
|
34
|
+
} catch (e) {
|
|
35
|
+
// Ignore. If we can't resolve the module, we assume it's not in the app.
|
|
36
|
+
}
|
|
37
|
+
if (resolvedInApp) {
|
|
38
|
+
var ourselves = path.join(__dirname, 'index.js')
|
|
39
|
+
if (ourselves !== resolvedInApp) {
|
|
40
|
+
clobberBailout = true
|
|
41
|
+
}
|
|
29
42
|
}
|
|
30
|
-
}
|
|
31
43
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
// If we're running via single-step install, and the runtime doesn't match
|
|
45
|
+
// the engines field in package.json, then we should not initialize the tracer.
|
|
46
|
+
if (!clobberBailout) {
|
|
47
|
+
var engines = require('./package.json').engines
|
|
48
|
+
var version = process.versions.node
|
|
49
|
+
if (!semver.satisfies(version, engines.node)) {
|
|
50
|
+
initBailout = true
|
|
51
|
+
telemetry([
|
|
52
|
+
{ name: 'abort', tags: ['reason:incompatible_runtime'] },
|
|
53
|
+
{ name: 'abort.runtime', tags: [] }
|
|
54
|
+
])
|
|
55
|
+
log.info('Aborting application instrumentation due to incompatible_runtime.')
|
|
56
|
+
log.info('Found incompatible runtime nodejs ' + version + ', Supported runtimes: nodejs ' + engines.node + '.')
|
|
57
|
+
if (forced) {
|
|
58
|
+
log.info('DD_INJECT_FORCE enabled, allowing unsupported runtimes and continuing.')
|
|
59
|
+
}
|
|
47
60
|
}
|
|
48
61
|
}
|
|
49
62
|
}
|
|
50
|
-
}
|
|
51
63
|
|
|
52
|
-
if (!clobberBailout && (!initBailout || forced)) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
if (!clobberBailout && (!initBailout || forced)) {
|
|
65
|
+
var tracer = require('.')
|
|
66
|
+
tracer.init()
|
|
67
|
+
module.exports = tracer
|
|
68
|
+
telemetry('complete', ['injection_forced:' + (forced && initBailout ? 'true' : 'false')])
|
|
69
|
+
log.info('Application instrumentation bootstrapping complete')
|
|
70
|
+
}
|
|
58
71
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.26.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"type:test": "cd docs && yarn && yarn test",
|
|
16
16
|
"lint": "node scripts/check_licenses.js && eslint . && yarn audit",
|
|
17
17
|
"lint-fix": "node scripts/check_licenses.js && eslint . --fix && yarn audit",
|
|
18
|
+
"release:proposal": "node scripts/release/proposal",
|
|
18
19
|
"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
|
|
19
20
|
"test": "SERVICES=* yarn services && mocha --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
|
|
20
21
|
"test:appsec": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" \"packages/dd-trace/test/appsec/**/*.spec.js\"",
|
|
@@ -81,12 +82,14 @@
|
|
|
81
82
|
"node": ">=18"
|
|
82
83
|
},
|
|
83
84
|
"dependencies": {
|
|
84
|
-
"@datadog/
|
|
85
|
+
"@datadog/libdatadog": "^0.2.2",
|
|
86
|
+
"@datadog/native-appsec": "8.3.0",
|
|
85
87
|
"@datadog/native-iast-rewriter": "2.5.0",
|
|
86
88
|
"@datadog/native-iast-taint-tracking": "3.2.0",
|
|
87
89
|
"@datadog/native-metrics": "^3.0.1",
|
|
88
90
|
"@datadog/pprof": "5.4.1",
|
|
89
91
|
"@datadog/sketches-js": "^2.1.0",
|
|
92
|
+
"@isaacs/ttlcache": "^1.4.1",
|
|
90
93
|
"@opentelemetry/api": ">=1.0.0 <1.9.0",
|
|
91
94
|
"@opentelemetry/core": "^1.14.0",
|
|
92
95
|
"crypto-randomuuid": "^1.0.0",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { AsyncLocalStorage } = require('async_hooks')
|
|
4
|
+
|
|
5
|
+
const storages = Object.create(null)
|
|
6
|
+
const legacyStorage = new AsyncLocalStorage()
|
|
7
|
+
|
|
8
|
+
const storage = function (namespace) {
|
|
9
|
+
if (!storages[namespace]) {
|
|
10
|
+
storages[namespace] = new AsyncLocalStorage()
|
|
11
|
+
}
|
|
12
|
+
return storages[namespace]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
storage.disable = legacyStorage.disable.bind(legacyStorage)
|
|
16
|
+
storage.enterWith = legacyStorage.enterWith.bind(legacyStorage)
|
|
17
|
+
storage.exit = legacyStorage.exit.bind(legacyStorage)
|
|
18
|
+
storage.getStore = legacyStorage.getStore.bind(legacyStorage)
|
|
19
|
+
storage.run = legacyStorage.run.bind(legacyStorage)
|
|
20
|
+
|
|
21
|
+
module.exports = storage
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const handlebarsCompileCh = channel('datadog:handlebars:compile:start')
|
|
7
|
+
const handlebarsRegisterPartialCh = channel('datadog:handlebars:register-partial:start')
|
|
8
|
+
|
|
9
|
+
function wrapCompile (compile) {
|
|
10
|
+
return function wrappedCompile (source) {
|
|
11
|
+
if (handlebarsCompileCh.hasSubscribers) {
|
|
12
|
+
handlebarsCompileCh.publish({ source })
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return compile.apply(this, arguments)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function wrapRegisterPartial (registerPartial) {
|
|
20
|
+
return function wrappedRegisterPartial (name, partial) {
|
|
21
|
+
if (handlebarsRegisterPartialCh.hasSubscribers) {
|
|
22
|
+
handlebarsRegisterPartialCh.publish({ partial })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return registerPartial.apply(this, arguments)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
addHook({ name: 'handlebars', file: 'dist/cjs/handlebars/compiler/compiler.js', versions: ['>=4.0.0'] }, compiler => {
|
|
30
|
+
shimmer.wrap(compiler, 'compile', wrapCompile)
|
|
31
|
+
shimmer.wrap(compiler, 'precompile', wrapCompile)
|
|
32
|
+
|
|
33
|
+
return compiler
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
addHook({ name: 'handlebars', file: 'dist/cjs/handlebars/base.js', versions: ['>=4.0.0'] }, base => {
|
|
37
|
+
shimmer.wrap(base.HandlebarsEnvironment.prototype, 'registerPartial', wrapRegisterPartial)
|
|
38
|
+
|
|
39
|
+
return base
|
|
40
|
+
})
|
|
@@ -51,6 +51,7 @@ module.exports = {
|
|
|
51
51
|
'generic-pool': () => require('../generic-pool'),
|
|
52
52
|
graphql: () => require('../graphql'),
|
|
53
53
|
grpc: () => require('../grpc'),
|
|
54
|
+
handlebars: () => require('../handlebars'),
|
|
54
55
|
hapi: () => require('../hapi'),
|
|
55
56
|
http: () => require('../http'),
|
|
56
57
|
http2: () => require('../http2'),
|
|
@@ -105,6 +106,7 @@ module.exports = {
|
|
|
105
106
|
'promise-js': () => require('../promise-js'),
|
|
106
107
|
promise: () => require('../promise'),
|
|
107
108
|
protobufjs: () => require('../protobufjs'),
|
|
109
|
+
pug: () => require('../pug'),
|
|
108
110
|
q: () => require('../q'),
|
|
109
111
|
qs: () => require('../qs'),
|
|
110
112
|
redis: () => require('../redis'),
|
|
@@ -127,6 +127,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
127
127
|
|
|
128
128
|
if (repositoryRoot) {
|
|
129
129
|
this.testSourceFile = getTestSuitePath(context.testPath, repositoryRoot)
|
|
130
|
+
this.repositoryRoot = repositoryRoot
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
this.isEarlyFlakeDetectionEnabled = this.testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled
|
|
@@ -667,10 +668,13 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
|
667
668
|
* controls whether coverage is reported.
|
|
668
669
|
*/
|
|
669
670
|
if (environment.testEnvironmentOptions?._ddTestCodeCoverageEnabled) {
|
|
671
|
+
const root = environment.repositoryRoot || environment.rootDir
|
|
672
|
+
|
|
670
673
|
const coverageFiles = getCoveredFilenamesFromCoverage(environment.global.__coverage__)
|
|
671
|
-
.map(filename => getTestSuitePath(filename,
|
|
674
|
+
.map(filename => getTestSuitePath(filename, root))
|
|
675
|
+
|
|
672
676
|
asyncResource.runInAsyncScope(() => {
|
|
673
|
-
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.
|
|
677
|
+
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.testSourceFile })
|
|
674
678
|
})
|
|
675
679
|
}
|
|
676
680
|
testSuiteFinishCh.publish({ status, errorMessage })
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const pugCompileCh = channel('datadog:pug:compile:start')
|
|
7
|
+
|
|
8
|
+
function wrapCompile (compile) {
|
|
9
|
+
return function wrappedCompile (source) {
|
|
10
|
+
if (pugCompileCh.hasSubscribers) {
|
|
11
|
+
pugCompileCh.publish({ source })
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return compile.apply(this, arguments)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
addHook({ name: 'pug', versions: ['>=2.0.4'] }, compiler => {
|
|
19
|
+
shimmer.wrap(compiler, 'compile', wrapCompile)
|
|
20
|
+
shimmer.wrap(compiler, 'compileClientWithDependenciesTracked', wrapCompile)
|
|
21
|
+
|
|
22
|
+
return compiler
|
|
23
|
+
})
|
|
@@ -112,7 +112,6 @@ function createWrapRouterMethod (name) {
|
|
|
112
112
|
path: pattern instanceof RegExp ? `(${pattern})` : pattern,
|
|
113
113
|
test: layer => {
|
|
114
114
|
const matchers = layerMatchers.get(layer)
|
|
115
|
-
|
|
116
115
|
return !isFastStar(layer, matchers) &&
|
|
117
116
|
!isFastSlash(layer, matchers) &&
|
|
118
117
|
cachedPathToRegExp(pattern).test(layer.path)
|
|
@@ -121,7 +120,7 @@ function createWrapRouterMethod (name) {
|
|
|
121
120
|
}
|
|
122
121
|
|
|
123
122
|
function isFastStar (layer, matchers) {
|
|
124
|
-
if (layer.regexp
|
|
123
|
+
if (layer.regexp?.fast_star !== undefined) {
|
|
125
124
|
return layer.regexp.fast_star
|
|
126
125
|
}
|
|
127
126
|
|
|
@@ -129,7 +128,7 @@ function createWrapRouterMethod (name) {
|
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
function isFastSlash (layer, matchers) {
|
|
132
|
-
if (layer.regexp
|
|
131
|
+
if (layer.regexp?.fast_slash !== undefined) {
|
|
133
132
|
return layer.regexp.fast_slash
|
|
134
133
|
}
|
|
135
134
|
|
|
@@ -93,6 +93,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
93
93
|
this.responseExtractDSMContext(operation, params, response.data ?? response, span)
|
|
94
94
|
}
|
|
95
95
|
this.addResponseTags(span, response)
|
|
96
|
+
this.addSpanPointers(span, response)
|
|
96
97
|
this.finish(span, response, response.error)
|
|
97
98
|
})
|
|
98
99
|
}
|
|
@@ -101,6 +102,10 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
101
102
|
// implemented by subclasses, or not
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
addSpanPointers (span, response) {
|
|
106
|
+
// Optionally implemented by subclasses, for services where we're unable to inject trace context
|
|
107
|
+
}
|
|
108
|
+
|
|
104
109
|
operationFromRequest (request) {
|
|
105
110
|
// can be overriden by subclasses
|
|
106
111
|
return this.operationName({
|
|
@@ -42,7 +42,8 @@ class Kinesis extends BaseAwsSdkPlugin {
|
|
|
42
42
|
{},
|
|
43
43
|
this.requestTags.get(request) || {},
|
|
44
44
|
{ 'span.kind': 'server' }
|
|
45
|
-
)
|
|
45
|
+
),
|
|
46
|
+
extractedLinks: responseExtraction.maybeChildOf._links
|
|
46
47
|
}
|
|
47
48
|
span = plugin.tracer.startSpan('aws.response', options)
|
|
48
49
|
this.enter(span, store)
|
|
@@ -113,14 +114,15 @@ class Kinesis extends BaseAwsSdkPlugin {
|
|
|
113
114
|
response.Records.forEach(record => {
|
|
114
115
|
const parsedAttributes = JSON.parse(Buffer.from(record.Data).toString())
|
|
115
116
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
) {
|
|
119
|
-
const payloadSize = getSizeOrZero(record.Data)
|
|
117
|
+
const payloadSize = getSizeOrZero(record.Data)
|
|
118
|
+
if (parsedAttributes?._datadog) {
|
|
120
119
|
this.tracer.decodeDataStreamsContext(parsedAttributes._datadog)
|
|
121
|
-
this.tracer
|
|
122
|
-
.setCheckpoint(['direction:in', `topic:${streamName}`, 'type:kinesis'], span, payloadSize)
|
|
123
120
|
}
|
|
121
|
+
const tags = streamName
|
|
122
|
+
? ['direction:in', `topic:${streamName}`, 'type:kinesis']
|
|
123
|
+
: ['direction:in', 'type:kinesis']
|
|
124
|
+
this.tracer
|
|
125
|
+
.setCheckpoint(tags, span, payloadSize)
|
|
124
126
|
})
|
|
125
127
|
}
|
|
126
128
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const BaseAwsSdkPlugin = require('../base')
|
|
4
|
+
const log = require('../../../dd-trace/src/log')
|
|
5
|
+
const { generatePointerHash } = require('../../../dd-trace/src/util')
|
|
6
|
+
const { S3_PTR_KIND, SPAN_POINTER_DIRECTION } = require('../../../dd-trace/src/constants')
|
|
4
7
|
|
|
5
8
|
class S3 extends BaseAwsSdkPlugin {
|
|
6
9
|
static get id () { return 's3' }
|
|
@@ -18,6 +21,37 @@ class S3 extends BaseAwsSdkPlugin {
|
|
|
18
21
|
bucketname: params.Bucket
|
|
19
22
|
})
|
|
20
23
|
}
|
|
24
|
+
|
|
25
|
+
addSpanPointers (span, response) {
|
|
26
|
+
const request = response?.request
|
|
27
|
+
const operationName = request?.operation
|
|
28
|
+
if (!['putObject', 'copyObject', 'completeMultipartUpload'].includes(operationName)) {
|
|
29
|
+
// We don't create span links for other S3 operations.
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// AWS v2: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html
|
|
34
|
+
// AWS v3: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
|
|
35
|
+
const bucketName = request?.params?.Bucket
|
|
36
|
+
const objectKey = request?.params?.Key
|
|
37
|
+
let eTag =
|
|
38
|
+
response?.ETag || // v3 PutObject & CompleteMultipartUpload
|
|
39
|
+
response?.CopyObjectResult?.ETag || // v3 CopyObject
|
|
40
|
+
response?.data?.ETag || // v2 PutObject & CompleteMultipartUpload
|
|
41
|
+
response?.data?.CopyObjectResult?.ETag // v2 CopyObject
|
|
42
|
+
|
|
43
|
+
if (!bucketName || !objectKey || !eTag) {
|
|
44
|
+
log.debug('Unable to calculate span pointer hash because of missing parameters.')
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// https://github.com/DataDog/dd-span-pointer-rules/blob/main/AWS/S3/Object/README.md
|
|
49
|
+
if (eTag.startsWith('"') && eTag.endsWith('"')) {
|
|
50
|
+
eTag = eTag.slice(1, -1)
|
|
51
|
+
}
|
|
52
|
+
const pointerHash = generatePointerHash([bucketName, objectKey, eTag])
|
|
53
|
+
span.addSpanPointer(S3_PTR_KIND, SPAN_POINTER_DIRECTION.DOWNSTREAM, pointerHash)
|
|
54
|
+
}
|
|
21
55
|
}
|
|
22
56
|
|
|
23
57
|
module.exports = S3
|
|
@@ -33,7 +33,8 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
33
33
|
{},
|
|
34
34
|
this.requestTags.get(request) || {},
|
|
35
35
|
{ 'span.kind': 'server' }
|
|
36
|
-
)
|
|
36
|
+
),
|
|
37
|
+
extractedLinks: contextExtraction.datadogContext._links
|
|
37
38
|
}
|
|
38
39
|
parsedMessageAttributes = contextExtraction.parsedAttributes
|
|
39
40
|
span = plugin.tracer.startSpan('aws.response', options)
|
|
@@ -42,7 +43,7 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
42
43
|
// extract DSM context after as we might not have a parent-child but may have a DSM context
|
|
43
44
|
|
|
44
45
|
this.responseExtractDSMContext(
|
|
45
|
-
request.operation, request.params, response, span || null, { parsedMessageAttributes }
|
|
46
|
+
request.operation, request.params, response, span || null, { parsedAttributes: parsedMessageAttributes }
|
|
46
47
|
)
|
|
47
48
|
})
|
|
48
49
|
|
|
@@ -195,16 +196,16 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
195
196
|
parsedAttributes = this.parseDatadogAttributes(message.MessageAttributes._datadog)
|
|
196
197
|
}
|
|
197
198
|
}
|
|
199
|
+
const payloadSize = getHeadersSize({
|
|
200
|
+
Body: message.Body,
|
|
201
|
+
MessageAttributes: message.MessageAttributes
|
|
202
|
+
})
|
|
203
|
+
const queue = params.QueueUrl.split('/').pop()
|
|
198
204
|
if (parsedAttributes) {
|
|
199
|
-
const payloadSize = getHeadersSize({
|
|
200
|
-
Body: message.Body,
|
|
201
|
-
MessageAttributes: message.MessageAttributes
|
|
202
|
-
})
|
|
203
|
-
const queue = params.QueueUrl.split('/').pop()
|
|
204
205
|
this.tracer.decodeDataStreamsContext(parsedAttributes)
|
|
205
|
-
this.tracer
|
|
206
|
-
.setCheckpoint(['direction:in', `topic:${queue}`, 'type:sqs'], span, payloadSize)
|
|
207
206
|
}
|
|
207
|
+
this.tracer
|
|
208
|
+
.setCheckpoint(['direction:in', `topic:${queue}`, 'type:sqs'], span, payloadSize)
|
|
208
209
|
})
|
|
209
210
|
}
|
|
210
211
|
|
|
@@ -654,55 +654,69 @@ class CypressPlugin {
|
|
|
654
654
|
return this.activeTestSpan ? { traceId: this.activeTestSpan.context().toTraceId() } : {}
|
|
655
655
|
},
|
|
656
656
|
'dd:afterEach': ({ test, coverage }) => {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
this.activeTestSpan.setTag('error', error)
|
|
680
|
-
}
|
|
681
|
-
if (isRUMActive) {
|
|
682
|
-
this.activeTestSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
683
|
-
}
|
|
684
|
-
if (testSourceLine) {
|
|
685
|
-
this.activeTestSpan.setTag(TEST_SOURCE_START, testSourceLine)
|
|
686
|
-
}
|
|
687
|
-
if (isNew) {
|
|
688
|
-
this.activeTestSpan.setTag(TEST_IS_NEW, 'true')
|
|
689
|
-
if (isEfdRetry) {
|
|
690
|
-
this.activeTestSpan.setTag(TEST_IS_RETRY, 'true')
|
|
691
|
-
}
|
|
657
|
+
if (!this.activeTestSpan) {
|
|
658
|
+
log.warn('There is no active test span in dd:afterEach handler')
|
|
659
|
+
return null
|
|
660
|
+
}
|
|
661
|
+
const {
|
|
662
|
+
state,
|
|
663
|
+
error,
|
|
664
|
+
isRUMActive,
|
|
665
|
+
testSourceLine,
|
|
666
|
+
testSuite,
|
|
667
|
+
testSuiteAbsolutePath,
|
|
668
|
+
testName,
|
|
669
|
+
isNew,
|
|
670
|
+
isEfdRetry
|
|
671
|
+
} = test
|
|
672
|
+
if (coverage && this.isCodeCoverageEnabled && this.tracer._tracer._exporter?.exportCoverage) {
|
|
673
|
+
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
674
|
+
const relativeCoverageFiles = [...coverageFiles, testSuiteAbsolutePath].map(
|
|
675
|
+
file => getTestSuitePath(file, this.repositoryRoot || this.rootDir)
|
|
676
|
+
)
|
|
677
|
+
if (!relativeCoverageFiles.length) {
|
|
678
|
+
incrementCountMetric(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
692
679
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
680
|
+
distributionMetric(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
681
|
+
const { _traceId, _spanId } = this.testSuiteSpan.context()
|
|
682
|
+
const formattedCoverage = {
|
|
683
|
+
sessionId: _traceId,
|
|
684
|
+
suiteId: _spanId,
|
|
685
|
+
testId: this.activeTestSpan.context()._spanId,
|
|
686
|
+
files: relativeCoverageFiles
|
|
698
687
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
688
|
+
this.tracer._tracer._exporter.exportCoverage(formattedCoverage)
|
|
689
|
+
}
|
|
690
|
+
const testStatus = CYPRESS_STATUS_TO_TEST_STATUS[state]
|
|
691
|
+
this.activeTestSpan.setTag(TEST_STATUS, testStatus)
|
|
692
|
+
|
|
693
|
+
if (error) {
|
|
694
|
+
this.activeTestSpan.setTag('error', error)
|
|
695
|
+
}
|
|
696
|
+
if (isRUMActive) {
|
|
697
|
+
this.activeTestSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
698
|
+
}
|
|
699
|
+
if (testSourceLine) {
|
|
700
|
+
this.activeTestSpan.setTag(TEST_SOURCE_START, testSourceLine)
|
|
701
|
+
}
|
|
702
|
+
if (isNew) {
|
|
703
|
+
this.activeTestSpan.setTag(TEST_IS_NEW, 'true')
|
|
704
|
+
if (isEfdRetry) {
|
|
705
|
+
this.activeTestSpan.setTag(TEST_IS_RETRY, 'true')
|
|
703
706
|
}
|
|
704
|
-
// test spans are finished at after:spec
|
|
705
707
|
}
|
|
708
|
+
const finishedTest = {
|
|
709
|
+
testName,
|
|
710
|
+
testStatus,
|
|
711
|
+
finishTime: this.activeTestSpan._getTime(), // we store the finish time here
|
|
712
|
+
testSpan: this.activeTestSpan
|
|
713
|
+
}
|
|
714
|
+
if (this.finishedTestsByFile[testSuite]) {
|
|
715
|
+
this.finishedTestsByFile[testSuite].push(finishedTest)
|
|
716
|
+
} else {
|
|
717
|
+
this.finishedTestsByFile[testSuite] = [finishedTest]
|
|
718
|
+
}
|
|
719
|
+
// test spans are finished at after:spec
|
|
706
720
|
this.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test', {
|
|
707
721
|
hasCodeOwners: !!this.activeTestSpan.context()._tags[TEST_CODE_OWNERS],
|
|
708
722
|
isNew,
|