dd-trace 5.56.0 → 5.57.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/index.d.ts +44 -2
- package/init.js +4 -1
- package/package.json +21 -21
- package/packages/datadog-esbuild/index.js +22 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
- package/packages/datadog-instrumentations/src/cucumber.js +4 -6
- package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
- package/packages/datadog-instrumentations/src/fastify.js +91 -9
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
- package/packages/datadog-instrumentations/src/ioredis.js +8 -13
- package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
- package/packages/datadog-instrumentations/src/jest.js +28 -6
- package/packages/datadog-instrumentations/src/memcached.js +17 -24
- package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
- package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
- package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
- package/packages/datadog-instrumentations/src/openai.js +30 -2
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +116 -0
- package/packages/datadog-instrumentations/src/redis.js +32 -43
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-instrumentations/src/sharedb.js +10 -16
- package/packages/datadog-instrumentations/src/vitest.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
- package/packages/datadog-plugin-bunyan/src/index.js +2 -2
- package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +4 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
- package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
- package/packages/datadog-plugin-http/src/client.js +1 -0
- package/packages/datadog-plugin-http/src/server.js +2 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -0
- package/packages/datadog-plugin-http2/src/server.js +1 -0
- package/packages/datadog-plugin-jest/src/index.js +4 -3
- package/packages/datadog-plugin-memcached/src/index.js +6 -2
- package/packages/datadog-plugin-mocha/src/index.js +3 -2
- package/packages/datadog-plugin-moleculer/src/client.js +15 -9
- package/packages/datadog-plugin-moleculer/src/server.js +9 -5
- package/packages/datadog-plugin-next/src/index.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +127 -80
- package/packages/datadog-plugin-pino/src/index.js +2 -2
- package/packages/datadog-plugin-prisma/src/client.js +62 -0
- package/packages/datadog-plugin-prisma/src/engine.js +81 -0
- package/packages/datadog-plugin-prisma/src/index.js +22 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-redis/src/index.js +9 -3
- package/packages/datadog-plugin-router/src/index.js +1 -0
- package/packages/datadog-plugin-sharedb/src/index.js +13 -5
- package/packages/datadog-plugin-winston/src/index.js +2 -2
- package/packages/dd-trace/src/appsec/channels.js +26 -21
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
- package/packages/dd-trace/src/appsec/index.js +16 -1
- package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
- package/packages/dd-trace/src/config.js +286 -270
- package/packages/dd-trace/src/constants.js +2 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
- package/packages/dd-trace/src/datastreams/context.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/writer.js +3 -3
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
- package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
- package/packages/dd-trace/src/dogstatsd.js +3 -3
- package/packages/dd-trace/src/exporters/agent/index.js +10 -5
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/log/index.js +1 -1
- package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
- package/packages/dd-trace/src/guardrails/index.js +3 -1
- package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/index.js +11 -5
- package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +13 -13
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
- package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
- package/packages/dd-trace/src/opentracing/span.js +1 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/cache.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
- package/packages/dd-trace/src/plugins/database.js +3 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
- package/packages/dd-trace/src/plugins/outbound.js +8 -6
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +83 -30
- package/packages/dd-trace/src/plugins/util/git.js +1 -0
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
- package/packages/dd-trace/src/plugins/util/tags.js +4 -1
- package/packages/dd-trace/src/plugins/util/test.js +80 -10
- package/packages/dd-trace/src/plugins/util/web.js +1 -0
- package/packages/dd-trace/src/profiler.js +0 -2
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
- package/packages/dd-trace/src/proxy.js +12 -27
- package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/supported-configurations.json +12 -3
- package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
- package/packages/dd-trace/src/tracer.js +11 -0
- package/packages/dd-trace/src/tracer_metadata.js +25 -0
- package/packages/dd-trace/src/util.js +11 -4
- package/version.js +3 -1
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
|
@@ -6,8 +6,14 @@ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
|
6
6
|
const errorChannel = channel('apm:fastify:middleware:error')
|
|
7
7
|
const handleChannel = channel('apm:fastify:request:handle')
|
|
8
8
|
const routeAddedChannel = channel('apm:fastify:route:added')
|
|
9
|
+
const bodyParserReadCh = channel('datadog:fastify:body-parser:finish')
|
|
10
|
+
const queryParamsReadCh = channel('datadog:fastify:query-params:finish')
|
|
11
|
+
const cookieParserReadCh = channel('datadog:fastify-cookie:read:finish')
|
|
12
|
+
const responsePayloadReadCh = channel('datadog:fastify:response:finish')
|
|
13
|
+
const pathParamsReadCh = channel('datadog:fastify:path-params:finish')
|
|
9
14
|
|
|
10
15
|
const parsingResources = new WeakMap()
|
|
16
|
+
const cookiesPublished = new WeakSet()
|
|
11
17
|
|
|
12
18
|
function wrapFastify (fastify, hasParsingEvents) {
|
|
13
19
|
if (typeof fastify !== 'function') return fastify
|
|
@@ -45,26 +51,46 @@ function wrapAddHook (addHook) {
|
|
|
45
51
|
const req = getReq(request)
|
|
46
52
|
|
|
47
53
|
try {
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
// done callback is always the last argument
|
|
55
|
+
const doneCallback = arguments[arguments.length - 1]
|
|
50
56
|
|
|
57
|
+
if (typeof doneCallback === 'function') {
|
|
51
58
|
arguments[arguments.length - 1] = function (err) {
|
|
52
59
|
publishError(err, req)
|
|
53
60
|
|
|
61
|
+
const hasCookies = request.cookies && Object.keys(request.cookies).length > 0
|
|
62
|
+
|
|
63
|
+
if (cookieParserReadCh.hasSubscribers && hasCookies && !cookiesPublished.has(req)) {
|
|
64
|
+
const res = getRes(reply)
|
|
65
|
+
const abortController = new AbortController()
|
|
66
|
+
|
|
67
|
+
cookieParserReadCh.publish({
|
|
68
|
+
req,
|
|
69
|
+
res,
|
|
70
|
+
abortController,
|
|
71
|
+
cookies: request.cookies
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
cookiesPublished.add(req)
|
|
75
|
+
|
|
76
|
+
if (abortController.signal.aborted) return
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
if (name === 'onRequest' || name === 'preParsing') {
|
|
55
80
|
const parsingResource = new AsyncResource('bound-anonymous-fn')
|
|
56
81
|
|
|
57
82
|
parsingResources.set(req, parsingResource)
|
|
58
83
|
|
|
59
84
|
return parsingResource.runInAsyncScope(() => {
|
|
60
|
-
return
|
|
85
|
+
return doneCallback.apply(this, arguments)
|
|
61
86
|
})
|
|
62
87
|
}
|
|
63
|
-
return
|
|
88
|
+
return doneCallback.apply(this, arguments)
|
|
64
89
|
}
|
|
65
90
|
|
|
66
91
|
return fn.apply(this, arguments)
|
|
67
92
|
}
|
|
93
|
+
|
|
68
94
|
const promise = fn.apply(this, arguments)
|
|
69
95
|
|
|
70
96
|
if (promise && typeof promise.catch === 'function') {
|
|
@@ -106,11 +132,52 @@ function preHandler (request, reply, done) {
|
|
|
106
132
|
|
|
107
133
|
function preValidation (request, reply, done) {
|
|
108
134
|
const req = getReq(request)
|
|
135
|
+
const res = getRes(reply)
|
|
109
136
|
const parsingResource = parsingResources.get(req)
|
|
110
137
|
|
|
111
|
-
|
|
138
|
+
const processInContext = () => {
|
|
139
|
+
let abortController
|
|
112
140
|
|
|
113
|
-
|
|
141
|
+
if (queryParamsReadCh.hasSubscribers && request.query) {
|
|
142
|
+
abortController ??= new AbortController()
|
|
143
|
+
|
|
144
|
+
queryParamsReadCh.publish({
|
|
145
|
+
req,
|
|
146
|
+
res,
|
|
147
|
+
abortController,
|
|
148
|
+
query: request.query
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
if (abortController.signal.aborted) return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (bodyParserReadCh.hasSubscribers && request.body) {
|
|
155
|
+
abortController ??= new AbortController()
|
|
156
|
+
|
|
157
|
+
bodyParserReadCh.publish({ req, res, body: request.body, abortController })
|
|
158
|
+
|
|
159
|
+
if (abortController.signal.aborted) return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (pathParamsReadCh.hasSubscribers && request.params) {
|
|
163
|
+
abortController ??= new AbortController()
|
|
164
|
+
|
|
165
|
+
pathParamsReadCh.publish({
|
|
166
|
+
req,
|
|
167
|
+
res,
|
|
168
|
+
abortController,
|
|
169
|
+
params: request.params
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
if (abortController.signal.aborted) return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
done()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!parsingResource) return processInContext()
|
|
179
|
+
|
|
180
|
+
parsingResource.runInAsyncScope(processInContext)
|
|
114
181
|
}
|
|
115
182
|
|
|
116
183
|
function preParsing (request, reply, payload, done) {
|
|
@@ -126,9 +193,12 @@ function preParsing (request, reply, payload, done) {
|
|
|
126
193
|
}
|
|
127
194
|
|
|
128
195
|
function wrapSend (send, req) {
|
|
129
|
-
return function sendWithTrace (
|
|
130
|
-
if (
|
|
131
|
-
errorChannel.publish({ req, error })
|
|
196
|
+
return function sendWithTrace (payload) {
|
|
197
|
+
if (payload instanceof Error) {
|
|
198
|
+
errorChannel.publish({ req, error: payload })
|
|
199
|
+
} else if (canPublishResponsePayload(payload)) {
|
|
200
|
+
const res = getRes(this)
|
|
201
|
+
responsePayloadReadCh.publish({ req, res, body: payload })
|
|
132
202
|
}
|
|
133
203
|
|
|
134
204
|
return send.apply(this, arguments)
|
|
@@ -159,6 +229,18 @@ function onRoute (routeOptions) {
|
|
|
159
229
|
routeAddedChannel.publish({ routeOptions, onRoute })
|
|
160
230
|
}
|
|
161
231
|
|
|
232
|
+
// send() payload types: https://fastify.dev/docs/latest/Reference/Reply/#senddata
|
|
233
|
+
function canPublishResponsePayload (payload) {
|
|
234
|
+
return responsePayloadReadCh.hasSubscribers &&
|
|
235
|
+
payload &&
|
|
236
|
+
typeof payload === 'object' &&
|
|
237
|
+
typeof payload.pipe !== 'function' && // Node streams
|
|
238
|
+
typeof payload.body?.pipe !== 'function' && // Response with body stream
|
|
239
|
+
!Buffer.isBuffer(payload) && // Buffer
|
|
240
|
+
!(payload instanceof ArrayBuffer) && // ArrayBuffer
|
|
241
|
+
!ArrayBuffer.isView(payload) // TypedArray
|
|
242
|
+
}
|
|
243
|
+
|
|
162
244
|
addHook({ name: 'fastify', versions: ['>=3'] }, fastify => {
|
|
163
245
|
const wrapped = shimmer.wrapFunction(fastify, fastify => wrapFastify(fastify, true))
|
|
164
246
|
|
|
@@ -26,14 +26,29 @@ if (!dc.unsubscribe) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} catch (err) {
|
|
29
|
+
function doHook (payload) {
|
|
30
|
+
const hook = hooks[payload.package]
|
|
31
|
+
if (!hook) {
|
|
33
32
|
log.error('esbuild-wrapped %s missing in list of hooks', payload.package)
|
|
34
|
-
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const hookFn = hook.fn ?? hook
|
|
37
|
+
if (typeof hookFn !== 'function') {
|
|
38
|
+
log.error('esbuild-wrapped hook %s is not a function', payload.package)
|
|
39
|
+
return
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
try {
|
|
43
|
+
hookFn()
|
|
44
|
+
} catch {
|
|
45
|
+
log.error('esbuild-wrapped %s hook failed', payload.package)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
dc.subscribe(CHANNEL, (payload) => {
|
|
50
|
+
doHook(payload)
|
|
51
|
+
|
|
37
52
|
if (!instrumentations[payload.package]) {
|
|
38
53
|
log.error('esbuild-wrapped %s missing in list of instrumentations', payload.package)
|
|
39
54
|
return
|
|
@@ -55,7 +55,7 @@ module.exports.checkForRequiredModules = function () {
|
|
|
55
55
|
if (naughties.has(pkg)) continue
|
|
56
56
|
if (!(pkg in packages)) continue
|
|
57
57
|
|
|
58
|
-
warnings.push(`Warning: Package '${pkg}' was loaded before dd-trace! This may break instrumentation.`)
|
|
58
|
+
warnings.push(() => `Warning: Package '${pkg}' was loaded before dd-trace! This may break instrumentation.`)
|
|
59
59
|
|
|
60
60
|
naughties.add(pkg)
|
|
61
61
|
didWarn = true
|
|
@@ -87,7 +87,7 @@ module.exports.checkForPotentialConflicts = function () {
|
|
|
87
87
|
if (naughties.has(pkg)) continue
|
|
88
88
|
if (!potentialConflicts.has(pkg)) continue
|
|
89
89
|
|
|
90
|
-
warnings.push(`Warning: Package '${pkg}' may cause conflicts with dd-trace.`)
|
|
90
|
+
warnings.push(() => `Warning: Package '${pkg}' may cause conflicts with dd-trace.`)
|
|
91
91
|
|
|
92
92
|
naughties.add(pkg)
|
|
93
93
|
didWarn = true
|
|
@@ -24,6 +24,7 @@ module.exports = {
|
|
|
24
24
|
'@node-redis/client': () => require('../redis'),
|
|
25
25
|
'@opensearch-project/opensearch': () => require('../opensearch'),
|
|
26
26
|
'@opentelemetry/sdk-trace-node': () => require('../otel-sdk-trace'),
|
|
27
|
+
'@prisma/client': () => require('../prisma'),
|
|
27
28
|
'@redis/client': () => require('../redis'),
|
|
28
29
|
'@smithy/smithy-client': () => require('../aws-sdk'),
|
|
29
30
|
'@vitest/runner': { esmFirst: true, fn: () => require('../vitest') },
|
|
@@ -9,6 +9,7 @@ const log = require('../../../dd-trace/src/log')
|
|
|
9
9
|
const checkRequireCache = require('./check-require-cache')
|
|
10
10
|
const telemetry = require('../../../dd-trace/src/guardrails/telemetry')
|
|
11
11
|
const { isInServerlessEnvironment } = require('../../../dd-trace/src/serverless')
|
|
12
|
+
const { isFalse, isTrue, normalizePluginEnvName } = require('../../../dd-trace/src/util')
|
|
12
13
|
const { getEnvironmentVariables } = require('../../../dd-trace/src/config-helper')
|
|
13
14
|
|
|
14
15
|
const envs = getEnvironmentVariables()
|
|
@@ -22,16 +23,22 @@ const hooks = require('./hooks')
|
|
|
22
23
|
const instrumentations = require('./instrumentations')
|
|
23
24
|
const names = Object.keys(hooks)
|
|
24
25
|
const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
|
|
26
|
+
|
|
25
27
|
const disabledInstrumentations = new Set(
|
|
26
|
-
DD_TRACE_DISABLED_INSTRUMENTATIONS
|
|
28
|
+
DD_TRACE_DISABLED_INSTRUMENTATIONS?.split(',').map(name => normalizePluginEnvName(name, true)) ?? []
|
|
27
29
|
)
|
|
30
|
+
const reenabledInstrumentations = new Set()
|
|
28
31
|
|
|
29
32
|
// Check for DD_TRACE_<INTEGRATION>_ENABLED environment variables
|
|
30
33
|
for (const [key, value] of Object.entries(envs)) {
|
|
31
34
|
const match = key.match(/^DD_TRACE_(.+)_ENABLED$/)
|
|
32
|
-
if (match &&
|
|
33
|
-
const integration = match[1]
|
|
34
|
-
|
|
35
|
+
if (match && value) {
|
|
36
|
+
const integration = normalizePluginEnvName(match[1], true)
|
|
37
|
+
if (isFalse(value)) {
|
|
38
|
+
disabledInstrumentations.add(integration)
|
|
39
|
+
} else if (isTrue(value)) {
|
|
40
|
+
reenabledInstrumentations.add(integration)
|
|
41
|
+
}
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
44
|
|
|
@@ -58,7 +65,8 @@ const allInstrumentations = {}
|
|
|
58
65
|
|
|
59
66
|
// TODO: make this more efficient
|
|
60
67
|
for (const packageName of names) {
|
|
61
|
-
|
|
68
|
+
const normalizedPackageName = normalizePluginEnvName(packageName, true)
|
|
69
|
+
if (disabledInstrumentations.has(normalizedPackageName)) continue
|
|
62
70
|
|
|
63
71
|
const hookOptions = {}
|
|
64
72
|
|
|
@@ -67,6 +75,10 @@ for (const packageName of names) {
|
|
|
67
75
|
if (typeof hook === 'object') {
|
|
68
76
|
if (hook.serverless === false && isInServerlessEnvironment()) continue
|
|
69
77
|
|
|
78
|
+
// some integrations are disabled by default, but can be enabled by setting
|
|
79
|
+
// the DD_TRACE_<INTEGRATION>_ENABLED environment variable to true
|
|
80
|
+
if (hook.disabled && !reenabledInstrumentations.has(normalizedPackageName)) continue
|
|
81
|
+
|
|
70
82
|
hookOptions.internals = hook.esmFirst
|
|
71
83
|
hook = hook.fn
|
|
72
84
|
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
channel,
|
|
5
|
-
addHook
|
|
6
|
-
AsyncResource
|
|
5
|
+
addHook
|
|
7
6
|
} = require('./helpers/instrument')
|
|
8
7
|
const shimmer = require('../../datadog-shimmer')
|
|
9
8
|
|
|
@@ -22,14 +21,9 @@ addHook({ name: 'ioredis', versions: ['>=2'] }, Redis => {
|
|
|
22
21
|
const db = options.db
|
|
23
22
|
const connectionOptions = { host: options.host, port: options.port }
|
|
24
23
|
|
|
25
|
-
const
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const onResolve = asyncResource.bind(() => finish(finishCh, errorCh))
|
|
30
|
-
const onReject = asyncResource.bind(err => finish(finishCh, errorCh, err))
|
|
31
|
-
|
|
32
|
-
command.promise.then(onResolve, onReject)
|
|
24
|
+
const ctx = { db, command: command.name, args: command.args, connectionOptions, connectionName }
|
|
25
|
+
return startCh.runStores(ctx, () => {
|
|
26
|
+
command.promise.then(() => finish(finishCh, errorCh, ctx), err => finish(finishCh, errorCh, ctx, err))
|
|
33
27
|
|
|
34
28
|
try {
|
|
35
29
|
return sendCommand.apply(this, arguments)
|
|
@@ -43,9 +37,10 @@ addHook({ name: 'ioredis', versions: ['>=2'] }, Redis => {
|
|
|
43
37
|
return Redis
|
|
44
38
|
})
|
|
45
39
|
|
|
46
|
-
function finish (finishCh, errorCh, error) {
|
|
40
|
+
function finish (finishCh, errorCh, ctx, error) {
|
|
47
41
|
if (error) {
|
|
48
|
-
|
|
42
|
+
ctx.error = error
|
|
43
|
+
errorCh.publish(ctx)
|
|
49
44
|
}
|
|
50
|
-
finishCh.publish()
|
|
45
|
+
finishCh.publish(ctx)
|
|
51
46
|
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
channel,
|
|
5
|
-
addHook
|
|
6
|
-
AsyncResource
|
|
5
|
+
addHook
|
|
7
6
|
} = require('./helpers/instrument')
|
|
8
7
|
const shimmer = require('../../datadog-shimmer')
|
|
9
8
|
|
|
@@ -22,19 +21,15 @@ addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
|
22
21
|
const db = options.db
|
|
23
22
|
const connectionOptions = { host: options.host, port: options.port }
|
|
24
23
|
|
|
25
|
-
const
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const onResolve = asyncResource.bind(() => finishCh.publish())
|
|
30
|
-
const onReject = asyncResource.bind(err => finish(finishCh, errorCh, err))
|
|
31
|
-
|
|
32
|
-
command.promise.then(onResolve, onReject)
|
|
24
|
+
const ctx = { db, command: command.name, args: command.args, connectionOptions, connectionName }
|
|
25
|
+
return startCh.runStores(ctx, () => {
|
|
26
|
+
command.promise.then(() => finish(finishCh, errorCh, ctx), err => finish(finishCh, errorCh, ctx, err))
|
|
33
27
|
|
|
34
28
|
try {
|
|
35
29
|
return sendCommand.apply(this, arguments)
|
|
36
30
|
} catch (err) {
|
|
37
|
-
|
|
31
|
+
ctx.error = err
|
|
32
|
+
errorCh.publish(ctx)
|
|
38
33
|
|
|
39
34
|
throw err
|
|
40
35
|
}
|
|
@@ -43,9 +38,10 @@ addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
|
43
38
|
return Valkey
|
|
44
39
|
})
|
|
45
40
|
|
|
46
|
-
function finish (finishCh, errorCh, error) {
|
|
41
|
+
function finish (finishCh, errorCh, ctx, error) {
|
|
47
42
|
if (error) {
|
|
48
|
-
|
|
43
|
+
ctx.error = error
|
|
44
|
+
errorCh.publish(ctx)
|
|
49
45
|
}
|
|
50
|
-
finishCh.publish()
|
|
46
|
+
finishCh.publish(ctx)
|
|
51
47
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { addHook, channel } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
5
|
const log = require('../../dd-trace/src/log')
|
|
6
|
+
const path = require('path')
|
|
6
7
|
const {
|
|
7
8
|
getCoveredFilenamesFromCoverage,
|
|
8
9
|
JEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
@@ -90,6 +91,7 @@ const retriedTestsToNumAttempts = new Map()
|
|
|
90
91
|
const newTestsTestStatuses = new Map()
|
|
91
92
|
const attemptToFixRetriedTestsStatuses = new Map()
|
|
92
93
|
const wrappedWorkers = new WeakSet()
|
|
94
|
+
const testSuiteMockedFiles = new Map()
|
|
93
95
|
|
|
94
96
|
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
|
|
95
97
|
|
|
@@ -137,6 +139,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
137
139
|
this.nameToParams = {}
|
|
138
140
|
this.global._ddtrace = global._ddtrace
|
|
139
141
|
this.hasSnapshotTests = undefined
|
|
142
|
+
this.testSuiteAbsolutePath = context.testPath
|
|
140
143
|
|
|
141
144
|
this.displayName = config.projectConfig?.displayName?.name
|
|
142
145
|
this.testEnvironmentOptions = getTestEnvironmentOptions(config)
|
|
@@ -291,7 +294,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
291
294
|
// We'll still detect new tests, but we won't retry them.
|
|
292
295
|
// TODO: do not bail out of retrying tests for the whole test suite
|
|
293
296
|
if (this.getHasSnapshotTests()) {
|
|
294
|
-
log.warn(
|
|
297
|
+
log.warn('%s is disabled for suites with snapshots', retryType)
|
|
295
298
|
return
|
|
296
299
|
}
|
|
297
300
|
|
|
@@ -299,7 +302,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
299
302
|
if (this.global.test) {
|
|
300
303
|
this.global.test(addRetryStringToTestName(testName, retryIndex), event.fn, event.timeout)
|
|
301
304
|
} else {
|
|
302
|
-
log.error(
|
|
305
|
+
log.error('%s could not retry test because global.test is undefined', retryType)
|
|
303
306
|
}
|
|
304
307
|
}
|
|
305
308
|
}
|
|
@@ -726,7 +729,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
726
729
|
return runCLI.apply(this, arguments)
|
|
727
730
|
}
|
|
728
731
|
|
|
729
|
-
libraryConfigurationCh.publish({ onDone })
|
|
732
|
+
libraryConfigurationCh.publish({ onDone, frameworkVersion: jestVersion })
|
|
730
733
|
|
|
731
734
|
try {
|
|
732
735
|
const { err, libraryConfig } = await configurationPromise
|
|
@@ -1095,10 +1098,12 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
|
1095
1098
|
if (environment.testEnvironmentOptions?._ddTestCodeCoverageEnabled) {
|
|
1096
1099
|
const root = environment.repositoryRoot || environment.rootDir
|
|
1097
1100
|
|
|
1098
|
-
const
|
|
1099
|
-
.map(filename => getTestSuitePath(filename, root))
|
|
1101
|
+
const getFilesWithPath = (files) => files.map(file => getTestSuitePath(file, root))
|
|
1100
1102
|
|
|
1101
|
-
|
|
1103
|
+
const coverageFiles = getFilesWithPath(getCoveredFilenamesFromCoverage(environment.global.__coverage__))
|
|
1104
|
+
const mockedFiles = getFilesWithPath(testSuiteMockedFiles.get(environment.testSuiteAbsolutePath) || [])
|
|
1105
|
+
|
|
1106
|
+
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.testSourceFile, mockedFiles })
|
|
1102
1107
|
}
|
|
1103
1108
|
testSuiteFinishCh.publish({ status, errorMessage })
|
|
1104
1109
|
return suiteResults
|
|
@@ -1267,6 +1272,23 @@ addHook({
|
|
|
1267
1272
|
}, (runtimePackage) => {
|
|
1268
1273
|
const Runtime = runtimePackage.default ?? runtimePackage
|
|
1269
1274
|
|
|
1275
|
+
shimmer.wrap(Runtime.prototype, '_createJestObjectFor', _createJestObjectFor => function (from) {
|
|
1276
|
+
const result = _createJestObjectFor.apply(this, arguments)
|
|
1277
|
+
const suiteFilePath = this._testPath
|
|
1278
|
+
|
|
1279
|
+
shimmer.wrap(result, 'mock', mock => function (moduleName) {
|
|
1280
|
+
if (suiteFilePath) {
|
|
1281
|
+
const existingMockedFiles = testSuiteMockedFiles.get(suiteFilePath) || []
|
|
1282
|
+
const suiteDir = path.dirname(suiteFilePath)
|
|
1283
|
+
const mockPath = path.resolve(suiteDir, moduleName)
|
|
1284
|
+
existingMockedFiles.push(mockPath)
|
|
1285
|
+
testSuiteMockedFiles.set(suiteFilePath, existingMockedFiles)
|
|
1286
|
+
}
|
|
1287
|
+
return mock.apply(this, arguments)
|
|
1288
|
+
})
|
|
1289
|
+
return result
|
|
1290
|
+
})
|
|
1291
|
+
|
|
1270
1292
|
shimmer.wrap(Runtime.prototype, 'requireModuleOrMock', requireModuleOrMock => function (from, moduleName) {
|
|
1271
1293
|
// TODO: do this for every library that we instrument
|
|
1272
1294
|
if (shouldBypassJestRequireEngine(moduleName)) {
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
channel,
|
|
5
|
-
addHook
|
|
6
|
-
AsyncResource
|
|
5
|
+
addHook
|
|
7
6
|
} = require('./helpers/instrument')
|
|
8
7
|
const shimmer = require('../../datadog-shimmer')
|
|
9
8
|
|
|
@@ -17,35 +16,29 @@ addHook({ name: 'memcached', versions: ['>=2.2'] }, Memcached => {
|
|
|
17
16
|
return command.apply(this, arguments)
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
const callbackResource = new AsyncResource('bound-anonymous-fn')
|
|
21
|
-
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
22
|
-
|
|
23
19
|
const client = this
|
|
24
20
|
|
|
25
|
-
const wrappedQueryCompiler =
|
|
21
|
+
const wrappedQueryCompiler = function () {
|
|
26
22
|
const query = queryCompiler.apply(this, arguments)
|
|
27
|
-
const callback = callbackResource.bind(query.callback)
|
|
28
|
-
|
|
29
|
-
query.callback = shimmer.wrapFunction(callback, callback => asyncResource.bind(function (err) {
|
|
30
|
-
if (err) {
|
|
31
|
-
errorCh.publish(err)
|
|
32
|
-
}
|
|
33
|
-
finishCh.publish()
|
|
34
|
-
|
|
35
|
-
return callback.apply(this, arguments)
|
|
36
|
-
}))
|
|
37
|
-
startCh.publish({ client, server, query })
|
|
38
23
|
|
|
24
|
+
const ctx = { client, server, query }
|
|
25
|
+
startCh.runStores(ctx, () => {
|
|
26
|
+
query.callback = shimmer.wrapFunction(query.callback, callback => function (err) {
|
|
27
|
+
if (err) {
|
|
28
|
+
ctx.error = err
|
|
29
|
+
errorCh.publish(ctx)
|
|
30
|
+
}
|
|
31
|
+
finishCh.publish(ctx)
|
|
32
|
+
|
|
33
|
+
return finishCh.runStores(ctx, callback, this, ...arguments)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
39
36
|
return query
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return asyncResource.runInAsyncScope(() => {
|
|
43
|
-
arguments[0] = wrappedQueryCompiler
|
|
37
|
+
}
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
arguments[0] = wrappedQueryCompiler
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
})
|
|
41
|
+
return command.apply(this, arguments)
|
|
49
42
|
})
|
|
50
43
|
|
|
51
44
|
return Memcached
|
|
@@ -201,9 +201,10 @@ function getOnEndHandler (isParallel) {
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
204
|
+
function getExecutionConfiguration (runner, isParallel, frameworkVersion, onFinishRequest) {
|
|
205
205
|
const ctx = {
|
|
206
|
-
isParallel
|
|
206
|
+
isParallel,
|
|
207
|
+
frameworkVersion
|
|
207
208
|
}
|
|
208
209
|
|
|
209
210
|
const onReceivedSkippableSuites = ({ err, skippableSuites, itrCorrelationId: responseItrCorrelationId }) => {
|
|
@@ -343,7 +344,7 @@ addHook({
|
|
|
343
344
|
name: 'mocha',
|
|
344
345
|
versions: ['>=5.2.0'],
|
|
345
346
|
file: 'lib/mocha.js'
|
|
346
|
-
}, (Mocha) => {
|
|
347
|
+
}, (Mocha, frameworkVersion) => {
|
|
347
348
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
348
349
|
// Workers do not need to request any data, just run the tests
|
|
349
350
|
if (!testFinishCh.hasSubscribers || getEnvironmentVariable('MOCHA_WORKER_ID') || this.options.parallel) {
|
|
@@ -363,7 +364,7 @@ addHook({
|
|
|
363
364
|
}
|
|
364
365
|
})
|
|
365
366
|
|
|
366
|
-
getExecutionConfiguration(runner, false, () => {
|
|
367
|
+
getExecutionConfiguration(runner, false, frameworkVersion, () => {
|
|
367
368
|
if (config.isKnownTestsEnabled) {
|
|
368
369
|
const testSuites = this.files.map(file => getTestSuitePath(file, process.cwd()))
|
|
369
370
|
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
@@ -521,7 +522,7 @@ addHook({
|
|
|
521
522
|
if (ctx) {
|
|
522
523
|
testSuiteFinishCh.publish({ status, ...ctx.currentStore }, () => {})
|
|
523
524
|
} else {
|
|
524
|
-
log.warn(
|
|
525
|
+
log.warn('No ctx found for suite', suite.file)
|
|
525
526
|
}
|
|
526
527
|
})
|
|
527
528
|
|
|
@@ -616,7 +617,7 @@ addHook({
|
|
|
616
617
|
this.once('start', getOnStartHandler(true, frameworkVersion))
|
|
617
618
|
this.once('end', getOnEndHandler(true))
|
|
618
619
|
|
|
619
|
-
getExecutionConfiguration(this, true, () => {
|
|
620
|
+
getExecutionConfiguration(this, true, frameworkVersion, () => {
|
|
620
621
|
if (config.isKnownTestsEnabled) {
|
|
621
622
|
const testSuites = files.map(file => getTestSuitePath(file, process.cwd()))
|
|
622
623
|
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { channel, addHook
|
|
3
|
+
const { channel, addHook } = require('../helpers/instrument')
|
|
4
4
|
const shimmer = require('../../../datadog-shimmer')
|
|
5
5
|
|
|
6
6
|
const startChannel = channel('apm:moleculer:call:start')
|
|
@@ -9,29 +9,28 @@ const errorChannel = channel('apm:moleculer:call:error')
|
|
|
9
9
|
|
|
10
10
|
function wrapCall (call) {
|
|
11
11
|
return function (actionName, params, opts) {
|
|
12
|
-
const callResource = new AsyncResource('bound-anonymous-fn')
|
|
13
|
-
|
|
14
12
|
opts = arguments[2] = opts || {}
|
|
15
13
|
opts.meta = opts.meta || {}
|
|
16
14
|
|
|
17
15
|
arguments.length = Math.max(3, arguments.length)
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
const ctx = { actionName, params, opts }
|
|
18
|
+
return startChannel.runStores(ctx, () => {
|
|
22
19
|
const promise = call.apply(this, arguments)
|
|
23
20
|
const broker = this
|
|
24
|
-
|
|
21
|
+
ctx.promiseCtx = promise.ctx
|
|
22
|
+
ctx.broker = broker
|
|
25
23
|
|
|
26
24
|
return promise
|
|
27
25
|
.then(
|
|
28
26
|
result => {
|
|
29
|
-
finishChannel.publish(
|
|
27
|
+
finishChannel.publish(ctx)
|
|
30
28
|
return result
|
|
31
29
|
},
|
|
32
30
|
error => {
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
ctx.error = error
|
|
32
|
+
errorChannel.publish(ctx)
|
|
33
|
+
finishChannel.publish(ctx)
|
|
35
34
|
throw error
|
|
36
35
|
}
|
|
37
36
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { channel, addHook
|
|
3
|
+
const { channel, addHook } = require('../helpers/instrument')
|
|
4
4
|
const shimmer = require('../../../datadog-shimmer')
|
|
5
5
|
|
|
6
6
|
const startChannel = channel('apm:moleculer:action:start')
|
|
@@ -24,27 +24,26 @@ function createMiddleware () {
|
|
|
24
24
|
localAction (next, action) {
|
|
25
25
|
const broker = this
|
|
26
26
|
|
|
27
|
-
return shimmer.wrapFunction(next, next => function datadogMiddleware (
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
return actionResource.runInAsyncScope(() => {
|
|
31
|
-
startChannel.publish({ action, ctx, broker })
|
|
32
|
-
|
|
27
|
+
return shimmer.wrapFunction(next, next => function datadogMiddleware (middlewareCtx) {
|
|
28
|
+
const ctx = { action, middlewareCtx, broker }
|
|
29
|
+
return startChannel.runStores(ctx, () => {
|
|
33
30
|
try {
|
|
34
|
-
return next(
|
|
31
|
+
return next(middlewareCtx).then(
|
|
35
32
|
result => {
|
|
36
|
-
finishChannel.publish()
|
|
33
|
+
finishChannel.publish(ctx)
|
|
37
34
|
return result
|
|
38
35
|
},
|
|
39
36
|
error => {
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
ctx.error = error
|
|
38
|
+
errorChannel.publish(ctx)
|
|
39
|
+
finishChannel.publish(ctx)
|
|
42
40
|
throw error
|
|
43
41
|
}
|
|
44
42
|
)
|
|
45
43
|
} catch (e) {
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
ctx.error = e
|
|
45
|
+
errorChannel.publish(ctx)
|
|
46
|
+
finishChannel.publish(ctx)
|
|
48
47
|
}
|
|
49
48
|
})
|
|
50
49
|
})
|