dd-trace 5.32.0 → 5.33.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 +12 -11
- package/index.d.ts +11 -1
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/aws-sdk.js +3 -1
- package/packages/datadog-instrumentations/src/cucumber.js +17 -9
- package/packages/datadog-instrumentations/src/jest.js +36 -21
- package/packages/datadog-instrumentations/src/mocha/main.js +9 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +4 -2
- package/packages/datadog-instrumentations/src/mocha/worker.js +4 -2
- package/packages/datadog-instrumentations/src/playwright.js +8 -3
- package/packages/datadog-instrumentations/src/vitest.js +35 -11
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +16 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +63 -0
- package/packages/datadog-plugin-aws-sdk/src/services/{bedrockruntime.js → bedrockruntime/utils.js} +67 -75
- package/packages/datadog-plugin-cucumber/src/index.js +3 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +19 -8
- package/packages/datadog-plugin-cypress/src/support.js +6 -2
- package/packages/datadog-plugin-fetch/src/index.js +3 -3
- package/packages/datadog-plugin-http/src/client.js +5 -33
- package/packages/datadog-plugin-jest/src/index.js +4 -1
- package/packages/datadog-plugin-mocha/src/index.js +3 -1
- package/packages/datadog-plugin-playwright/src/index.js +3 -1
- package/packages/datadog-plugin-vitest/src/index.js +16 -4
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +3 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +41 -24
- package/packages/dd-trace/src/appsec/iast/iast-context.js +12 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +19 -23
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +75 -24
- package/packages/dd-trace/src/appsec/rasp/utils.js +10 -5
- package/packages/dd-trace/src/appsec/stack_trace.js +38 -28
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +5 -3
- package/packages/dd-trace/src/config.js +4 -0
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +59 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +1 -0
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +0 -2
- package/packages/dd-trace/src/plugins/util/test.js +2 -0
|
@@ -6,11 +6,18 @@ const ddBasePath = calculateDDBasePath(__dirname)
|
|
|
6
6
|
|
|
7
7
|
const LIBRARY_FRAMES_BUFFER = 20
|
|
8
8
|
|
|
9
|
+
const STACK_TRACE_NAMESPACES = {
|
|
10
|
+
RASP: 'exploit',
|
|
11
|
+
IAST: 'vulnerability'
|
|
12
|
+
}
|
|
13
|
+
|
|
9
14
|
function getCallSiteList (maxDepth = 100) {
|
|
10
15
|
const previousPrepareStackTrace = Error.prepareStackTrace
|
|
11
16
|
const previousStackTraceLimit = Error.stackTraceLimit
|
|
12
17
|
let callsiteList
|
|
13
|
-
|
|
18
|
+
// Since some frames will be discarded because they come from tracer codebase, a buffer is added
|
|
19
|
+
// to the limit in order to get as close as `maxDepth` number of frames.
|
|
20
|
+
Error.stackTraceLimit = maxDepth + LIBRARY_FRAMES_BUFFER
|
|
14
21
|
|
|
15
22
|
try {
|
|
16
23
|
Error.prepareStackTrace = function (_, callsites) {
|
|
@@ -30,7 +37,10 @@ function filterOutFramesFromLibrary (callSiteList) {
|
|
|
30
37
|
return callSiteList.filter(callSite => !callSite.getFileName()?.startsWith(ddBasePath))
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
function
|
|
40
|
+
function getCallsiteFrames (maxDepth = 32, callSiteListGetter = getCallSiteList) {
|
|
41
|
+
if (maxDepth < 1) maxDepth = Infinity
|
|
42
|
+
|
|
43
|
+
const callSiteList = callSiteListGetter(maxDepth)
|
|
34
44
|
const filteredFrames = filterOutFramesFromLibrary(callSiteList)
|
|
35
45
|
|
|
36
46
|
const half = filteredFrames.length > maxDepth ? Math.round(maxDepth / 2) : Infinity
|
|
@@ -45,46 +55,46 @@ function getFramesForMetaStruct (callSiteList, maxDepth = 32) {
|
|
|
45
55
|
line: callSite.getLineNumber(),
|
|
46
56
|
column: callSite.getColumnNumber(),
|
|
47
57
|
function: callSite.getFunctionName(),
|
|
48
|
-
class_name: callSite.getTypeName()
|
|
58
|
+
class_name: callSite.getTypeName(),
|
|
59
|
+
isNative: callSite.isNative()
|
|
49
60
|
})
|
|
50
61
|
}
|
|
51
62
|
|
|
52
63
|
return indexedFrames
|
|
53
64
|
}
|
|
54
65
|
|
|
55
|
-
function reportStackTrace (rootSpan, stackId,
|
|
66
|
+
function reportStackTrace (rootSpan, stackId, frames, namespace = STACK_TRACE_NAMESPACES.RASP) {
|
|
56
67
|
if (!rootSpan) return
|
|
68
|
+
if (!Array.isArray(frames)) return
|
|
57
69
|
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (maxDepth < 1) maxDepth = Infinity
|
|
62
|
-
const callSiteList = callSiteListGetter(maxDepth + LIBRARY_FRAMES_BUFFER)
|
|
63
|
-
if (!Array.isArray(callSiteList)) return
|
|
70
|
+
if (!rootSpan.meta_struct) {
|
|
71
|
+
rootSpan.meta_struct = {}
|
|
72
|
+
}
|
|
64
73
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
if (!rootSpan.meta_struct['_dd.stack']) {
|
|
75
|
+
rootSpan.meta_struct['_dd.stack'] = {}
|
|
76
|
+
}
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
if (!rootSpan.meta_struct['_dd.stack'][namespace]) {
|
|
79
|
+
rootSpan.meta_struct['_dd.stack'][namespace] = []
|
|
80
|
+
}
|
|
72
81
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
rootSpan.meta_struct['_dd.stack'][namespace].push({
|
|
83
|
+
id: stackId,
|
|
84
|
+
language: 'nodejs',
|
|
85
|
+
frames
|
|
86
|
+
})
|
|
87
|
+
}
|
|
76
88
|
|
|
77
|
-
|
|
89
|
+
function canReportStackTrace (rootSpan, maxStackTraces, namespace = STACK_TRACE_NAMESPACES.RASP) {
|
|
90
|
+
if (!rootSpan) return false
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
id: stackId,
|
|
81
|
-
language: 'nodejs',
|
|
82
|
-
frames
|
|
83
|
-
})
|
|
84
|
-
}
|
|
92
|
+
return maxStackTraces < 1 || (rootSpan.meta_struct?.['_dd.stack']?.[namespace]?.length ?? 0) < maxStackTraces
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
module.exports = {
|
|
88
|
-
|
|
89
|
-
reportStackTrace
|
|
96
|
+
getCallsiteFrames,
|
|
97
|
+
reportStackTrace,
|
|
98
|
+
canReportStackTrace,
|
|
99
|
+
STACK_TRACE_NAMESPACES
|
|
90
100
|
}
|
|
@@ -87,9 +87,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
87
87
|
|
|
88
88
|
shouldRequestKnownTests () {
|
|
89
89
|
return !!(
|
|
90
|
-
this._config.isEarlyFlakeDetectionEnabled &&
|
|
91
90
|
this._canUseCiVisProtocol &&
|
|
92
|
-
this._libraryConfig?.
|
|
91
|
+
this._libraryConfig?.isKnownTestsEnabled
|
|
93
92
|
)
|
|
94
93
|
}
|
|
95
94
|
|
|
@@ -197,7 +196,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
197
196
|
earlyFlakeDetectionNumRetries,
|
|
198
197
|
earlyFlakeDetectionFaultyThreshold,
|
|
199
198
|
isFlakyTestRetriesEnabled,
|
|
200
|
-
isDiEnabled
|
|
199
|
+
isDiEnabled,
|
|
200
|
+
isKnownTestsEnabled
|
|
201
201
|
} = remoteConfiguration
|
|
202
202
|
return {
|
|
203
203
|
isCodeCoverageEnabled,
|
|
@@ -209,7 +209,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
209
209
|
earlyFlakeDetectionFaultyThreshold,
|
|
210
210
|
isFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled && this._config.isFlakyTestRetriesEnabled,
|
|
211
211
|
flakyTestRetriesCount: this._config.flakyTestRetriesCount,
|
|
212
|
-
isDiEnabled: isDiEnabled && this._config.isTestDynamicInstrumentationEnabled
|
|
212
|
+
isDiEnabled: isDiEnabled && this._config.isTestDynamicInstrumentationEnabled,
|
|
213
|
+
isKnownTestsEnabled
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
|
|
@@ -93,7 +93,8 @@ function getLibraryConfiguration ({
|
|
|
93
93
|
require_git: requireGit,
|
|
94
94
|
early_flake_detection: earlyFlakeDetectionConfig,
|
|
95
95
|
flaky_test_retries_enabled: isFlakyTestRetriesEnabled,
|
|
96
|
-
di_enabled: isDiEnabled
|
|
96
|
+
di_enabled: isDiEnabled,
|
|
97
|
+
known_tests_enabled: isKnownTestsEnabled
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
} = JSON.parse(res)
|
|
@@ -103,13 +104,14 @@ function getLibraryConfiguration ({
|
|
|
103
104
|
isSuitesSkippingEnabled,
|
|
104
105
|
isItrEnabled,
|
|
105
106
|
requireGit,
|
|
106
|
-
isEarlyFlakeDetectionEnabled: earlyFlakeDetectionConfig?.enabled ?? false,
|
|
107
|
+
isEarlyFlakeDetectionEnabled: isKnownTestsEnabled && (earlyFlakeDetectionConfig?.enabled ?? false),
|
|
107
108
|
earlyFlakeDetectionNumRetries:
|
|
108
109
|
earlyFlakeDetectionConfig?.slow_test_retries?.['5s'] || DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES,
|
|
109
110
|
earlyFlakeDetectionFaultyThreshold:
|
|
110
111
|
earlyFlakeDetectionConfig?.faulty_session_threshold ?? DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD,
|
|
111
112
|
isFlakyTestRetriesEnabled,
|
|
112
|
-
isDiEnabled: isDiEnabled && isFlakyTestRetriesEnabled
|
|
113
|
+
isDiEnabled: isDiEnabled && isFlakyTestRetriesEnabled,
|
|
114
|
+
isKnownTestsEnabled
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
log.debug(() => `Remote settings: ${JSON.stringify(settings)}`)
|
|
@@ -497,6 +497,7 @@ class Config {
|
|
|
497
497
|
this._setValue(defaults, 'iast.redactionValuePattern', null)
|
|
498
498
|
this._setValue(defaults, 'iast.requestSampling', 30)
|
|
499
499
|
this._setValue(defaults, 'iast.telemetryVerbosity', 'INFORMATION')
|
|
500
|
+
this._setValue(defaults, 'iast.stackTrace.enabled', true)
|
|
500
501
|
this._setValue(defaults, 'injectionEnabled', [])
|
|
501
502
|
this._setValue(defaults, 'isAzureFunction', false)
|
|
502
503
|
this._setValue(defaults, 'isCiVisibility', false)
|
|
@@ -622,6 +623,7 @@ class Config {
|
|
|
622
623
|
DD_IAST_REDACTION_VALUE_PATTERN,
|
|
623
624
|
DD_IAST_REQUEST_SAMPLING,
|
|
624
625
|
DD_IAST_TELEMETRY_VERBOSITY,
|
|
626
|
+
DD_IAST_STACK_TRACE_ENABLED,
|
|
625
627
|
DD_INJECTION_ENABLED,
|
|
626
628
|
DD_INSTRUMENTATION_TELEMETRY_ENABLED,
|
|
627
629
|
DD_INSTRUMENTATION_CONFIG_ID,
|
|
@@ -787,6 +789,7 @@ class Config {
|
|
|
787
789
|
}
|
|
788
790
|
this._envUnprocessed['iast.requestSampling'] = DD_IAST_REQUEST_SAMPLING
|
|
789
791
|
this._setString(env, 'iast.telemetryVerbosity', DD_IAST_TELEMETRY_VERBOSITY)
|
|
792
|
+
this._setBoolean(env, 'iast.stackTrace.enabled', DD_IAST_STACK_TRACE_ENABLED)
|
|
790
793
|
this._setArray(env, 'injectionEnabled', DD_INJECTION_ENABLED)
|
|
791
794
|
this._setBoolean(env, 'isAzureFunction', getIsAzureFunction())
|
|
792
795
|
this._setBoolean(env, 'isGCPFunction', getIsGCPFunction())
|
|
@@ -976,6 +979,7 @@ class Config {
|
|
|
976
979
|
this._optsUnprocessed['iast.requestSampling'] = options.iast?.requestSampling
|
|
977
980
|
}
|
|
978
981
|
this._setString(opts, 'iast.telemetryVerbosity', options.iast && options.iast.telemetryVerbosity)
|
|
982
|
+
this._setBoolean(opts, 'iast.stackTrace.enabled', options.iast?.stackTrace?.enabled)
|
|
979
983
|
this._setBoolean(opts, 'isCiVisibility', options.isCiVisibility)
|
|
980
984
|
this._setBoolean(opts, 'legacyBaggageEnabled', options.legacyBaggageEnabled)
|
|
981
985
|
this._setBoolean(opts, 'llmobs.agentlessEnabled', options.llmobs?.agentlessEnabled)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const BaseLLMObsPlugin = require('./base')
|
|
2
|
+
const { storage } = require('../../../../datadog-core')
|
|
3
|
+
const llmobsStore = storage('llmobs')
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
extractRequestParams,
|
|
7
|
+
extractTextAndResponseReason,
|
|
8
|
+
parseModelId
|
|
9
|
+
} = require('../../../../datadog-plugin-aws-sdk/src/services/bedrockruntime/utils')
|
|
10
|
+
|
|
11
|
+
const enabledOperations = ['invokeModel']
|
|
12
|
+
|
|
13
|
+
class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
14
|
+
constructor () {
|
|
15
|
+
super(...arguments)
|
|
16
|
+
|
|
17
|
+
this.addSub('apm:aws:request:complete:bedrockruntime', ({ response }) => {
|
|
18
|
+
const request = response.request
|
|
19
|
+
const operation = request.operation
|
|
20
|
+
// avoids instrumenting other non supported runtime operations
|
|
21
|
+
if (!enabledOperations.includes(operation)) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
const { modelProvider, modelName } = parseModelId(request.params.modelId)
|
|
25
|
+
|
|
26
|
+
// avoids instrumenting non llm type
|
|
27
|
+
if (modelName.includes('embed')) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
const span = storage.getStore()?.span
|
|
31
|
+
this.setLLMObsTags({ request, span, response, modelProvider, modelName })
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setLLMObsTags ({ request, span, response, modelProvider, modelName }) {
|
|
36
|
+
const parent = llmobsStore.getStore()?.span
|
|
37
|
+
this._tagger.registerLLMObsSpan(span, {
|
|
38
|
+
parent,
|
|
39
|
+
modelName: modelName.toLowerCase(),
|
|
40
|
+
modelProvider: modelProvider.toLowerCase(),
|
|
41
|
+
kind: 'llm',
|
|
42
|
+
name: 'bedrock-runtime.command'
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const requestParams = extractRequestParams(request.params, modelProvider)
|
|
46
|
+
const textAndResponseReason = extractTextAndResponseReason(response, modelProvider, modelName)
|
|
47
|
+
|
|
48
|
+
// add metadata tags
|
|
49
|
+
this._tagger.tagMetadata(span, {
|
|
50
|
+
temperature: parseFloat(requestParams.temperature) || 0.0,
|
|
51
|
+
max_tokens: parseInt(requestParams.maxTokens) || 0
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// add I/O tags
|
|
55
|
+
this._tagger.tagLLMIO(span, requestParams.prompt, textAndResponseReason.message)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = BedrockRuntimeLLMObsPlugin
|
|
@@ -158,6 +158,7 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
158
158
|
if (err) {
|
|
159
159
|
log.error('Known tests could not be fetched. %s', err.message)
|
|
160
160
|
this.libraryConfig.isEarlyFlakeDetectionEnabled = false
|
|
161
|
+
this.libraryConfig.isKnownTestsEnabled = false
|
|
161
162
|
}
|
|
162
163
|
onDone({ err, knownTests })
|
|
163
164
|
})
|
|
@@ -2,7 +2,6 @@ const log = require('../../log')
|
|
|
2
2
|
const tags = require('../../../../../ext/tags')
|
|
3
3
|
|
|
4
4
|
const RESOURCE_NAME = tags.RESOURCE_NAME
|
|
5
|
-
const HTTP_ROUTE = tags.HTTP_ROUTE
|
|
6
5
|
const SPAN_KIND = tags.SPAN_KIND
|
|
7
6
|
const SPAN_TYPE = tags.SPAN_TYPE
|
|
8
7
|
const HTTP_URL = tags.HTTP_URL
|
|
@@ -54,7 +53,6 @@ function createInferredProxySpan (headers, childOf, tracer, context) {
|
|
|
54
53
|
[SPAN_TYPE]: 'web',
|
|
55
54
|
[HTTP_METHOD]: proxyContext.method,
|
|
56
55
|
[HTTP_URL]: proxyContext.domainName + proxyContext.path,
|
|
57
|
-
[HTTP_ROUTE]: proxyContext.path,
|
|
58
56
|
stage: proxyContext.stage
|
|
59
57
|
}
|
|
60
58
|
}
|
|
@@ -59,6 +59,7 @@ const TEST_IS_NEW = 'test.is_new'
|
|
|
59
59
|
const TEST_IS_RETRY = 'test.is_retry'
|
|
60
60
|
const TEST_EARLY_FLAKE_ENABLED = 'test.early_flake.enabled'
|
|
61
61
|
const TEST_EARLY_FLAKE_ABORT_REASON = 'test.early_flake.abort_reason'
|
|
62
|
+
const TEST_RETRY_REASON = 'test.retry_reason'
|
|
62
63
|
|
|
63
64
|
const CI_APP_ORIGIN = 'ciapp-test'
|
|
64
65
|
|
|
@@ -145,6 +146,7 @@ module.exports = {
|
|
|
145
146
|
TEST_IS_RETRY,
|
|
146
147
|
TEST_EARLY_FLAKE_ENABLED,
|
|
147
148
|
TEST_EARLY_FLAKE_ABORT_REASON,
|
|
149
|
+
TEST_RETRY_REASON,
|
|
148
150
|
getTestEnvironmentMetadata,
|
|
149
151
|
getTestParametersString,
|
|
150
152
|
finishAllTraceSpans,
|