dd-trace 6.20.0 → 6.21.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 +91 -3
- package/package.json +6 -7
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +57 -4
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/jest.js +119 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +124 -36
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +61 -34
- package/packages/datadog-instrumentations/src/mocha/worker.js +6 -3
- package/packages/datadog-instrumentations/src/playwright.js +3 -0
- package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
- package/packages/datadog-instrumentations/src/webdriverio.js +115 -15
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +17 -0
- package/packages/datadog-plugin-mocha/src/index.js +216 -29
- package/packages/datadog-plugin-mocha/src/webdriverio-video.js +449 -0
- package/packages/dd-trace/src/config/supported-configurations.json +2 -2
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +5 -3
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +17 -12
- package/packages/dd-trace/src/debugger/devtools_client/send.js +6 -2
- package/packages/dd-trace/src/debugger/devtools_client/worker-error.js +21 -0
- package/packages/dd-trace/src/debugger/index.js +24 -2
- package/packages/dd-trace/src/debugger/probe_sampler.js +108 -11
- package/packages/dd-trace/src/exporters/common/request.js +1 -0
- package/packages/dd-trace/src/exporters/common/url.js +1 -1
- package/packages/dd-trace/src/id.js +1 -4
- package/packages/dd-trace/src/llmobs/agent-manifest.js +296 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/sdk.js +23 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +17 -6
- package/packages/dd-trace/src/llmobs/tagger.js +54 -1
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -1
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -1
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +30 -1
- package/packages/dd-trace/src/openfeature/configuration_source.js +17 -2
- package/packages/dd-trace/src/openfeature/debug-logging-hook.js +25 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +29 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +9 -0
- package/packages/dd-trace/src/openfeature/writers/util.js +43 -4
- package/packages/dd-trace/src/opentelemetry/resource-attributes.js +1 -1
- package/packages/dd-trace/src/otel-thread-ctx.js +2 -2
- package/packages/dd-trace/src/plugins/util/url.js +6 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +4 -10
- package/packages/dd-trace/src/proxy.js +2 -0
- package/packages/dd-trace/src/serverless.js +5 -0
- package/packages/dd-trace/src/storage-channels.js +112 -46
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
const dc = require('dc-polyfill')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
|
+
const { isACFActive } = require('../../datadog-core/src/storage')
|
|
5
6
|
|
|
6
7
|
// Channels that surface tracer-storage events to interested consumers
|
|
7
8
|
// (currently the wall profiler and the OTEP-4947 thread context writer).
|
|
8
9
|
//
|
|
9
10
|
// dd-trace:storage:enter — fires when the active legacy-storage store
|
|
10
|
-
// changes. Published by the shimmer installed in
|
|
11
|
-
// dd-trace:storage:before — fires from an async_hooks "before" callback
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
11
|
+
// changes. Published by the shimmer installed in acquireChannels().
|
|
12
|
+
// dd-trace:storage:before — fires from an async_hooks "before" callback while
|
|
13
|
+
// at least one consumer that acquired the channels needs it. Used by the
|
|
14
|
+
// wall profiler in its non-AsyncContextFrame (single holder) mode to refresh
|
|
15
|
+
// the sample context at the start of each async resource callback.
|
|
15
16
|
// dd-trace:span:finish, dd-trace:span:tags:update — published by the
|
|
16
17
|
// tracer core (opentracing/span.js). Re-exported here as a convenience
|
|
17
18
|
// so consumers have a single import path for storage-related channels.
|
|
@@ -25,55 +26,119 @@ function getActiveSpan () {
|
|
|
25
26
|
return store && store.span
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// The legacy storage instrumentation feeding enterCh and beforeCh is installed
|
|
30
|
+
// lazily via acquireChannels() / releaseChannels(), ref-counted across
|
|
31
|
+
// consumers, so that once the last consumer stops (e.g. the profiler is turned
|
|
32
|
+
// off remotely), instrumentation is undone.
|
|
33
|
+
// Consumers MUST balance every acquireChannels() call with a matching
|
|
34
|
+
// releaseChannels() when they no longer use them.
|
|
35
|
+
let refCount = 0
|
|
36
|
+
// The async hook has a separate count: it's only needed by some consumers, and
|
|
37
|
+
// is a per-callback cost, so it's disabled as soon as the last of them releases.
|
|
38
|
+
let beforeRefCount = 0
|
|
39
|
+
let inRun = false
|
|
40
|
+
let beforeHook
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
// Wrappers currently installed on legacy storage, keyed by method name. Each
|
|
43
|
+
// entry records the method's own property descriptor from before wrapping
|
|
44
|
+
// (undefined when the method was inherited from the prototype) so it can be
|
|
45
|
+
// restored exactly.
|
|
46
|
+
const installedWrappers = new Map()
|
|
47
|
+
|
|
48
|
+
function wrapEnterWith (original) {
|
|
49
|
+
return function (store) {
|
|
50
|
+
const retVal = original.call(this, store)
|
|
51
|
+
if (!inRun && refCount !== 0) enterCh.publish()
|
|
52
|
+
return retVal
|
|
53
|
+
}
|
|
54
|
+
}
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
function wrapRun (original) {
|
|
57
|
+
const shimmer = require('../../datadog-shimmer')
|
|
58
|
+
return function (store, callback, ...args) {
|
|
59
|
+
if (refCount === 0) return original.call(this, store, callback, ...args)
|
|
60
|
+
const wrappedCb = shimmer.wrapFunction(callback, cb => function (...args) {
|
|
61
|
+
inRun = false
|
|
62
|
+
enterCh.publish()
|
|
63
|
+
const retVal = cb.apply(this, args)
|
|
64
|
+
inRun = true
|
|
45
65
|
return retVal
|
|
46
|
-
}
|
|
47
|
-
|
|
66
|
+
})
|
|
67
|
+
inRun = true
|
|
68
|
+
const retVal = original.call(this, store, wrappedCb, ...args)
|
|
69
|
+
enterCh.publish()
|
|
70
|
+
inRun = false
|
|
71
|
+
return retVal
|
|
72
|
+
}
|
|
73
|
+
}
|
|
48
74
|
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
75
|
+
function installWrapper (target, name, wrapper) {
|
|
76
|
+
if (installedWrappers.has(name)) return
|
|
77
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, name)
|
|
78
|
+
require('../../datadog-shimmer').wrap(target, name, wrapper)
|
|
79
|
+
installedWrappers.set(name, { descriptor, wrapped: target[name] })
|
|
80
|
+
}
|
|
54
81
|
|
|
82
|
+
function uninstallWrappers (target) {
|
|
83
|
+
for (const [name, { descriptor, wrapped }] of installedWrappers) {
|
|
84
|
+
// If someone else wrapped the method on top of ours, restoring would
|
|
85
|
+
// silently drop their wrapper too. Leave ours in place instead; it
|
|
86
|
+
// short-circuits while released, and gets reused on the next acquisition.
|
|
87
|
+
if (target[name] !== wrapped) continue
|
|
88
|
+
if (descriptor === undefined) {
|
|
89
|
+
delete target[name]
|
|
90
|
+
} else {
|
|
91
|
+
Object.defineProperty(target, name, descriptor)
|
|
92
|
+
}
|
|
93
|
+
installedWrappers.delete(name)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Acquires a reference to the channel publishers. The first reference installs
|
|
99
|
+
* the legacy storage instrumentation publishing on enterCh.
|
|
100
|
+
*
|
|
101
|
+
* @param {boolean} needsBeforeHook Whether the consumer needs beforeCh events.
|
|
102
|
+
* The same value must be passed to the matching releaseChannels() call.
|
|
103
|
+
*/
|
|
104
|
+
function acquireChannels (needsBeforeHook) {
|
|
105
|
+
if (refCount++ === 0) {
|
|
106
|
+
// We need to instrument enterWith() on the legacy storage — that's the storage
|
|
107
|
+
// carrying span data and the only one consumers of these channels care about.
|
|
108
|
+
const legacyStorage = storage('legacy')
|
|
109
|
+
installWrapper(legacyStorage, 'enterWith', wrapEnterWith)
|
|
55
110
|
// In ACF-based implementation run() delegates to enterWith() so it doesn't
|
|
56
|
-
// need to be separately instrumented.
|
|
111
|
+
// need to be separately instrumented. In non-ACF implementation run()
|
|
57
112
|
// doesn't delegate to enterWith(), so separate instrumentation is necessary.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
inRun = false
|
|
62
|
-
enterCh.publish()
|
|
63
|
-
const retVal = cb.apply(this, args)
|
|
64
|
-
inRun = true
|
|
65
|
-
return retVal
|
|
66
|
-
})
|
|
67
|
-
inRun = true
|
|
68
|
-
const retVal = original.call(this, store, wrappedCb, ...args)
|
|
69
|
-
enterCh.publish()
|
|
70
|
-
inRun = false
|
|
71
|
-
return retVal
|
|
72
|
-
}
|
|
73
|
-
})
|
|
113
|
+
if (!isACFActive) {
|
|
114
|
+
installWrapper(legacyStorage, 'run', wrapRun)
|
|
115
|
+
}
|
|
74
116
|
}
|
|
75
117
|
|
|
76
|
-
|
|
118
|
+
if (needsBeforeHook && beforeRefCount++ === 0) {
|
|
119
|
+
beforeHook ??= require('async_hooks').createHook({ before: () => beforeCh.publish() })
|
|
120
|
+
beforeHook.enable()
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Releases one acquireChannels() reference. The async hook is disabled when the
|
|
126
|
+
* last reference needing it is released, and the legacy storage instrumentation
|
|
127
|
+
* is removed when the last reference overall is released.
|
|
128
|
+
*
|
|
129
|
+
* @param {boolean} needsBeforeHook The value passed to the matching
|
|
130
|
+
* acquireChannels() call.
|
|
131
|
+
*/
|
|
132
|
+
function releaseChannels (needsBeforeHook) {
|
|
133
|
+
if (refCount === 0) return
|
|
134
|
+
|
|
135
|
+
if (needsBeforeHook && beforeRefCount !== 0 && --beforeRefCount === 0) {
|
|
136
|
+
beforeHook.disable()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (--refCount === 0) {
|
|
140
|
+
uninstallWrappers(storage('legacy'))
|
|
141
|
+
}
|
|
77
142
|
}
|
|
78
143
|
|
|
79
144
|
module.exports = {
|
|
@@ -82,5 +147,6 @@ module.exports = {
|
|
|
82
147
|
spanFinishCh,
|
|
83
148
|
tagsUpdateCh,
|
|
84
149
|
getActiveSpan,
|
|
85
|
-
|
|
150
|
+
acquireChannels,
|
|
151
|
+
releaseChannels,
|
|
86
152
|
}
|