dd-trace 5.35.0 → 5.37.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 -1
- package/index.d.ts +8 -7
- package/loader-hook.mjs +0 -4
- package/package.json +15 -14
- package/packages/datadog-core/index.js +1 -1
- package/packages/datadog-core/src/storage.js +76 -31
- package/packages/datadog-instrumentations/src/cucumber.js +54 -1
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
- package/packages/datadog-instrumentations/src/jest.js +105 -11
- package/packages/datadog-instrumentations/src/mocha/main.js +46 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +35 -2
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -0
- package/packages/datadog-instrumentations/src/mysql2.js +3 -3
- package/packages/datadog-instrumentations/src/openai.js +8 -0
- package/packages/datadog-instrumentations/src/playwright.js +70 -22
- package/packages/datadog-instrumentations/src/vitest.js +60 -6
- package/packages/datadog-plugin-aerospike/src/index.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/fetch.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -2
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-couchbase/src/index.js +2 -2
- package/packages/datadog-plugin-cucumber/src/index.js +31 -14
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +72 -7
- package/packages/datadog-plugin-cypress/src/support.js +36 -29
- package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
- package/packages/datadog-plugin-graphql/src/utils.js +8 -1
- package/packages/datadog-plugin-grpc/src/client.js +1 -1
- package/packages/datadog-plugin-grpc/src/server.js +1 -1
- package/packages/datadog-plugin-hapi/src/index.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +3 -3
- package/packages/datadog-plugin-http2/src/server.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +17 -12
- package/packages/datadog-plugin-langchain/src/tracing.js +1 -1
- package/packages/datadog-plugin-mariadb/src/index.js +3 -3
- package/packages/datadog-plugin-mocha/src/index.js +35 -16
- package/packages/datadog-plugin-mongodb-core/src/index.js +28 -2
- package/packages/datadog-plugin-next/src/index.js +4 -4
- package/packages/datadog-plugin-openai/src/tracing.js +2 -3
- package/packages/datadog-plugin-playwright/src/index.js +35 -9
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +2 -2
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +36 -12
- package/packages/dd-trace/src/appsec/graphql.js +6 -6
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +3 -7
- package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +15 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +17 -30
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -11
- package/packages/dd-trace/src/appsec/iast/analyzers/stored-injection-analyzer.js +11 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +2 -6
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +24 -4
- package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/index.js +4 -2
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +187 -0
- package/packages/dd-trace/src/appsec/iast/security-controls/parser.js +96 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js +6 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -8
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +65 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +14 -5
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +80 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/secure-marks-generator.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/secure-marks.js +28 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +5 -0
- package/packages/dd-trace/src/appsec/iast/utils.js +24 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +8 -13
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +4 -4
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +5 -5
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +5 -5
- package/packages/dd-trace/src/appsec/rasp/lfi.js +3 -3
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +4 -4
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +3 -3
- package/packages/dd-trace/src/appsec/reporter.js +3 -3
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +2 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +31 -56
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +20 -2
- package/packages/dd-trace/src/ci-visibility/quarantined-tests/get-quarantined-tests.js +62 -0
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +5 -2
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +3 -3
- package/packages/dd-trace/src/config.js +18 -3
- package/packages/dd-trace/src/data_streams_context.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +14 -7
- package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +50 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +38 -10
- package/packages/dd-trace/src/exporters/common/agents.js +1 -1
- package/packages/dd-trace/src/exporters/common/request.js +3 -3
- package/packages/dd-trace/src/iitm.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +12 -2
- package/packages/dd-trace/src/log/writer.js +3 -3
- package/packages/dd-trace/src/noop/span.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +5 -4
- package/packages/dd-trace/src/opentracing/span.js +3 -3
- package/packages/dd-trace/src/plugin_manager.js +3 -1
- package/packages/dd-trace/src/plugins/apollo.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +51 -4
- package/packages/dd-trace/src/plugins/database.js +14 -4
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +8 -8
- package/packages/dd-trace/src/plugins/tracing.js +3 -3
- package/packages/dd-trace/src/plugins/util/git.js +3 -3
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -3
- package/packages/dd-trace/src/plugins/util/test.js +10 -4
- package/packages/dd-trace/src/profiling/exporters/agent.js +3 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
- package/packages/dd-trace/src/proxy.js +5 -1
- package/packages/dd-trace/src/ritm.js +2 -1
- package/packages/dd-trace/src/scope.js +5 -5
- package/packages/dd-trace/src/spanleak.js +0 -1
- package/packages/dd-trace/src/tracer.js +0 -14
- package/packages/memwatch/package.json +0 -9
|
@@ -4,6 +4,10 @@ let isKnownTestsEnabled = false
|
|
|
4
4
|
let knownTestsForSuite = []
|
|
5
5
|
let suiteTests = []
|
|
6
6
|
let earlyFlakeDetectionNumRetries = 0
|
|
7
|
+
// We need to grab the original window as soon as possible,
|
|
8
|
+
// in case the test changes the origin. If the test does change the origin,
|
|
9
|
+
// any call to `cy.window()` will result in a cross origin error.
|
|
10
|
+
let originalWindow
|
|
7
11
|
|
|
8
12
|
// If the test is using multi domain with cy.origin, trying to access
|
|
9
13
|
// window properties will result in a cross origin error.
|
|
@@ -61,6 +65,9 @@ beforeEach(function () {
|
|
|
61
65
|
this.skip()
|
|
62
66
|
}
|
|
63
67
|
})
|
|
68
|
+
cy.window().then(win => {
|
|
69
|
+
originalWindow = win
|
|
70
|
+
})
|
|
64
71
|
})
|
|
65
72
|
|
|
66
73
|
before(function () {
|
|
@@ -78,39 +85,39 @@ before(function () {
|
|
|
78
85
|
})
|
|
79
86
|
|
|
80
87
|
after(() => {
|
|
81
|
-
|
|
82
|
-
if (safeGetRum(
|
|
83
|
-
|
|
88
|
+
try {
|
|
89
|
+
if (safeGetRum(originalWindow)) {
|
|
90
|
+
originalWindow.dispatchEvent(new Event('beforeunload'))
|
|
84
91
|
}
|
|
85
|
-
})
|
|
92
|
+
} catch (e) {
|
|
93
|
+
// ignore error. It's usually a multi origin issue.
|
|
94
|
+
}
|
|
86
95
|
})
|
|
87
96
|
|
|
88
97
|
|
|
89
98
|
afterEach(function () {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
} catch (e) {}
|
|
99
|
+
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
|
|
100
|
+
const testInfo = {
|
|
101
|
+
testName: currentTest.fullTitle(),
|
|
102
|
+
testSuite: Cypress.mocha.getRootSuite().file,
|
|
103
|
+
testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute,
|
|
104
|
+
state: currentTest.state,
|
|
105
|
+
error: currentTest.err,
|
|
106
|
+
isNew: currentTest._ddIsNew,
|
|
107
|
+
isEfdRetry: currentTest._ddIsEfdRetry
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
|
|
111
|
+
} catch (e) {}
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
})
|
|
113
|
+
if (safeGetRum(originalWindow)) {
|
|
114
|
+
testInfo.isRUMActive = true
|
|
115
|
+
}
|
|
116
|
+
let coverage
|
|
117
|
+
try {
|
|
118
|
+
coverage = originalWindow.__coverage__
|
|
119
|
+
} catch (e) {
|
|
120
|
+
// ignore error and continue
|
|
121
|
+
}
|
|
122
|
+
cy.task('dd:afterEach', { test: testInfo, coverage })
|
|
116
123
|
})
|
|
@@ -28,7 +28,7 @@ module.exports = class DdTraceApiPlugin extends Plugin {
|
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
const handleEvent = (name) => {
|
|
31
|
-
const counter = apiMetrics.count('
|
|
31
|
+
const counter = apiMetrics.count('public_api.called', [
|
|
32
32
|
`name:${name.replaceAll(':', '.')}`,
|
|
33
33
|
'api_version:v1',
|
|
34
34
|
injectionEnabledTag
|
|
@@ -74,8 +74,6 @@ module.exports = class DdTraceApiPlugin extends Plugin {
|
|
|
74
74
|
const proxyVal = proxy()
|
|
75
75
|
objectMap.set(proxyVal, ret.value)
|
|
76
76
|
ret.value = proxyVal
|
|
77
|
-
} else if (ret.value && typeof ret.value === 'object') {
|
|
78
|
-
throw new TypeError(`Objects need proxies when returned via API (${name})`)
|
|
79
77
|
}
|
|
80
78
|
} catch (e) {
|
|
81
79
|
ret.error = e
|
|
@@ -27,7 +27,14 @@ function extractErrorIntoSpanEvent (config, span, exc) {
|
|
|
27
27
|
if (config.graphqlErrorExtensions) {
|
|
28
28
|
for (const ext of config.graphqlErrorExtensions) {
|
|
29
29
|
if (exc.extensions?.[ext]) {
|
|
30
|
-
|
|
30
|
+
const value = exc.extensions[ext]
|
|
31
|
+
|
|
32
|
+
// We should only stringify the value if it is not of type number or boolean
|
|
33
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
34
|
+
attributes[`extensions.${ext}`] = value
|
|
35
|
+
} else {
|
|
36
|
+
attributes[`extensions.${ext}`] = String(value)
|
|
37
|
+
}
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
}
|
|
@@ -20,7 +20,7 @@ class GrpcClientPlugin extends ClientPlugin {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
bindStart (message) {
|
|
23
|
-
const store = storage.getStore()
|
|
23
|
+
const store = storage('legacy').getStore()
|
|
24
24
|
const { metadata, path, type } = message
|
|
25
25
|
const metadataFilter = this.config.metadataFilter
|
|
26
26
|
const method = getMethodMetadata(path, type)
|
|
@@ -27,7 +27,7 @@ class GrpcServerPlugin extends ServerPlugin {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
bindStart (message) {
|
|
30
|
-
const store = storage.getStore()
|
|
30
|
+
const store = storage('legacy').getStore()
|
|
31
31
|
const { name, metadata, type } = message
|
|
32
32
|
const metadataFilter = this.config.metadataFilter
|
|
33
33
|
const childOf = extract(this.tracer, metadata)
|
|
@@ -15,7 +15,7 @@ class HapiPlugin extends RouterPlugin {
|
|
|
15
15
|
this._requestSpans = new WeakMap()
|
|
16
16
|
|
|
17
17
|
this.addSub('apm:hapi:request:handle', ({ req }) => {
|
|
18
|
-
const store = storage.getStore()
|
|
18
|
+
const store = storage('legacy').getStore()
|
|
19
19
|
const span = store && store.span
|
|
20
20
|
|
|
21
21
|
this.setFramework(req, 'hapi', this.config)
|
|
@@ -21,7 +21,7 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
21
21
|
|
|
22
22
|
bindStart (message) {
|
|
23
23
|
const { args, http = {} } = message
|
|
24
|
-
const store = storage.getStore()
|
|
24
|
+
const store = storage('legacy').getStore()
|
|
25
25
|
const options = args.options
|
|
26
26
|
const agent = options.agent || options._defaultAgent || http.globalAgent || {}
|
|
27
27
|
const protocol = options.protocol || agent.protocol || 'http:'
|
|
@@ -36,7 +36,7 @@ class Http2ClientPlugin extends ClientPlugin {
|
|
|
36
36
|
const uri = `${sessionDetails.protocol}//${sessionDetails.host}:${sessionDetails.port}${pathname}`
|
|
37
37
|
const allowed = this.config.filter(uri)
|
|
38
38
|
|
|
39
|
-
const store = storage.getStore()
|
|
39
|
+
const store = storage('legacy').getStore()
|
|
40
40
|
const childOf = store && allowed ? store.span : null
|
|
41
41
|
const span = this.startSpan(this.operationName(), {
|
|
42
42
|
childOf,
|
|
@@ -85,7 +85,7 @@ class Http2ClientPlugin extends ClientPlugin {
|
|
|
85
85
|
return parentStore
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
return storage.getStore()
|
|
88
|
+
return storage('legacy').getStore()
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
configure (config) {
|
|
@@ -98,7 +98,7 @@ class Http2ClientPlugin extends ClientPlugin {
|
|
|
98
98
|
store.span.setTag(HTTP_STATUS_CODE, status)
|
|
99
99
|
|
|
100
100
|
if (!this.config.validateStatus(status)) {
|
|
101
|
-
storage.run(store, () => this.addError())
|
|
101
|
+
storage('legacy').run(store, () => this.addError())
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
addHeaderTags(store.span, headers, HTTP_RESPONSE_HEADERS, this.config)
|
|
@@ -24,7 +24,9 @@ const {
|
|
|
24
24
|
TEST_IS_RUM_ACTIVE,
|
|
25
25
|
TEST_BROWSER_DRIVER,
|
|
26
26
|
getFormattedError,
|
|
27
|
-
TEST_RETRY_REASON
|
|
27
|
+
TEST_RETRY_REASON,
|
|
28
|
+
TEST_MANAGEMENT_ENABLED,
|
|
29
|
+
TEST_MANAGEMENT_IS_QUARANTINED
|
|
28
30
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
29
31
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
30
32
|
const id = require('../../dd-trace/src/id')
|
|
@@ -106,6 +108,7 @@ class JestPlugin extends CiPlugin {
|
|
|
106
108
|
error,
|
|
107
109
|
isEarlyFlakeDetectionEnabled,
|
|
108
110
|
isEarlyFlakeDetectionFaulty,
|
|
111
|
+
isQuarantinedTestsEnabled,
|
|
109
112
|
onDone
|
|
110
113
|
}) => {
|
|
111
114
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
@@ -137,6 +140,9 @@ class JestPlugin extends CiPlugin {
|
|
|
137
140
|
if (isEarlyFlakeDetectionFaulty) {
|
|
138
141
|
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
|
|
139
142
|
}
|
|
143
|
+
if (isQuarantinedTestsEnabled) {
|
|
144
|
+
this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
|
|
145
|
+
}
|
|
140
146
|
|
|
141
147
|
this.testModuleSpan.finish()
|
|
142
148
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
@@ -166,6 +172,7 @@ class JestPlugin extends CiPlugin {
|
|
|
166
172
|
config._ddEarlyFlakeDetectionNumRetries = this.libraryConfig?.earlyFlakeDetectionNumRetries ?? 0
|
|
167
173
|
config._ddRepositoryRoot = this.repositoryRoot
|
|
168
174
|
config._ddIsFlakyTestRetriesEnabled = this.libraryConfig?.isFlakyTestRetriesEnabled ?? false
|
|
175
|
+
config._ddIsQuarantinedTestsEnabled = this.libraryConfig?.isQuarantinedTestsEnabled ?? false
|
|
169
176
|
config._ddFlakyTestRetriesCount = this.libraryConfig?.flakyTestRetriesCount
|
|
170
177
|
config._ddIsDiEnabled = this.libraryConfig?.isDiEnabled ?? false
|
|
171
178
|
config._ddIsKnownTestsEnabled = this.libraryConfig?.isKnownTestsEnabled ?? false
|
|
@@ -291,6 +298,7 @@ class JestPlugin extends CiPlugin {
|
|
|
291
298
|
if (isJestWorker) {
|
|
292
299
|
this.tracer._exporter.flush()
|
|
293
300
|
}
|
|
301
|
+
this.removeAllDiProbes()
|
|
294
302
|
})
|
|
295
303
|
|
|
296
304
|
/**
|
|
@@ -317,19 +325,22 @@ class JestPlugin extends CiPlugin {
|
|
|
317
325
|
})
|
|
318
326
|
|
|
319
327
|
this.addSub('ci:jest:test:start', (test) => {
|
|
320
|
-
const store = storage.getStore()
|
|
328
|
+
const store = storage('legacy').getStore()
|
|
321
329
|
const span = this.startTestSpan(test)
|
|
322
330
|
|
|
323
331
|
this.enter(span, store)
|
|
324
332
|
this.activeTestSpan = span
|
|
325
333
|
})
|
|
326
334
|
|
|
327
|
-
this.addSub('ci:jest:test:finish', ({ status, testStartLine,
|
|
328
|
-
const span = storage.getStore().span
|
|
335
|
+
this.addSub('ci:jest:test:finish', ({ status, testStartLine, isQuarantined }) => {
|
|
336
|
+
const span = storage('legacy').getStore().span
|
|
329
337
|
span.setTag(TEST_STATUS, status)
|
|
330
338
|
if (testStartLine) {
|
|
331
339
|
span.setTag(TEST_SOURCE_START, testStartLine)
|
|
332
340
|
}
|
|
341
|
+
if (isQuarantined) {
|
|
342
|
+
span.setTag(TEST_MANAGEMENT_IS_QUARANTINED, 'true')
|
|
343
|
+
}
|
|
333
344
|
|
|
334
345
|
const spanTags = span.context()._tags
|
|
335
346
|
this.telemetry.ciVisEvent(
|
|
@@ -346,15 +357,11 @@ class JestPlugin extends CiPlugin {
|
|
|
346
357
|
span.finish()
|
|
347
358
|
finishAllTraceSpans(span)
|
|
348
359
|
this.activeTestSpan = null
|
|
349
|
-
if (shouldRemoveProbe && this.runningTestProbeId) {
|
|
350
|
-
promises.isProbeRemoved = withTimeout(this.removeDiProbe(this.runningTestProbeId), 2000)
|
|
351
|
-
this.runningTestProbeId = null
|
|
352
|
-
}
|
|
353
360
|
})
|
|
354
361
|
|
|
355
362
|
this.addSub('ci:jest:test:err', ({ error, shouldSetProbe, promises }) => {
|
|
356
363
|
if (error) {
|
|
357
|
-
const store = storage.getStore()
|
|
364
|
+
const store = storage('legacy').getStore()
|
|
358
365
|
if (store && store.span) {
|
|
359
366
|
const span = store.span
|
|
360
367
|
span.setTag(TEST_STATUS, 'fail')
|
|
@@ -362,9 +369,7 @@ class JestPlugin extends CiPlugin {
|
|
|
362
369
|
if (shouldSetProbe) {
|
|
363
370
|
const probeInformation = this.addDiProbe(error)
|
|
364
371
|
if (probeInformation) {
|
|
365
|
-
const {
|
|
366
|
-
this.runningTestProbeId = probeId
|
|
367
|
-
this.testErrorStackIndex = stackIndex
|
|
372
|
+
const { setProbePromise } = probeInformation
|
|
368
373
|
promises.isProbeReady = withTimeout(setProbePromise, 2000)
|
|
369
374
|
}
|
|
370
375
|
}
|
|
@@ -13,12 +13,12 @@ class MariadbPlugin extends MySQLPlugin {
|
|
|
13
13
|
super(...args)
|
|
14
14
|
|
|
15
15
|
this.addSub(`apm:${this.component}:pool:skip`, () => {
|
|
16
|
-
skippedStore = storage.getStore()
|
|
17
|
-
storage.enterWith({ noop: true })
|
|
16
|
+
skippedStore = storage('legacy').getStore()
|
|
17
|
+
storage('legacy').enterWith({ noop: true })
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
this.addSub(`apm:${this.component}:pool:unskip`, () => {
|
|
21
|
-
storage.enterWith(skippedStore)
|
|
21
|
+
storage('legacy').enterWith(skippedStore)
|
|
22
22
|
skippedStore = undefined
|
|
23
23
|
})
|
|
24
24
|
}
|
|
@@ -31,7 +31,9 @@ const {
|
|
|
31
31
|
MOCHA_IS_PARALLEL,
|
|
32
32
|
TEST_IS_RUM_ACTIVE,
|
|
33
33
|
TEST_BROWSER_DRIVER,
|
|
34
|
-
TEST_RETRY_REASON
|
|
34
|
+
TEST_RETRY_REASON,
|
|
35
|
+
TEST_MANAGEMENT_ENABLED,
|
|
36
|
+
TEST_MANAGEMENT_IS_QUARANTINED
|
|
35
37
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
36
38
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
37
39
|
const {
|
|
@@ -48,6 +50,8 @@ const {
|
|
|
48
50
|
const id = require('../../dd-trace/src/id')
|
|
49
51
|
const log = require('../../dd-trace/src/log')
|
|
50
52
|
|
|
53
|
+
const BREAKPOINT_SET_GRACE_PERIOD_MS = 200
|
|
54
|
+
|
|
51
55
|
function getTestSuiteLevelVisibilityTags (testSuiteSpan) {
|
|
52
56
|
const testSuiteSpanContext = testSuiteSpan.context()
|
|
53
57
|
const suiteTags = {
|
|
@@ -155,13 +159,13 @@ class MochaPlugin extends CiPlugin {
|
|
|
155
159
|
if (itrCorrelationId) {
|
|
156
160
|
testSuiteSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId)
|
|
157
161
|
}
|
|
158
|
-
const store = storage.getStore()
|
|
162
|
+
const store = storage('legacy').getStore()
|
|
159
163
|
this.enter(testSuiteSpan, store)
|
|
160
164
|
this._testSuites.set(testSuite, testSuiteSpan)
|
|
161
165
|
})
|
|
162
166
|
|
|
163
167
|
this.addSub('ci:mocha:test-suite:finish', (status) => {
|
|
164
|
-
const store = storage.getStore()
|
|
168
|
+
const store = storage('legacy').getStore()
|
|
165
169
|
if (store && store.span) {
|
|
166
170
|
const span = store.span
|
|
167
171
|
// the test status of the suite may have been set in ci:mocha:test-suite:error already
|
|
@@ -174,7 +178,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
174
178
|
})
|
|
175
179
|
|
|
176
180
|
this.addSub('ci:mocha:test-suite:error', (err) => {
|
|
177
|
-
const store = storage.getStore()
|
|
181
|
+
const store = storage('legacy').getStore()
|
|
178
182
|
if (store && store.span) {
|
|
179
183
|
const span = store.span
|
|
180
184
|
span.setTag('error', err)
|
|
@@ -183,7 +187,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
183
187
|
})
|
|
184
188
|
|
|
185
189
|
this.addSub('ci:mocha:test:start', (testInfo) => {
|
|
186
|
-
const store = storage.getStore()
|
|
190
|
+
const store = storage('legacy').getStore()
|
|
187
191
|
const span = this.startTestSpan(testInfo)
|
|
188
192
|
|
|
189
193
|
this.enter(span, store)
|
|
@@ -195,7 +199,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
195
199
|
})
|
|
196
200
|
|
|
197
201
|
this.addSub('ci:mocha:test:finish', ({ status, hasBeenRetried, isLastRetry }) => {
|
|
198
|
-
const store = storage.getStore()
|
|
202
|
+
const store = storage('legacy').getStore()
|
|
199
203
|
const span = store?.span
|
|
200
204
|
|
|
201
205
|
if (span) {
|
|
@@ -219,15 +223,15 @@ class MochaPlugin extends CiPlugin {
|
|
|
219
223
|
span.finish()
|
|
220
224
|
finishAllTraceSpans(span)
|
|
221
225
|
this.activeTestSpan = null
|
|
222
|
-
if (this.di && this.libraryConfig?.isDiEnabled && this.
|
|
223
|
-
this.removeDiProbe(this.
|
|
224
|
-
this.
|
|
226
|
+
if (this.di && this.libraryConfig?.isDiEnabled && this.runningTestProbe && isLastRetry) {
|
|
227
|
+
this.removeDiProbe(this.runningTestProbe)
|
|
228
|
+
this.runningTestProbe = null
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
231
|
})
|
|
228
232
|
|
|
229
233
|
this.addSub('ci:mocha:test:skip', (testInfo) => {
|
|
230
|
-
const store = storage.getStore()
|
|
234
|
+
const store = storage('legacy').getStore()
|
|
231
235
|
// skipped through it.skip, so the span is not created yet
|
|
232
236
|
// for this test
|
|
233
237
|
if (!store) {
|
|
@@ -237,7 +241,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
237
241
|
})
|
|
238
242
|
|
|
239
243
|
this.addSub('ci:mocha:test:error', (err) => {
|
|
240
|
-
const store = storage.getStore()
|
|
244
|
+
const store = storage('legacy').getStore()
|
|
241
245
|
const span = store?.span
|
|
242
246
|
if (err && span) {
|
|
243
247
|
if (err.constructor.name === 'Pending' && !this.forbidPending) {
|
|
@@ -250,7 +254,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
250
254
|
})
|
|
251
255
|
|
|
252
256
|
this.addSub('ci:mocha:test:retry', ({ isFirstAttempt, willBeRetried, err, test }) => {
|
|
253
|
-
const store = storage.getStore()
|
|
257
|
+
const store = storage('legacy').getStore()
|
|
254
258
|
const span = store?.span
|
|
255
259
|
if (span) {
|
|
256
260
|
span.setTag(TEST_STATUS, 'fail')
|
|
@@ -275,11 +279,16 @@ class MochaPlugin extends CiPlugin {
|
|
|
275
279
|
if (isFirstAttempt && willBeRetried && this.di && this.libraryConfig?.isDiEnabled) {
|
|
276
280
|
const probeInformation = this.addDiProbe(err)
|
|
277
281
|
if (probeInformation) {
|
|
278
|
-
const {
|
|
279
|
-
this.
|
|
282
|
+
const { file, line, stackIndex } = probeInformation
|
|
283
|
+
this.runningTestProbe = { file, line }
|
|
280
284
|
this.testErrorStackIndex = stackIndex
|
|
281
285
|
test._ddShouldWaitForHitProbe = true
|
|
282
|
-
|
|
286
|
+
const waitUntil = Date.now() + BREAKPOINT_SET_GRACE_PERIOD_MS
|
|
287
|
+
while (Date.now() < waitUntil) {
|
|
288
|
+
// TODO: To avoid a race condition, we should wait until `probeInformation.setProbePromise` has resolved.
|
|
289
|
+
// However, Mocha doesn't have a mechanism for waiting asyncrounously here, so for now, we'll have to
|
|
290
|
+
// fall back to a fixed syncronous delay.
|
|
291
|
+
}
|
|
283
292
|
}
|
|
284
293
|
}
|
|
285
294
|
|
|
@@ -302,6 +311,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
302
311
|
error,
|
|
303
312
|
isEarlyFlakeDetectionEnabled,
|
|
304
313
|
isEarlyFlakeDetectionFaulty,
|
|
314
|
+
isQuarantinedTestsEnabled,
|
|
305
315
|
isParallel
|
|
306
316
|
}) => {
|
|
307
317
|
if (this.testSessionSpan) {
|
|
@@ -318,6 +328,10 @@ class MochaPlugin extends CiPlugin {
|
|
|
318
328
|
this.testSessionSpan.setTag(MOCHA_IS_PARALLEL, 'true')
|
|
319
329
|
}
|
|
320
330
|
|
|
331
|
+
if (isQuarantinedTestsEnabled) {
|
|
332
|
+
this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
|
|
333
|
+
}
|
|
334
|
+
|
|
321
335
|
addIntelligentTestRunnerSpanTags(
|
|
322
336
|
this.testSessionSpan,
|
|
323
337
|
this.testModuleSpan,
|
|
@@ -390,7 +404,8 @@ class MochaPlugin extends CiPlugin {
|
|
|
390
404
|
isNew,
|
|
391
405
|
isEfdRetry,
|
|
392
406
|
testStartLine,
|
|
393
|
-
isParallel
|
|
407
|
+
isParallel,
|
|
408
|
+
isQuarantined
|
|
394
409
|
} = testInfo
|
|
395
410
|
|
|
396
411
|
const testName = removeEfdStringFromTestName(testInfo.testName)
|
|
@@ -409,6 +424,10 @@ class MochaPlugin extends CiPlugin {
|
|
|
409
424
|
extraTags[MOCHA_IS_PARALLEL] = 'true'
|
|
410
425
|
}
|
|
411
426
|
|
|
427
|
+
if (isQuarantined) {
|
|
428
|
+
extraTags[TEST_MANAGEMENT_IS_QUARANTINED] = 'true'
|
|
429
|
+
}
|
|
430
|
+
|
|
412
431
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.sourceRoot)
|
|
413
432
|
const testSuiteSpan = this._testSuites.get(testSuite)
|
|
414
433
|
|
|
@@ -11,8 +11,9 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
11
11
|
start ({ ns, ops, options = {}, name }) {
|
|
12
12
|
const query = getQuery(ops)
|
|
13
13
|
const resource = truncate(getResource(this, ns, query, name))
|
|
14
|
-
this.
|
|
15
|
-
|
|
14
|
+
const service = this.serviceName({ pluginConfig: this.config })
|
|
15
|
+
const span = this.startSpan(this.operationName(), {
|
|
16
|
+
service,
|
|
16
17
|
resource,
|
|
17
18
|
type: 'mongodb',
|
|
18
19
|
kind: 'client',
|
|
@@ -24,6 +25,7 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
24
25
|
'out.port': options.port
|
|
25
26
|
}
|
|
26
27
|
})
|
|
28
|
+
ops = this.injectDbmCommand(span, ops, service)
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
getPeerService (tags) {
|
|
@@ -34,6 +36,30 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
34
36
|
}
|
|
35
37
|
return super.getPeerService(tags)
|
|
36
38
|
}
|
|
39
|
+
|
|
40
|
+
injectDbmCommand (span, command, serviceName) {
|
|
41
|
+
const dbmTraceComment = this.createDbmComment(span, serviceName)
|
|
42
|
+
|
|
43
|
+
if (!dbmTraceComment) {
|
|
44
|
+
return command
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// create a copy of the command to avoid mutating the original
|
|
48
|
+
const dbmTracedCommand = { ...command }
|
|
49
|
+
|
|
50
|
+
if (dbmTracedCommand.comment) {
|
|
51
|
+
// if the command already has a comment, append the dbm trace comment
|
|
52
|
+
if (typeof dbmTracedCommand.comment === 'string') {
|
|
53
|
+
dbmTracedCommand.comment += `,${dbmTraceComment}`
|
|
54
|
+
} else if (Array.isArray(dbmTracedCommand.comment)) {
|
|
55
|
+
dbmTracedCommand.comment.push(dbmTraceComment)
|
|
56
|
+
} // do nothing if the comment is not a string or an array
|
|
57
|
+
} else {
|
|
58
|
+
dbmTracedCommand.comment = dbmTraceComment
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return dbmTracedCommand
|
|
62
|
+
}
|
|
37
63
|
}
|
|
38
64
|
|
|
39
65
|
function sanitizeBigInt (data) {
|
|
@@ -20,7 +20,7 @@ class NextPlugin extends ServerPlugin {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
bindStart ({ req, res }) {
|
|
23
|
-
const store = storage.getStore()
|
|
23
|
+
const store = storage('legacy').getStore()
|
|
24
24
|
const childOf = store ? store.span : store
|
|
25
25
|
const span = this.tracer.startSpan(this.operationName(), {
|
|
26
26
|
childOf,
|
|
@@ -43,7 +43,7 @@ class NextPlugin extends ServerPlugin {
|
|
|
43
43
|
|
|
44
44
|
error ({ span, error }) {
|
|
45
45
|
if (!span) {
|
|
46
|
-
const store = storage.getStore()
|
|
46
|
+
const store = storage('legacy').getStore()
|
|
47
47
|
if (!store) return
|
|
48
48
|
|
|
49
49
|
span = store.span
|
|
@@ -53,7 +53,7 @@ class NextPlugin extends ServerPlugin {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
finish ({ req, res, nextRequest = {} }) {
|
|
56
|
-
const store = storage.getStore()
|
|
56
|
+
const store = storage('legacy').getStore()
|
|
57
57
|
|
|
58
58
|
if (!store) return
|
|
59
59
|
|
|
@@ -85,7 +85,7 @@ class NextPlugin extends ServerPlugin {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
pageLoad ({ page, isAppPath = false, isStatic = false }) {
|
|
88
|
-
const store = storage.getStore()
|
|
88
|
+
const store = storage('legacy').getStore()
|
|
89
89
|
|
|
90
90
|
if (!store) return
|
|
91
91
|
|
|
@@ -15,7 +15,6 @@ let normalize
|
|
|
15
15
|
|
|
16
16
|
function safeRequire (path) {
|
|
17
17
|
try {
|
|
18
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
19
18
|
return require(path)
|
|
20
19
|
} catch {
|
|
21
20
|
return null
|
|
@@ -60,7 +59,7 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
60
59
|
bindStart (ctx) {
|
|
61
60
|
const { methodName, args, basePath, apiKey } = ctx
|
|
62
61
|
const payload = normalizeRequestPayload(methodName, args)
|
|
63
|
-
const store = storage.getStore() || {}
|
|
62
|
+
const store = storage('legacy').getStore() || {}
|
|
64
63
|
|
|
65
64
|
const span = this.startSpan('openai.request', {
|
|
66
65
|
service: this.config.service,
|
|
@@ -796,7 +795,7 @@ function truncateApiKey (apiKey) {
|
|
|
796
795
|
|
|
797
796
|
function tagChatCompletionRequestContent (contents, messageIdx, tags) {
|
|
798
797
|
if (typeof contents === 'string') {
|
|
799
|
-
tags[`openai.request.messages.${messageIdx}.content`] = contents
|
|
798
|
+
tags[`openai.request.messages.${messageIdx}.content`] = normalize(contents)
|
|
800
799
|
} else if (Array.isArray(contents)) {
|
|
801
800
|
// content can also be an array of objects
|
|
802
801
|
// which represent text input or image url
|