dd-trace 6.2.0 → 6.4.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/README.md +1 -1
- package/index.electron.js +3 -0
- package/package.json +8 -5
- package/packages/datadog-instrumentations/src/ai.js +29 -24
- package/packages/datadog-instrumentations/src/cookie.js +7 -1
- package/packages/datadog-instrumentations/src/cucumber.js +4 -3
- package/packages/datadog-instrumentations/src/express.js +20 -2
- package/packages/datadog-instrumentations/src/grpc/server.js +18 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/modelcontextprotocol-sdk.js +30 -54
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +8 -8
- package/packages/datadog-instrumentations/src/http/server.js +27 -0
- package/packages/datadog-instrumentations/src/http2/server.js +143 -17
- package/packages/datadog-instrumentations/src/jest.js +10 -4
- package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +248 -1
- package/packages/datadog-instrumentations/src/playwright.js +40 -3
- package/packages/datadog-instrumentations/src/router.js +180 -105
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +41 -16
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +21 -21
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +14 -8
- package/packages/datadog-plugin-aws-sdk/src/util.js +0 -22
- package/packages/datadog-plugin-azure-functions/src/index.js +2 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +5 -5
- package/packages/datadog-plugin-graphql/src/execute.js +90 -14
- package/packages/datadog-plugin-graphql/src/parse.js +22 -1
- package/packages/datadog-plugin-graphql/src/request.js +33 -2
- package/packages/datadog-plugin-graphql/src/utils.js +42 -0
- package/packages/datadog-plugin-graphql/src/validate.js +13 -1
- package/packages/datadog-plugin-http2/src/server.js +38 -6
- package/packages/datadog-plugin-jest/src/util.js +21 -6
- package/packages/datadog-plugin-modelcontextprotocol-sdk/src/tracing.js +144 -26
- package/packages/datadog-plugin-modelcontextprotocol-sdk/src/utils.js +30 -0
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +4 -2
- package/packages/datadog-shimmer/src/shimmer.js +9 -2
- package/packages/dd-trace/index.electron.js +3 -0
- package/packages/dd-trace/index.js +2 -37
- package/packages/dd-trace/src/appsec/channels.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +6 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/bootstrap.js +39 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +23 -16
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +14 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +5 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +55 -5
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +8 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/config-types.d.ts +8 -0
- package/packages/dd-trace/src/config/defaults.js +20 -15
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
- package/packages/dd-trace/src/config/index.js +13 -3
- package/packages/dd-trace/src/config/parsers.js +79 -0
- package/packages/dd-trace/src/config/supported-configurations.json +17 -0
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/datastreams/pathway.js +6 -4
- package/packages/dd-trace/src/feature-registry.js +22 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
- package/packages/dd-trace/src/llmobs/index.js +10 -2
- package/packages/dd-trace/src/llmobs/tagger.js +19 -1
- package/packages/dd-trace/src/noop/proxy.js +5 -4
- package/packages/dd-trace/src/openfeature/register.js +46 -0
- package/packages/dd-trace/src/opentelemetry/span_processor.js +7 -5
- package/packages/dd-trace/src/opentelemetry/tracer_provider.js +32 -16
- package/packages/dd-trace/src/opentracing/propagation/log.js +11 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +80 -14
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +10 -1
- package/packages/dd-trace/src/opentracing/tracer.js +7 -1
- package/packages/dd-trace/src/plugins/util/test.js +9 -4
- package/packages/dd-trace/src/plugins/util/web.js +12 -0
- package/packages/dd-trace/src/proxy.js +21 -9
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +20 -11
- package/packages/dd-trace/src/standalone/index.js +0 -22
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
|
@@ -1,55 +1,173 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
3
4
|
const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const {
|
|
7
|
+
DISTRIBUTED_TRACE_META_KEY,
|
|
8
|
+
tagErrorResult,
|
|
9
|
+
} = require('./utils')
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const MCP_REQUEST_SPAN_NAME = 'mcp.request'
|
|
12
|
+
const CLIENT_TOOL_CALL_RESOURCE = 'client_tool_call'
|
|
13
|
+
const CLIENT_LIST_TOOLS_RESOURCE = 'ClientSession.list_tools'
|
|
14
|
+
const SERVER_TOOL_CALL_RESOURCE = 'server_tool_call'
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
function getServerRequestResource (request) {
|
|
17
|
+
if (request?.method === 'tools/call') return SERVER_TOOL_CALL_RESOURCE
|
|
18
|
+
return request?.method
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class McpPlugin extends TracingPlugin {
|
|
22
|
+
bindStart (ctx) {
|
|
23
|
+
const spanOptions = {
|
|
24
|
+
resource: this.getResource(ctx),
|
|
15
25
|
type: 'mcp',
|
|
16
|
-
kind:
|
|
17
|
-
}
|
|
26
|
+
kind: this.constructor.kind,
|
|
27
|
+
}
|
|
28
|
+
const childOf = this.getChildOf(ctx)
|
|
29
|
+
if (childOf) spanOptions.childOf = childOf
|
|
18
30
|
|
|
31
|
+
this.startSpan(this.constructor.spanName, spanOptions, ctx)
|
|
32
|
+
const span = ctx.currentStore?.span
|
|
33
|
+
if (span) this.onStart(span, ctx)
|
|
19
34
|
return ctx.currentStore
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
asyncEnd (ctx) {
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
const span = ctx.currentStore?.span
|
|
26
|
-
const errorText = result.content?.find?.(c => c.type === 'text')?.text || 'Tool call returned isError: true'
|
|
27
|
-
span?.setTag('error', new Error(errorText))
|
|
28
|
-
}
|
|
38
|
+
const span = ctx.currentStore?.span
|
|
39
|
+
if (span) this.onEnd(span, ctx)
|
|
29
40
|
super.finish(ctx)
|
|
30
41
|
}
|
|
42
|
+
|
|
43
|
+
getResource () {}
|
|
44
|
+
getChildOf () {}
|
|
45
|
+
onStart () {}
|
|
46
|
+
onEnd () {}
|
|
31
47
|
}
|
|
32
48
|
|
|
33
|
-
class
|
|
49
|
+
class McpPropagationPlugin extends Plugin {
|
|
50
|
+
static id = 'modelcontextprotocol_propagation'
|
|
51
|
+
|
|
52
|
+
constructor (...args) {
|
|
53
|
+
super(...args)
|
|
54
|
+
this.addSub('apm:mcp:client:request:inject', this.injectTraceContext.bind(this))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
injectTraceContext (ctx) {
|
|
58
|
+
const span = this.tracer.scope().active()
|
|
59
|
+
if (!span) return
|
|
60
|
+
|
|
61
|
+
const traceContext = {}
|
|
62
|
+
this.tracer.inject(span, 'text_map', traceContext)
|
|
63
|
+
ctx.traceContext = traceContext
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class McpToolCallPlugin extends McpPlugin {
|
|
68
|
+
static id = 'modelcontextprotocol_client'
|
|
69
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_callTool'
|
|
70
|
+
static spanName = MCP_REQUEST_SPAN_NAME
|
|
71
|
+
static kind = 'client'
|
|
72
|
+
getResource () { return CLIENT_TOOL_CALL_RESOURCE }
|
|
73
|
+
onEnd (span, ctx) { tagErrorResult(span, ctx.result) }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class McpListToolsPlugin extends McpPlugin {
|
|
34
77
|
static id = 'modelcontextprotocol_list_tools'
|
|
35
78
|
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_listTools'
|
|
79
|
+
static spanName = MCP_REQUEST_SPAN_NAME
|
|
80
|
+
static kind = 'client'
|
|
81
|
+
getResource () { return CLIENT_LIST_TOOLS_RESOURCE }
|
|
82
|
+
}
|
|
36
83
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
84
|
+
class McpListResourcesPlugin extends McpPlugin {
|
|
85
|
+
static id = 'modelcontextprotocol_list_resources'
|
|
86
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_listResources'
|
|
87
|
+
static spanName = 'mcp.resources.list'
|
|
88
|
+
static kind = 'client'
|
|
89
|
+
getResource () { return 'resources/list' }
|
|
90
|
+
}
|
|
43
91
|
|
|
44
|
-
|
|
92
|
+
class McpReadResourcePlugin extends McpPlugin {
|
|
93
|
+
static id = 'modelcontextprotocol_read_resource'
|
|
94
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_readResource'
|
|
95
|
+
static spanName = 'mcp.resource.read'
|
|
96
|
+
static kind = 'client'
|
|
97
|
+
getResource () { return 'resources/read' }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class McpListPromptsPlugin extends McpPlugin {
|
|
101
|
+
static id = 'modelcontextprotocol_list_prompts'
|
|
102
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_listPrompts'
|
|
103
|
+
static spanName = 'mcp.prompts.list'
|
|
104
|
+
static kind = 'client'
|
|
105
|
+
getResource () { return 'prompts/list' }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class McpGetPromptPlugin extends McpPlugin {
|
|
109
|
+
static id = 'modelcontextprotocol_get_prompt'
|
|
110
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_getPrompt'
|
|
111
|
+
static spanName = 'mcp.prompt.get'
|
|
112
|
+
static kind = 'client'
|
|
113
|
+
getResource () { return 'prompts/get' }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class McpServerRequestPlugin extends McpPlugin {
|
|
117
|
+
static id = 'modelcontextprotocol_server'
|
|
118
|
+
static prefix = 'tracing:apm:mcp:server:request'
|
|
119
|
+
static spanName = MCP_REQUEST_SPAN_NAME
|
|
120
|
+
static kind = 'server'
|
|
121
|
+
getResource (ctx) { return getServerRequestResource(ctx.request) }
|
|
122
|
+
getChildOf (ctx) {
|
|
123
|
+
const traceContext = ctx.request?.params?._meta?.[DISTRIBUTED_TRACE_META_KEY]
|
|
124
|
+
if (!traceContext || typeof traceContext !== 'object') return
|
|
125
|
+
|
|
126
|
+
const childOf = this.tracer.extract('text_map', traceContext)
|
|
127
|
+
const activeSpan = this.activeSpan
|
|
128
|
+
if (!childOf || activeSpan?.context().toTraceId() === childOf.toTraceId()) return
|
|
129
|
+
|
|
130
|
+
return childOf
|
|
45
131
|
}
|
|
46
132
|
|
|
47
|
-
|
|
48
|
-
|
|
133
|
+
onEnd (span, ctx) {
|
|
134
|
+
if (ctx.error) {
|
|
135
|
+
span.setTag('error', ctx.error)
|
|
136
|
+
} else {
|
|
137
|
+
tagErrorResult(span, ctx.result)
|
|
138
|
+
}
|
|
49
139
|
}
|
|
50
140
|
}
|
|
51
141
|
|
|
142
|
+
class McpServerToolCallPlugin extends McpPlugin {
|
|
143
|
+
static id = 'modelcontextprotocol_server_tool'
|
|
144
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:McpServer_executeToolHandler'
|
|
145
|
+
static spanName = 'mcp.server.tool.call'
|
|
146
|
+
static kind = 'internal'
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {...unknown} args Plugin constructor arguments.
|
|
150
|
+
*/
|
|
151
|
+
constructor (...args) {
|
|
152
|
+
super(...args)
|
|
153
|
+
this.toolNames = new WeakMap()
|
|
154
|
+
this.addSub('apm:mcp:server:tool:registered', ({ tool, name }) => {
|
|
155
|
+
this.toolNames.set(tool, name)
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
getResource (ctx) { return this.toolNames.get(ctx.arguments?.[0]) }
|
|
160
|
+
onEnd (span, ctx) { tagErrorResult(span, ctx.result) }
|
|
161
|
+
}
|
|
162
|
+
|
|
52
163
|
module.exports = [
|
|
164
|
+
McpPropagationPlugin,
|
|
53
165
|
McpToolCallPlugin,
|
|
54
166
|
McpListToolsPlugin,
|
|
167
|
+
McpListResourcesPlugin,
|
|
168
|
+
McpReadResourcePlugin,
|
|
169
|
+
McpListPromptsPlugin,
|
|
170
|
+
McpGetPromptPlugin,
|
|
171
|
+
McpServerRequestPlugin,
|
|
172
|
+
McpServerToolCallPlugin,
|
|
55
173
|
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { ERROR_MESSAGE, ERROR_TYPE } = require('../../dd-trace/src/constants')
|
|
4
|
+
|
|
5
|
+
const DISTRIBUTED_TRACE_META_KEY = '_dd_trace_context'
|
|
6
|
+
|
|
7
|
+
function getFirstTextContent (content) {
|
|
8
|
+
if (!Array.isArray(content)) return
|
|
9
|
+
|
|
10
|
+
for (const item of content) {
|
|
11
|
+
if (item.type === 'text' && item.text) return item.text
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function setErrorTags (span, message) {
|
|
16
|
+
span.setTag('error', 1)
|
|
17
|
+
span.setTag(ERROR_TYPE, 'Error')
|
|
18
|
+
span.setTag(ERROR_MESSAGE, message)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function tagErrorResult (span, result) {
|
|
22
|
+
if (result?.isError) {
|
|
23
|
+
setErrorTags(span, getFirstTextContent(result.content) || 'Tool call returned isError: true')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
DISTRIBUTED_TRACE_META_KEY,
|
|
29
|
+
tagErrorResult,
|
|
30
|
+
}
|
|
@@ -68,7 +68,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
68
68
|
}) => {
|
|
69
69
|
const testSuite = getTestSuitePath(filePath, this.repositoryRoot)
|
|
70
70
|
const isModified = isModifiedTest(testSuite, 0, 0, modifiedFiles, this.constructor.id)
|
|
71
|
-
onDone(
|
|
71
|
+
onDone(isModified)
|
|
72
72
|
})
|
|
73
73
|
|
|
74
74
|
this.addSub('ci:playwright:session:finish', ({
|
|
@@ -264,8 +264,10 @@ class VitestPlugin extends CiPlugin {
|
|
|
264
264
|
span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
|
|
265
265
|
}
|
|
266
266
|
const finish = () => {
|
|
267
|
-
if (duration) {
|
|
268
|
-
span.finish(
|
|
267
|
+
if (Number.isFinite(duration) && duration >= 0) {
|
|
268
|
+
span.finish(
|
|
269
|
+
span._startTime + Math.max(duration - MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION, 0)
|
|
270
|
+
) // milliseconds
|
|
269
271
|
} else {
|
|
270
272
|
span.finish() // `duration` is empty for retries, so we'll use clock time
|
|
271
273
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { isModuleNamespaceObject } = require('node:util').types
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* @type {Set<string | symbol>}
|
|
5
7
|
*/
|
|
@@ -168,14 +170,19 @@ function wrap (target, name, wrapper, options) {
|
|
|
168
170
|
|
|
169
171
|
copyProperties(original, wrapped)
|
|
170
172
|
|
|
171
|
-
|
|
173
|
+
const immutableModuleNamespace = descriptor.configurable === false &&
|
|
174
|
+
descriptor.writable && isModuleNamespaceObject(target)
|
|
175
|
+
|
|
176
|
+
if (descriptor.writable && !immutableModuleNamespace) {
|
|
172
177
|
if (descriptor.configurable && descriptor.enumerable) {
|
|
173
178
|
target[name] = wrapped
|
|
174
179
|
return target
|
|
175
180
|
}
|
|
176
181
|
descriptor.value = wrapped
|
|
177
182
|
} else {
|
|
178
|
-
if (
|
|
183
|
+
if (immutableModuleNamespace) {
|
|
184
|
+
descriptor.value = wrapped
|
|
185
|
+
} else if (descriptor.set && options?.replaceGetter) {
|
|
179
186
|
// A lazy accessor pair (e.g. Node 20's `fs.opendir`). `original` already
|
|
180
187
|
// resolved the value through the getter. Keep the property an accessor pair
|
|
181
188
|
// so the shape stays observationally identical — a downstream consumer may
|
|
@@ -1,39 +1,4 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// Set up beforeExitHandlers before loading the tracer so that modules loaded
|
|
7
|
-
// during require('./src') can register handlers.
|
|
8
|
-
Object.defineProperty(globalThis, ddTraceSymbol, {
|
|
9
|
-
value: {
|
|
10
|
-
beforeExitHandlers: new Set(),
|
|
11
|
-
},
|
|
12
|
-
enumerable: false,
|
|
13
|
-
configurable: true,
|
|
14
|
-
writable: false,
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
process.once('beforeExit', function mainBeforeExit () {
|
|
18
|
-
if (globalThis[ddTraceSymbol]?.beforeExitHandlers) {
|
|
19
|
-
for (const handler of globalThis[ddTraceSymbol].beforeExitHandlers) {
|
|
20
|
-
handler()
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const TracerProxy = require('./src')
|
|
26
|
-
|
|
27
|
-
Object.defineProperty(global, '_ddtrace', {
|
|
28
|
-
value: new TracerProxy(),
|
|
29
|
-
enumerable: false,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = global._ddtrace
|
|
36
|
-
// Static aliases so cjs-module-lexer surfaces them as ESM named exports
|
|
37
|
-
// (`import { tracer } from 'dd-trace'`).
|
|
38
|
-
module.exports.tracer = global._ddtrace
|
|
39
|
-
module.exports.default = global._ddtrace
|
|
3
|
+
require('./src/openfeature/register')
|
|
4
|
+
module.exports = require('./src/bootstrap')
|
|
@@ -25,6 +25,7 @@ module.exports = {
|
|
|
25
25
|
httpClientRequestStart: dc.channel('apm:http:client:request:start'),
|
|
26
26
|
httpClientResponseStart: dc.channel('apm:http:client:response:start'),
|
|
27
27
|
httpClientResponseFinish: dc.channel('apm:http:client:response:finish'),
|
|
28
|
+
informationalResponse: dc.channel('datadog:http:server:informational-response:start'),
|
|
28
29
|
incomingHttpRequestEnd: dc.channel('dd-trace:incomingHttpRequestEnd'),
|
|
29
30
|
incomingHttpRequestStart: dc.channel('dd-trace:incomingHttpRequestStart'),
|
|
30
31
|
lambdaStartInvocation: dc.channel('datadog:lambda:start-invocation'),
|
|
@@ -29,6 +29,7 @@ const {
|
|
|
29
29
|
responseBody,
|
|
30
30
|
responseWriteHead,
|
|
31
31
|
responseSetHeader,
|
|
32
|
+
informationalResponse,
|
|
32
33
|
routerParam,
|
|
33
34
|
fastifyResponseChannel,
|
|
34
35
|
fastifyPathParams,
|
|
@@ -98,7 +99,8 @@ function enable (_config) {
|
|
|
98
99
|
responseBody.subscribe(onResponseBody)
|
|
99
100
|
fastifyResponseChannel.subscribe(onResponseBody)
|
|
100
101
|
responseWriteHead.subscribe(onResponseWriteHead)
|
|
101
|
-
responseSetHeader.subscribe(
|
|
102
|
+
responseSetHeader.subscribe(onResponseOperation)
|
|
103
|
+
informationalResponse.subscribe(onResponseOperation)
|
|
102
104
|
stripeCheckoutSessionCreate.subscribe(onStripeCheckoutSessionCreate)
|
|
103
105
|
stripePaymentIntentCreate.subscribe(onStripePaymentIntentCreate)
|
|
104
106
|
stripeConstructEvent.subscribe(onStripeConstructEvent)
|
|
@@ -403,7 +405,7 @@ function onResponseWriteHead ({ req, res, abortController, statusCode, responseH
|
|
|
403
405
|
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
404
406
|
}
|
|
405
407
|
|
|
406
|
-
function
|
|
408
|
+
function onResponseOperation ({ res, abortController }) {
|
|
407
409
|
if (isBlocked(res)) {
|
|
408
410
|
abortController?.abort()
|
|
409
411
|
}
|
|
@@ -547,7 +549,8 @@ function disable () {
|
|
|
547
549
|
if (responseBody.hasSubscribers) responseBody.unsubscribe(onResponseBody)
|
|
548
550
|
if (fastifyResponseChannel.hasSubscribers) fastifyResponseChannel.unsubscribe(onResponseBody)
|
|
549
551
|
if (responseWriteHead.hasSubscribers) responseWriteHead.unsubscribe(onResponseWriteHead)
|
|
550
|
-
if (responseSetHeader.hasSubscribers) responseSetHeader.unsubscribe(
|
|
552
|
+
if (responseSetHeader.hasSubscribers) responseSetHeader.unsubscribe(onResponseOperation)
|
|
553
|
+
if (informationalResponse.hasSubscribers) informationalResponse.unsubscribe(onResponseOperation)
|
|
551
554
|
if (stripeCheckoutSessionCreate.hasSubscribers) stripeCheckoutSessionCreate.unsubscribe(onStripeCheckoutSessionCreate)
|
|
552
555
|
if (stripePaymentIntentCreate.hasSubscribers) stripePaymentIntentCreate.unsubscribe(onStripePaymentIntentCreate)
|
|
553
556
|
if (stripeConstructEvent.hasSubscribers) stripeConstructEvent.unsubscribe(onStripeConstructEvent)
|
|
@@ -42,7 +42,7 @@ class WAFManager {
|
|
|
42
42
|
this.ddwafVersion = this.ddwafVersion || 'unknown'
|
|
43
43
|
Reporter.reportWafInit(this.ddwafVersion, 'unknown')
|
|
44
44
|
|
|
45
|
-
log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.')
|
|
45
|
+
log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.', err)
|
|
46
46
|
|
|
47
47
|
throw err
|
|
48
48
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
if (!global._ddtrace) {
|
|
4
|
+
const ddTraceSymbol = Symbol.for('dd-trace')
|
|
5
|
+
|
|
6
|
+
// Set up beforeExitHandlers before loading the tracer so that modules loaded
|
|
7
|
+
// during require('./src') can register handlers.
|
|
8
|
+
Object.defineProperty(globalThis, ddTraceSymbol, {
|
|
9
|
+
value: {
|
|
10
|
+
beforeExitHandlers: new Set(),
|
|
11
|
+
},
|
|
12
|
+
enumerable: false,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: false,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
process.once('beforeExit', function mainBeforeExit () {
|
|
18
|
+
if (globalThis[ddTraceSymbol]?.beforeExitHandlers) {
|
|
19
|
+
for (const handler of globalThis[ddTraceSymbol].beforeExitHandlers) {
|
|
20
|
+
handler()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const TracerProxy = require('.')
|
|
26
|
+
|
|
27
|
+
Object.defineProperty(global, '_ddtrace', {
|
|
28
|
+
value: new TracerProxy(),
|
|
29
|
+
enumerable: false,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = global._ddtrace
|
|
36
|
+
// Static aliases so cjs-module-lexer surfaces them as ESM named exports
|
|
37
|
+
// (`import { tracer } from 'dd-trace'`).
|
|
38
|
+
module.exports.tracer = global._ddtrace
|
|
39
|
+
module.exports.default = global._ddtrace
|
|
@@ -51,12 +51,20 @@ const limits = {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* @param {object} value - Snapshot object or sub-object.
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
function isCapturedValue (value) {
|
|
58
|
+
return typeof value.type === 'string'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Remove empty capture containers before sending snapshots through the Test Optimization logs path.
|
|
55
63
|
*
|
|
56
64
|
* @param {object} value - Snapshot object or sub-object.
|
|
57
65
|
* @returns {void}
|
|
58
66
|
*/
|
|
59
|
-
function
|
|
67
|
+
function removeEmptyCaptureProperties (value) {
|
|
60
68
|
const stack = [value]
|
|
61
69
|
|
|
62
70
|
while (stack.length > 0) {
|
|
@@ -72,26 +80,25 @@ function removeEmptyCollectionProperties (value) {
|
|
|
72
80
|
continue
|
|
73
81
|
}
|
|
74
82
|
|
|
75
|
-
if (
|
|
76
|
-
if (current.elements.length === 0) {
|
|
83
|
+
if (isCapturedValue(current)) {
|
|
84
|
+
if (current.elements === null || (Array.isArray(current.elements) && current.elements.length === 0)) {
|
|
77
85
|
delete current.elements
|
|
78
|
-
} else {
|
|
79
|
-
stack.push(current.elements)
|
|
80
86
|
}
|
|
81
|
-
}
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
if (current.entries.length === 0) {
|
|
88
|
+
if (current.entries === null || (Array.isArray(current.entries) && current.entries.length === 0)) {
|
|
85
89
|
delete current.entries
|
|
86
|
-
} else {
|
|
87
|
-
stack.push(current.entries)
|
|
88
90
|
}
|
|
89
|
-
}
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
if (current.fields === null || (
|
|
93
|
+
current.fields &&
|
|
94
|
+
typeof current.fields === 'object' &&
|
|
95
|
+
Object.keys(current.fields).length === 0
|
|
96
|
+
)) {
|
|
97
|
+
delete current.fields
|
|
98
|
+
}
|
|
99
|
+
}
|
|
93
100
|
|
|
94
|
-
|
|
101
|
+
for (const child of Object.values(current)) {
|
|
95
102
|
if (child && typeof child === 'object') {
|
|
96
103
|
stack.push(child)
|
|
97
104
|
}
|
|
@@ -129,7 +136,7 @@ session.on('Debugger.paused', async ({ params: { hitBreakpoints: [hitBreakpoint]
|
|
|
129
136
|
language: 'javascript',
|
|
130
137
|
}
|
|
131
138
|
|
|
132
|
-
|
|
139
|
+
removeEmptyCaptureProperties(snapshot.captures)
|
|
133
140
|
|
|
134
141
|
if (processTags) {
|
|
135
142
|
snapshot[processTags.DYNAMIC_INSTRUMENTATION_FIELD_NAME] = processTags.tagsObject
|
|
@@ -293,6 +293,9 @@ class CiVisibilityExporter extends BufferingExporter {
|
|
|
293
293
|
isCoverageReportUploadEnabled,
|
|
294
294
|
} = remoteConfiguration
|
|
295
295
|
const { testOptimization } = this._config
|
|
296
|
+
const earlyFlakeDetectionRetryCount =
|
|
297
|
+
testOptimization.DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT
|
|
298
|
+
const hasEarlyFlakeDetectionRetryCount = earlyFlakeDetectionRetryCount !== undefined
|
|
296
299
|
return {
|
|
297
300
|
isCodeCoverageEnabled,
|
|
298
301
|
isSuitesSkippingEnabled,
|
|
@@ -300,8 +303,16 @@ class CiVisibilityExporter extends BufferingExporter {
|
|
|
300
303
|
requireGit,
|
|
301
304
|
isEarlyFlakeDetectionEnabled:
|
|
302
305
|
isEarlyFlakeDetectionEnabled && testOptimization.DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED,
|
|
303
|
-
earlyFlakeDetectionNumRetries
|
|
304
|
-
|
|
306
|
+
earlyFlakeDetectionNumRetries:
|
|
307
|
+
hasEarlyFlakeDetectionRetryCount ? earlyFlakeDetectionRetryCount : earlyFlakeDetectionNumRetries,
|
|
308
|
+
earlyFlakeDetectionSlowTestRetries: hasEarlyFlakeDetectionRetryCount
|
|
309
|
+
? {
|
|
310
|
+
'5s': earlyFlakeDetectionRetryCount,
|
|
311
|
+
'10s': earlyFlakeDetectionRetryCount,
|
|
312
|
+
'30s': earlyFlakeDetectionRetryCount,
|
|
313
|
+
'5m': earlyFlakeDetectionRetryCount,
|
|
314
|
+
}
|
|
315
|
+
: earlyFlakeDetectionSlowTestRetries,
|
|
305
316
|
earlyFlakeDetectionFaultyThreshold,
|
|
306
317
|
isFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled && testOptimization.DD_CIVISIBILITY_FLAKY_RETRY_ENABLED,
|
|
307
318
|
flakyTestRetriesCount: testOptimization.DD_CIVISIBILITY_FLAKY_RETRY_COUNT,
|
|
@@ -318,6 +329,7 @@ class CiVisibilityExporter extends BufferingExporter {
|
|
|
318
329
|
|
|
319
330
|
sendGitMetadata (repositoryUrl) {
|
|
320
331
|
if (!this._config.testOptimization.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED) {
|
|
332
|
+
this._resolveGit()
|
|
321
333
|
return
|
|
322
334
|
}
|
|
323
335
|
this._canUseCiVisProtocolPromise.then((canUseCiVisProtocol) => {
|
|
@@ -102,14 +102,30 @@ class TestWorkerCiVisibilityExporter {
|
|
|
102
102
|
this._logsWriter.append({ testEnvironmentMetadata, logMessage })
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
/**
|
|
106
|
+
* @param {() => void} [onDone]
|
|
107
|
+
*/
|
|
106
108
|
flush (onDone) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
this._telemetryWriter
|
|
109
|
+
if (!onDone) {
|
|
110
|
+
this._writer.flush()
|
|
111
|
+
this._coverageWriter.flush()
|
|
112
|
+
this._logsWriter.flush()
|
|
113
|
+
if (this._telemetryWriter) {
|
|
114
|
+
this._telemetryWriter.flush()
|
|
115
|
+
}
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let pendingWriters = this._telemetryWriter ? 4 : 3
|
|
120
|
+
const onWriterFlushed = () => {
|
|
121
|
+
pendingWriters--
|
|
122
|
+
if (pendingWriters === 0) onDone()
|
|
112
123
|
}
|
|
124
|
+
|
|
125
|
+
this._writer.flush(onWriterFlushed)
|
|
126
|
+
this._coverageWriter.flush(onWriterFlushed)
|
|
127
|
+
this._logsWriter.flush(onWriterFlushed)
|
|
128
|
+
this._telemetryWriter?.flush(onWriterFlushed)
|
|
113
129
|
}
|
|
114
130
|
}
|
|
115
131
|
|
|
@@ -15,6 +15,9 @@ class Writer {
|
|
|
15
15
|
this._interprocessCode = interprocessCode
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @param {() => void} [onDone]
|
|
20
|
+
*/
|
|
18
21
|
flush (onDone) {
|
|
19
22
|
const count = this._encoder.count()
|
|
20
23
|
|
|
@@ -22,6 +25,8 @@ class Writer {
|
|
|
22
25
|
const payload = this._encoder.makePayload()
|
|
23
26
|
|
|
24
27
|
this._sendPayload(payload, onDone)
|
|
28
|
+
} else {
|
|
29
|
+
onDone?.()
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
|