dd-trace 4.18.0 → 5.6.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/CONTRIBUTING.md +98 -0
- package/LICENSE-3rdparty.csv +4 -5
- package/MIGRATING.md +15 -0
- package/README.md +20 -140
- package/ci/cypress/after-run.js +1 -0
- package/ci/cypress/after-spec.js +1 -0
- package/ci/init.js +1 -4
- package/ext/kinds.d.ts +1 -0
- package/ext/kinds.js +2 -1
- package/ext/tags.d.ts +2 -1
- package/ext/tags.js +6 -1
- package/index.d.ts +1523 -1460
- package/package.json +19 -19
- package/packages/datadog-core/src/storage/async_resource.js +1 -1
- package/packages/datadog-core/src/utils/src/get.js +11 -0
- package/packages/datadog-core/src/utils/src/has.js +14 -0
- package/packages/datadog-core/src/utils/src/kebabcase.js +16 -0
- package/packages/datadog-core/src/utils/src/pick.js +11 -0
- package/packages/datadog-core/src/utils/src/set.js +16 -0
- package/packages/datadog-core/src/utils/src/uniq.js +5 -0
- package/packages/datadog-esbuild/index.js +1 -20
- package/packages/datadog-instrumentations/src/aerospike.js +47 -0
- package/packages/datadog-instrumentations/src/amqplib.js +2 -2
- package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
- package/packages/datadog-instrumentations/src/child_process.js +150 -0
- package/packages/datadog-instrumentations/src/couchbase.js +5 -4
- package/packages/datadog-instrumentations/src/crypto.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +163 -46
- package/packages/datadog-instrumentations/src/dns.js +2 -1
- package/packages/datadog-instrumentations/src/express.js +20 -0
- package/packages/datadog-instrumentations/src/graphql.js +18 -4
- package/packages/datadog-instrumentations/src/grpc/client.js +56 -36
- package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -3
- package/packages/datadog-instrumentations/src/helpers/instrument.js +9 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +19 -3
- package/packages/datadog-instrumentations/src/http/client.js +12 -2
- package/packages/datadog-instrumentations/src/http/server.js +7 -4
- package/packages/datadog-instrumentations/src/http2/client.js +3 -1
- package/packages/datadog-instrumentations/src/http2/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +239 -52
- package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
- package/packages/datadog-instrumentations/src/mocha.js +154 -18
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
- package/packages/datadog-instrumentations/src/mongoose.js +23 -10
- package/packages/datadog-instrumentations/src/mquery.js +65 -0
- package/packages/datadog-instrumentations/src/net.js +10 -2
- package/packages/datadog-instrumentations/src/next.js +35 -9
- package/packages/datadog-instrumentations/src/playwright.js +110 -16
- package/packages/datadog-instrumentations/src/restify.js +14 -1
- package/packages/datadog-instrumentations/src/rhea.js +15 -9
- package/packages/datadog-plugin-aerospike/src/index.js +113 -0
- package/packages/datadog-plugin-amqplib/src/consumer.js +14 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +13 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +163 -27
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +46 -8
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +129 -22
- package/packages/datadog-plugin-child_process/src/index.js +91 -0
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +125 -0
- package/packages/datadog-plugin-cucumber/src/index.js +70 -13
- package/packages/datadog-plugin-cypress/src/after-run.js +3 -0
- package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +625 -0
- package/packages/datadog-plugin-cypress/src/plugin.js +6 -454
- package/packages/datadog-plugin-cypress/src/support.js +50 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -0
- package/packages/datadog-plugin-graphql/src/index.js +1 -6
- package/packages/datadog-plugin-graphql/src/resolve.js +28 -18
- package/packages/datadog-plugin-grpc/src/client.js +16 -2
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +19 -2
- package/packages/datadog-plugin-jest/src/index.js +118 -12
- package/packages/datadog-plugin-jest/src/util.js +38 -16
- package/packages/datadog-plugin-kafkajs/src/consumer.js +76 -6
- package/packages/datadog-plugin-kafkajs/src/producer.js +64 -8
- package/packages/datadog-plugin-mocha/src/index.js +87 -17
- package/packages/datadog-plugin-next/src/index.js +40 -14
- package/packages/datadog-plugin-playwright/src/index.js +71 -8
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -1
- package/packages/datadog-plugin-rhea/src/producer.js +10 -0
- package/packages/dd-trace/src/appsec/activation.js +29 -0
- package/packages/dd-trace/src/appsec/addresses.js +5 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +61 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
- package/packages/dd-trace/src/appsec/blocking.js +95 -43
- package/packages/dd-trace/src/appsec/channels.js +7 -3
- package/packages/dd-trace/src/appsec/graphql.js +146 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +22 -17
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -28
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +10 -6
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-randomness-analyzer.js +19 -0
- package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +90 -0
- package/packages/dd-trace/src/appsec/iast/context/kafka-ctx-plugin.js +14 -0
- package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +13 -2
- package/packages/dd-trace/src/appsec/iast/index.js +15 -5
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
- package/packages/dd-trace/src/appsec/iast/path-line.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +2 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +53 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +10 -46
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +13 -9
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +47 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +19 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +3 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +41 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +2 -0
- package/packages/dd-trace/src/appsec/index.js +49 -33
- package/packages/dd-trace/src/appsec/recommended.json +1763 -106
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +42 -16
- package/packages/dd-trace/src/appsec/remote_config/manager.js +9 -8
- package/packages/dd-trace/src/appsec/reporter.js +51 -34
- package/packages/dd-trace/src/appsec/rule_manager.js +11 -8
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +28 -13
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
- package/packages/dd-trace/src/ci-visibility/{intelligent-test-runner/get-itr-configuration.js → early-flake-detection/get-known-tests.js} +17 -22
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +25 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +2 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +95 -37
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +134 -61
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +37 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +131 -0
- package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
- package/packages/dd-trace/src/config.js +561 -470
- package/packages/dd-trace/src/data_streams_context.js +1 -1
- package/packages/dd-trace/src/datastreams/pathway.js +58 -1
- package/packages/dd-trace/src/datastreams/processor.js +196 -27
- package/packages/dd-trace/src/datastreams/writer.js +11 -5
- package/packages/dd-trace/src/dogstatsd.js +3 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -6
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
- package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
- package/packages/dd-trace/src/exporters/common/request.js +21 -3
- package/packages/dd-trace/src/format.js +30 -2
- package/packages/dd-trace/src/id.js +12 -0
- package/packages/dd-trace/src/iitm.js +1 -1
- package/packages/dd-trace/src/log/channels.js +1 -1
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +104 -4
- package/packages/dd-trace/src/opentelemetry/tracer.js +9 -10
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +16 -7
- package/packages/dd-trace/src/opentracing/span.js +48 -4
- package/packages/dd-trace/src/opentracing/span_context.js +15 -6
- package/packages/dd-trace/src/opentracing/tracer.js +4 -3
- package/packages/dd-trace/src/plugin_manager.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +78 -19
- package/packages/dd-trace/src/plugins/database.js +1 -1
- package/packages/dd-trace/src/plugins/index.js +7 -0
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +6 -19
- package/packages/dd-trace/src/plugins/util/git.js +104 -22
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +7 -6
- package/packages/dd-trace/src/plugins/util/test.js +60 -10
- package/packages/dd-trace/src/plugins/util/url.js +26 -0
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +4 -16
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +30 -38
- package/packages/dd-trace/src/profiler.js +5 -3
- package/packages/dd-trace/src/profiling/config.js +77 -24
- package/packages/dd-trace/src/profiling/exporters/agent.js +77 -31
- package/packages/dd-trace/src/profiling/exporters/file.js +2 -1
- package/packages/dd-trace/src/profiling/profiler.js +33 -22
- package/packages/dd-trace/src/profiling/profilers/events.js +270 -0
- package/packages/dd-trace/src/profiling/profilers/shared.js +45 -0
- package/packages/dd-trace/src/profiling/profilers/space.js +18 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +146 -70
- package/packages/dd-trace/src/proxy.js +56 -24
- package/packages/dd-trace/src/ritm.js +1 -1
- package/packages/dd-trace/src/sampling_rule.js +130 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/span_processor.js +9 -1
- package/packages/dd-trace/src/span_sampler.js +6 -64
- package/packages/dd-trace/src/spanleak.js +98 -0
- package/packages/dd-trace/src/startup-log.js +7 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +56 -10
- package/packages/dd-trace/src/telemetry/index.js +182 -53
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/telemetry/send-data.js +65 -7
- package/packages/dd-trace/src/tracer.js +12 -5
- package/register.js +4 -0
- package/scripts/install_plugin_modules.js +11 -3
- package/scripts/st.js +105 -0
- package/packages/datadog-instrumentations/src/child-process.js +0 -30
- package/packages/dd-trace/src/plugins/util/exec.js +0 -13
- package/packages/diagnostics_channel/index.js +0 -3
- package/packages/diagnostics_channel/src/index.js +0 -121
|
@@ -58,7 +58,7 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
58
58
|
span._spanContext._trace.record = false
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
if (
|
|
61
|
+
if (this.shouldInjectTraceHeaders(options, uri)) {
|
|
62
62
|
this.tracer.inject(span, HTTP_HEADERS, options.headers)
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -71,6 +71,18 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
71
71
|
return message.currentStore
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
shouldInjectTraceHeaders (options, uri) {
|
|
75
|
+
if (hasAmazonSignature(options) && !this.config.enablePropagationWithAmazonHeaders) {
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!this.config.propagationFilter(uri)) {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
bindAsyncStart ({ parentStore }) {
|
|
75
87
|
return parentStore
|
|
76
88
|
}
|
|
@@ -98,7 +110,7 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
98
110
|
span.finish()
|
|
99
111
|
}
|
|
100
112
|
|
|
101
|
-
error ({ span, error }) {
|
|
113
|
+
error ({ span, error, args, customRequestTimeout }) {
|
|
102
114
|
if (!span) return
|
|
103
115
|
if (error) {
|
|
104
116
|
span.addTags({
|
|
@@ -107,6 +119,11 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
107
119
|
[ERROR_STACK]: error.stack
|
|
108
120
|
})
|
|
109
121
|
} else {
|
|
122
|
+
// conditions for no error:
|
|
123
|
+
// 1. not using a custom agent instance with custom timeout specified
|
|
124
|
+
// 2. no invocation of `req.setTimeout`
|
|
125
|
+
if (!args.options.agent?.options?.timeout && !customRequestTimeout) return
|
|
126
|
+
|
|
110
127
|
span.setTag('error', 1)
|
|
111
128
|
}
|
|
112
129
|
}
|
|
@@ -12,10 +12,27 @@ const {
|
|
|
12
12
|
TEST_FRAMEWORK_VERSION,
|
|
13
13
|
TEST_SOURCE_START,
|
|
14
14
|
TEST_ITR_UNSKIPPABLE,
|
|
15
|
-
TEST_ITR_FORCED_RUN
|
|
15
|
+
TEST_ITR_FORCED_RUN,
|
|
16
|
+
TEST_CODE_OWNERS,
|
|
17
|
+
ITR_CORRELATION_ID,
|
|
18
|
+
TEST_SOURCE_FILE,
|
|
19
|
+
TEST_IS_NEW,
|
|
20
|
+
TEST_EARLY_FLAKE_IS_RETRY,
|
|
21
|
+
TEST_EARLY_FLAKE_IS_ENABLED,
|
|
22
|
+
JEST_DISPLAY_NAME
|
|
16
23
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
17
24
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
18
25
|
const id = require('../../dd-trace/src/id')
|
|
26
|
+
const {
|
|
27
|
+
TELEMETRY_EVENT_CREATED,
|
|
28
|
+
TELEMETRY_EVENT_FINISHED,
|
|
29
|
+
TELEMETRY_CODE_COVERAGE_STARTED,
|
|
30
|
+
TELEMETRY_CODE_COVERAGE_FINISHED,
|
|
31
|
+
TELEMETRY_ITR_FORCED_TO_RUN,
|
|
32
|
+
TELEMETRY_CODE_COVERAGE_EMPTY,
|
|
33
|
+
TELEMETRY_ITR_UNSKIPPABLE,
|
|
34
|
+
TELEMETRY_CODE_COVERAGE_NUM_FILES
|
|
35
|
+
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
19
36
|
|
|
20
37
|
const isJestWorker = !!process.env.JEST_WORKER_ID
|
|
21
38
|
|
|
@@ -27,6 +44,20 @@ class JestPlugin extends CiPlugin {
|
|
|
27
44
|
return 'jest'
|
|
28
45
|
}
|
|
29
46
|
|
|
47
|
+
// The lists are the same for every test suite, so we can cache them
|
|
48
|
+
getUnskippableSuites (unskippableSuitesList) {
|
|
49
|
+
if (!this.unskippableSuites) {
|
|
50
|
+
this.unskippableSuites = JSON.parse(unskippableSuitesList)
|
|
51
|
+
}
|
|
52
|
+
return this.unskippableSuites
|
|
53
|
+
}
|
|
54
|
+
getForcedToRunSuites (forcedToRunSuitesList) {
|
|
55
|
+
if (!this.forcedToRunSuites) {
|
|
56
|
+
this.forcedToRunSuites = JSON.parse(forcedToRunSuitesList)
|
|
57
|
+
}
|
|
58
|
+
return this.forcedToRunSuites
|
|
59
|
+
}
|
|
60
|
+
|
|
30
61
|
constructor (...args) {
|
|
31
62
|
super(...args)
|
|
32
63
|
|
|
@@ -55,7 +86,9 @@ class JestPlugin extends CiPlugin {
|
|
|
55
86
|
numSkippedSuites,
|
|
56
87
|
hasUnskippableSuites,
|
|
57
88
|
hasForcedToRunSuites,
|
|
58
|
-
error
|
|
89
|
+
error,
|
|
90
|
+
isEarlyFlakeDetectionEnabled,
|
|
91
|
+
onDone
|
|
59
92
|
}) => {
|
|
60
93
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
61
94
|
this.testModuleSpan.setTag(TEST_STATUS, status)
|
|
@@ -80,30 +113,47 @@ class JestPlugin extends CiPlugin {
|
|
|
80
113
|
}
|
|
81
114
|
)
|
|
82
115
|
|
|
116
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
117
|
+
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_IS_ENABLED, 'true')
|
|
118
|
+
}
|
|
119
|
+
|
|
83
120
|
this.testModuleSpan.finish()
|
|
121
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
84
122
|
this.testSessionSpan.finish()
|
|
123
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
85
124
|
finishAllTraceSpans(this.testSessionSpan)
|
|
86
|
-
|
|
125
|
+
|
|
126
|
+
this.tracer._exporter.flush(() => {
|
|
127
|
+
if (onDone) {
|
|
128
|
+
onDone()
|
|
129
|
+
}
|
|
130
|
+
})
|
|
87
131
|
})
|
|
88
132
|
|
|
89
133
|
// Test suites can be run in a different process from jest's main one.
|
|
90
134
|
// This subscriber changes the configuration objects from jest to inject the trace id
|
|
91
|
-
// of the test session to the processes that run the test suites.
|
|
135
|
+
// of the test session to the processes that run the test suites, and other data.
|
|
92
136
|
this.addSub('ci:jest:session:configuration', configs => {
|
|
93
137
|
configs.forEach(config => {
|
|
94
138
|
config._ddTestSessionId = this.testSessionSpan.context().toTraceId()
|
|
95
139
|
config._ddTestModuleId = this.testModuleSpan.context().toSpanId()
|
|
96
140
|
config._ddTestCommand = this.testSessionSpan.context()._tags[TEST_COMMAND]
|
|
141
|
+
config._ddItrCorrelationId = this.itrCorrelationId
|
|
142
|
+
config._ddIsEarlyFlakeDetectionEnabled = !!this.libraryConfig?.isEarlyFlakeDetectionEnabled
|
|
143
|
+
config._ddEarlyFlakeDetectionNumRetries = this.libraryConfig?.earlyFlakeDetectionNumRetries ?? 0
|
|
144
|
+
config._ddRepositoryRoot = this.repositoryRoot
|
|
97
145
|
})
|
|
98
146
|
})
|
|
99
147
|
|
|
100
|
-
this.addSub('ci:jest:test-suite:start', ({ testSuite, testEnvironmentOptions, frameworkVersion }) => {
|
|
148
|
+
this.addSub('ci:jest:test-suite:start', ({ testSuite, testEnvironmentOptions, frameworkVersion, displayName }) => {
|
|
101
149
|
const {
|
|
102
150
|
_ddTestSessionId: testSessionId,
|
|
103
151
|
_ddTestCommand: testCommand,
|
|
104
152
|
_ddTestModuleId: testModuleId,
|
|
153
|
+
_ddItrCorrelationId: itrCorrelationId,
|
|
105
154
|
_ddForcedToRun,
|
|
106
|
-
_ddUnskippable
|
|
155
|
+
_ddUnskippable,
|
|
156
|
+
_ddTestCodeCoverageEnabled
|
|
107
157
|
} = testEnvironmentOptions
|
|
108
158
|
|
|
109
159
|
const testSessionSpanContext = this.tracer.extract('text_map', {
|
|
@@ -114,11 +164,25 @@ class JestPlugin extends CiPlugin {
|
|
|
114
164
|
const testSuiteMetadata = getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, 'jest')
|
|
115
165
|
|
|
116
166
|
if (_ddUnskippable) {
|
|
117
|
-
|
|
167
|
+
const unskippableSuites = this.getUnskippableSuites(_ddUnskippable)
|
|
168
|
+
if (unskippableSuites[testSuite]) {
|
|
169
|
+
this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
170
|
+
testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
171
|
+
}
|
|
118
172
|
if (_ddForcedToRun) {
|
|
119
|
-
|
|
173
|
+
const forcedToRunSuites = this.getForcedToRunSuites(_ddForcedToRun)
|
|
174
|
+
if (forcedToRunSuites[testSuite]) {
|
|
175
|
+
this.telemetry.count(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
176
|
+
testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
177
|
+
}
|
|
120
178
|
}
|
|
121
179
|
}
|
|
180
|
+
if (itrCorrelationId) {
|
|
181
|
+
testSuiteMetadata[ITR_CORRELATION_ID] = itrCorrelationId
|
|
182
|
+
}
|
|
183
|
+
if (displayName) {
|
|
184
|
+
testSuiteMetadata[JEST_DISPLAY_NAME] = displayName
|
|
185
|
+
}
|
|
122
186
|
|
|
123
187
|
this.testSuiteSpan = this.tracer.startSpan('jest.test_suite', {
|
|
124
188
|
childOf: testSessionSpanContext,
|
|
@@ -128,6 +192,10 @@ class JestPlugin extends CiPlugin {
|
|
|
128
192
|
...testSuiteMetadata
|
|
129
193
|
}
|
|
130
194
|
})
|
|
195
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
196
|
+
if (_ddTestCodeCoverageEnabled) {
|
|
197
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_STARTED, 'suite', { library: 'istanbul' })
|
|
198
|
+
}
|
|
131
199
|
})
|
|
132
200
|
|
|
133
201
|
this.addSub('ci:jest:worker-report:trace', traces => {
|
|
@@ -164,6 +232,7 @@ class JestPlugin extends CiPlugin {
|
|
|
164
232
|
this.testSuiteSpan.setTag('error', new Error(errorMessage))
|
|
165
233
|
}
|
|
166
234
|
this.testSuiteSpan.finish()
|
|
235
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
167
236
|
// Suites potentially run in a different process than the session,
|
|
168
237
|
// so calling finishAllTraceSpans on the session span is not enough
|
|
169
238
|
finishAllTraceSpans(this.testSuiteSpan)
|
|
@@ -176,18 +245,26 @@ class JestPlugin extends CiPlugin {
|
|
|
176
245
|
})
|
|
177
246
|
|
|
178
247
|
/**
|
|
179
|
-
* This can't use `this.
|
|
248
|
+
* This can't use `this.libraryConfig` like `ci:mocha:test-suite:code-coverage`
|
|
180
249
|
* because this subscription happens in a different process from the one
|
|
181
250
|
* fetching the ITR config.
|
|
182
251
|
*/
|
|
183
|
-
this.addSub('ci:jest:test-suite:code-coverage', (coverageFiles) => {
|
|
252
|
+
this.addSub('ci:jest:test-suite:code-coverage', ({ coverageFiles, testSuite }) => {
|
|
253
|
+
if (!coverageFiles.length) {
|
|
254
|
+
this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
255
|
+
}
|
|
256
|
+
const files = [...coverageFiles, testSuite]
|
|
257
|
+
|
|
184
258
|
const { _traceId, _spanId } = this.testSuiteSpan.context()
|
|
185
259
|
const formattedCoverage = {
|
|
186
260
|
sessionId: _traceId,
|
|
187
261
|
suiteId: _spanId,
|
|
188
|
-
files
|
|
262
|
+
files
|
|
189
263
|
}
|
|
264
|
+
|
|
190
265
|
this.tracer._exporter.exportCoverage(formattedCoverage)
|
|
266
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
|
|
267
|
+
this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, files.length)
|
|
191
268
|
})
|
|
192
269
|
|
|
193
270
|
this.addSub('ci:jest:test:start', (test) => {
|
|
@@ -204,6 +281,11 @@ class JestPlugin extends CiPlugin {
|
|
|
204
281
|
span.setTag(TEST_SOURCE_START, testStartLine)
|
|
205
282
|
}
|
|
206
283
|
span.finish()
|
|
284
|
+
this.telemetry.ciVisEvent(
|
|
285
|
+
TELEMETRY_EVENT_FINISHED,
|
|
286
|
+
'test',
|
|
287
|
+
{ hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
|
|
288
|
+
)
|
|
207
289
|
finishAllTraceSpans(span)
|
|
208
290
|
})
|
|
209
291
|
|
|
@@ -226,7 +308,18 @@ class JestPlugin extends CiPlugin {
|
|
|
226
308
|
}
|
|
227
309
|
|
|
228
310
|
startTestSpan (test) {
|
|
229
|
-
const {
|
|
311
|
+
const {
|
|
312
|
+
suite,
|
|
313
|
+
name,
|
|
314
|
+
runner,
|
|
315
|
+
displayName,
|
|
316
|
+
testParameters,
|
|
317
|
+
frameworkVersion,
|
|
318
|
+
testStartLine,
|
|
319
|
+
testSourceFile,
|
|
320
|
+
isNew,
|
|
321
|
+
isEfdRetry
|
|
322
|
+
} = test
|
|
230
323
|
|
|
231
324
|
const extraTags = {
|
|
232
325
|
[JEST_TEST_RUNNER]: runner,
|
|
@@ -236,6 +329,19 @@ class JestPlugin extends CiPlugin {
|
|
|
236
329
|
if (testStartLine) {
|
|
237
330
|
extraTags[TEST_SOURCE_START] = testStartLine
|
|
238
331
|
}
|
|
332
|
+
// If for whatever we don't have the source file, we'll fall back to the suite name
|
|
333
|
+
extraTags[TEST_SOURCE_FILE] = testSourceFile || suite
|
|
334
|
+
|
|
335
|
+
if (displayName) {
|
|
336
|
+
extraTags[JEST_DISPLAY_NAME] = displayName
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (isNew) {
|
|
340
|
+
extraTags[TEST_IS_NEW] = 'true'
|
|
341
|
+
if (isEfdRetry) {
|
|
342
|
+
extraTags[TEST_EARLY_FLAKE_IS_RETRY] = 'true'
|
|
343
|
+
}
|
|
344
|
+
}
|
|
239
345
|
|
|
240
346
|
return super.startTestSpan(name, suite, this.testSuiteSpan, extraTags)
|
|
241
347
|
}
|
|
@@ -77,30 +77,52 @@ function isMarkedAsUnskippable (test) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
function getJestSuitesToRun (skippableSuites, originalTests, rootDir) {
|
|
80
|
-
|
|
80
|
+
const unskippableSuites = {}
|
|
81
|
+
const forcedToRunSuites = {}
|
|
82
|
+
|
|
83
|
+
const skippedSuites = []
|
|
84
|
+
const suitesToRun = []
|
|
85
|
+
|
|
86
|
+
for (const test of originalTests) {
|
|
81
87
|
const relativePath = getTestSuitePath(test.path, rootDir)
|
|
82
88
|
const shouldBeSkipped = skippableSuites.includes(relativePath)
|
|
83
|
-
|
|
84
89
|
if (isMarkedAsUnskippable(test)) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (shouldBeSkipped) {
|
|
90
|
-
test.context.config.testEnvironmentOptions['_ddForcedToRun'] = true
|
|
91
|
-
acc.hasForcedToRunSuites = true
|
|
92
|
-
}
|
|
90
|
+
suitesToRun.push(test)
|
|
91
|
+
unskippableSuites[relativePath] = true
|
|
92
|
+
if (shouldBeSkipped) {
|
|
93
|
+
forcedToRunSuites[relativePath] = true
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
+
continue
|
|
95
96
|
}
|
|
96
|
-
|
|
97
97
|
if (shouldBeSkipped) {
|
|
98
|
-
|
|
98
|
+
skippedSuites.push(relativePath)
|
|
99
99
|
} else {
|
|
100
|
-
|
|
100
|
+
suitesToRun.push(test)
|
|
101
101
|
}
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const hasUnskippableSuites = Object.keys(unskippableSuites).length > 0
|
|
105
|
+
const hasForcedToRunSuites = Object.keys(forcedToRunSuites).length > 0
|
|
106
|
+
|
|
107
|
+
if (originalTests.length) {
|
|
108
|
+
// The config object is shared by all tests, so we can just take the first one
|
|
109
|
+
const [test] = originalTests
|
|
110
|
+
if (test?.context?.config?.testEnvironmentOptions) {
|
|
111
|
+
if (hasUnskippableSuites) {
|
|
112
|
+
test.context.config.testEnvironmentOptions._ddUnskippable = JSON.stringify(unskippableSuites)
|
|
113
|
+
}
|
|
114
|
+
if (hasForcedToRunSuites) {
|
|
115
|
+
test.context.config.testEnvironmentOptions._ddForcedToRun = JSON.stringify(forcedToRunSuites)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
skippedSuites,
|
|
122
|
+
suitesToRun,
|
|
123
|
+
hasUnskippableSuites,
|
|
124
|
+
hasForcedToRunSuites
|
|
125
|
+
}
|
|
104
126
|
}
|
|
105
127
|
|
|
106
128
|
module.exports = { getFormattedJestTestParameters, getJestTestName, getJestSuitesToRun, isMarkedAsUnskippable }
|
|
@@ -1,19 +1,71 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const dc = require('dc-polyfill')
|
|
4
|
+
const { getMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
5
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
3
6
|
const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
|
|
4
7
|
|
|
8
|
+
const afterStartCh = dc.channel('dd-trace:kafkajs:consumer:afterStart')
|
|
9
|
+
const beforeFinishCh = dc.channel('dd-trace:kafkajs:consumer:beforeFinish')
|
|
10
|
+
|
|
5
11
|
class KafkajsConsumerPlugin extends ConsumerPlugin {
|
|
6
12
|
static get id () { return 'kafkajs' }
|
|
7
13
|
static get operation () { return 'consume' }
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
constructor () {
|
|
16
|
+
super(...arguments)
|
|
17
|
+
this.addSub('apm:kafkajs:consume:commit', message => this.commit(message))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Transform individual commit details sent by kafkajs' event reporter
|
|
22
|
+
* into actionable backlog items for DSM
|
|
23
|
+
*
|
|
24
|
+
* @typedef {object} ConsumerBacklog
|
|
25
|
+
* @property {number} type
|
|
26
|
+
* @property {string} consumer_group
|
|
27
|
+
* @property {string} topic
|
|
28
|
+
* @property {number} partition
|
|
29
|
+
* @property {number} offset
|
|
30
|
+
*
|
|
31
|
+
* @typedef {object} CommitEventItem
|
|
32
|
+
* @property {string} groupId
|
|
33
|
+
* @property {string} topic
|
|
34
|
+
* @property {number} partition
|
|
35
|
+
* @property {import('kafkajs/utils/long').Long} offset
|
|
36
|
+
*
|
|
37
|
+
* @param {CommitEventItem} commit
|
|
38
|
+
* @returns {ConsumerBacklog}
|
|
39
|
+
*/
|
|
40
|
+
transformCommit (commit) {
|
|
41
|
+
const { groupId, partition, offset, topic } = commit
|
|
42
|
+
return {
|
|
43
|
+
partition,
|
|
44
|
+
topic,
|
|
45
|
+
type: 'kafka_commit',
|
|
46
|
+
offset: Number(offset),
|
|
47
|
+
consumer_group: groupId
|
|
14
48
|
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
commit (commitList) {
|
|
52
|
+
if (!this.config.dsmEnabled) return
|
|
53
|
+
const keys = [
|
|
54
|
+
'consumer_group',
|
|
55
|
+
'type',
|
|
56
|
+
'partition',
|
|
57
|
+
'offset',
|
|
58
|
+
'topic'
|
|
59
|
+
]
|
|
60
|
+
for (const commit of commitList.map(this.transformCommit)) {
|
|
61
|
+
if (keys.some(key => !commit.hasOwnProperty(key))) continue
|
|
62
|
+
this.tracer.setOffset(commit)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
start ({ topic, partition, message, groupId }) {
|
|
15
67
|
const childOf = extract(this.tracer, message.headers)
|
|
16
|
-
this.startSpan({
|
|
68
|
+
const span = this.startSpan({
|
|
17
69
|
childOf,
|
|
18
70
|
resource: topic,
|
|
19
71
|
type: 'worker',
|
|
@@ -26,6 +78,24 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
|
|
|
26
78
|
'kafka.partition': partition
|
|
27
79
|
}
|
|
28
80
|
})
|
|
81
|
+
if (this.config.dsmEnabled && message?.headers && DsmPathwayCodec.contextExists(message.headers)) {
|
|
82
|
+
const payloadSize = getMessageSize(message)
|
|
83
|
+
this.tracer.decodeDataStreamsContext(message.headers)
|
|
84
|
+
this.tracer
|
|
85
|
+
.setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'], span, payloadSize)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (afterStartCh.hasSubscribers) {
|
|
89
|
+
afterStartCh.publish({ topic, partition, message, groupId })
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
finish () {
|
|
94
|
+
if (beforeFinishCh.hasSubscribers) {
|
|
95
|
+
beforeFinishCh.publish()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
super.finish()
|
|
29
99
|
}
|
|
30
100
|
}
|
|
31
101
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
|
|
4
|
-
const {
|
|
4
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
5
|
+
const { getMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
6
|
+
|
|
5
7
|
const BOOTSTRAP_SERVERS_KEY = 'messaging.kafka.bootstrap.servers'
|
|
6
8
|
|
|
7
9
|
class KafkajsProducerPlugin extends ProducerPlugin {
|
|
@@ -9,13 +11,62 @@ class KafkajsProducerPlugin extends ProducerPlugin {
|
|
|
9
11
|
static get operation () { return 'produce' }
|
|
10
12
|
static get peerServicePrecursors () { return [BOOTSTRAP_SERVERS_KEY] }
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
constructor () {
|
|
15
|
+
super(...arguments)
|
|
16
|
+
this.addSub('apm:kafkajs:produce:commit', message => this.commit(message))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Transform individual commit details sent by kafkajs' event reporter
|
|
21
|
+
* into actionable backlog items for DSM
|
|
22
|
+
*
|
|
23
|
+
* @typedef {object} ProducerBacklog
|
|
24
|
+
* @property {number} type
|
|
25
|
+
* @property {string} topic
|
|
26
|
+
* @property {number} partition
|
|
27
|
+
* @property {number} offset
|
|
28
|
+
*
|
|
29
|
+
* @typedef {object} ProducerResponseItem
|
|
30
|
+
* @property {string} topic
|
|
31
|
+
* @property {number} partition
|
|
32
|
+
* @property {import('kafkajs/utils/long').Long} [offset]
|
|
33
|
+
* @property {import('kafkajs/utils/long').Long} [baseOffset]
|
|
34
|
+
*
|
|
35
|
+
* @param {ProducerResponseItem} response
|
|
36
|
+
* @returns {ProducerBacklog}
|
|
37
|
+
*/
|
|
38
|
+
transformProduceResponse (response) {
|
|
39
|
+
// In produce protocol >=v3, the offset key changes from `offset` to `baseOffset`
|
|
40
|
+
const { topicName: topic, partition, offset, baseOffset } = response
|
|
41
|
+
const offsetAsLong = offset || baseOffset
|
|
42
|
+
return {
|
|
43
|
+
type: 'kafka_produce',
|
|
44
|
+
partition,
|
|
45
|
+
offset: offsetAsLong ? Number(offsetAsLong) : undefined,
|
|
46
|
+
topic
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param {ProducerResponseItem[]} commitList
|
|
53
|
+
* @returns {void}
|
|
54
|
+
*/
|
|
55
|
+
commit (commitList) {
|
|
56
|
+
if (!this.config.dsmEnabled) return
|
|
57
|
+
const keys = [
|
|
58
|
+
'type',
|
|
59
|
+
'partition',
|
|
60
|
+
'offset',
|
|
61
|
+
'topic'
|
|
62
|
+
]
|
|
63
|
+
for (const commit of commitList.map(this.transformProduceResponse)) {
|
|
64
|
+
if (keys.some(key => !commit.hasOwnProperty(key))) continue
|
|
65
|
+
this.tracer.setOffset(commit)
|
|
18
66
|
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
start ({ topic, messages, bootstrapServers }) {
|
|
19
70
|
const span = this.startSpan({
|
|
20
71
|
resource: topic,
|
|
21
72
|
meta: {
|
|
@@ -31,8 +82,13 @@ class KafkajsProducerPlugin extends ProducerPlugin {
|
|
|
31
82
|
}
|
|
32
83
|
for (const message of messages) {
|
|
33
84
|
if (typeof message === 'object') {
|
|
34
|
-
if (this.config.dsmEnabled) message.headers['dd-pathway-ctx'] = pathwayCtx
|
|
35
85
|
this.tracer.inject(span, 'text_map', message.headers)
|
|
86
|
+
if (this.config.dsmEnabled) {
|
|
87
|
+
const payloadSize = getMessageSize(message)
|
|
88
|
+
const dataStreamsContext = this.tracer
|
|
89
|
+
.setCheckpoint(['direction:out', `topic:${topic}`, 'type:kafka'], span, payloadSize)
|
|
90
|
+
DsmPathwayCodec.encode(dataStreamsContext, message.headers)
|
|
91
|
+
}
|
|
36
92
|
}
|
|
37
93
|
}
|
|
38
94
|
}
|