dd-trace 5.43.0 → 5.45.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/package.json +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +61 -23
- package/packages/datadog-instrumentations/src/dd-trace-api.js +7 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +134 -48
- package/packages/datadog-instrumentations/src/mocha/main.js +20 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +89 -30
- package/packages/datadog-instrumentations/src/mocha/worker.js +3 -1
- package/packages/datadog-instrumentations/src/playwright.js +97 -17
- package/packages/datadog-instrumentations/src/router.js +1 -0
- package/packages/datadog-instrumentations/src/tedious.js +13 -10
- package/packages/datadog-instrumentations/src/vitest.js +77 -17
- package/packages/datadog-plugin-cucumber/src/index.js +24 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +69 -20
- package/packages/datadog-plugin-cypress/src/support.js +39 -10
- package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +8 -186
- package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +186 -0
- package/packages/datadog-plugin-google-cloud-vertexai/src/utils.js +19 -0
- package/packages/datadog-plugin-jest/src/index.js +38 -5
- package/packages/datadog-plugin-mocha/src/index.js +28 -5
- package/packages/datadog-plugin-playwright/src/index.js +22 -2
- package/packages/datadog-plugin-tedious/src/index.js +14 -9
- package/packages/datadog-plugin-vitest/src/index.js +46 -14
- package/packages/dd-trace/src/appsec/blocking.js +2 -0
- package/packages/dd-trace/src/appsec/graphql.js +3 -1
- package/packages/dd-trace/src/appsec/reporter.js +13 -8
- package/packages/dd-trace/src/appsec/sdk/track_event.js +7 -0
- package/packages/dd-trace/src/appsec/telemetry/common.js +6 -3
- package/packages/dd-trace/src/appsec/telemetry/index.js +28 -5
- package/packages/dd-trace/src/appsec/telemetry/user.js +9 -1
- package/packages/dd-trace/src/appsec/telemetry/waf.js +29 -9
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +16 -7
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -1
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
- package/packages/dd-trace/src/dogstatsd.js +94 -77
- package/packages/dd-trace/src/histogram.js +12 -23
- package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
- package/packages/dd-trace/src/llmobs/index.js +3 -0
- package/packages/dd-trace/src/llmobs/noop.js +3 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +2 -1
- package/packages/dd-trace/src/llmobs/plugins/vertexai.js +196 -0
- package/packages/dd-trace/src/llmobs/sdk.js +2 -0
- package/packages/dd-trace/src/llmobs/span_processor.js +6 -0
- package/packages/dd-trace/src/llmobs/tagger.js +8 -2
- package/packages/dd-trace/src/llmobs/telemetry.js +108 -1
- package/packages/dd-trace/src/llmobs/writers/base.js +4 -0
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +10 -1
- package/packages/dd-trace/src/plugin_manager.js +0 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +16 -26
- package/packages/dd-trace/src/plugins/database.js +4 -4
- package/packages/dd-trace/src/plugins/plugin.js +2 -0
- package/packages/dd-trace/src/plugins/util/test.js +62 -1
- package/packages/dd-trace/src/remote_config/manager.js +5 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +7 -6
- package/packages/dd-trace/src/telemetry/send-data.js +5 -1
|
@@ -22,8 +22,10 @@ const {
|
|
|
22
22
|
TEST_MANAGEMENT_ENABLED,
|
|
23
23
|
TEST_MANAGEMENT_IS_QUARANTINED,
|
|
24
24
|
TEST_MANAGEMENT_IS_DISABLED,
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX,
|
|
26
|
+
TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED,
|
|
27
|
+
TEST_HAS_FAILED_ALL_RETRIES,
|
|
28
|
+
getLibraryCapabilitiesTags
|
|
27
29
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
28
30
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
29
31
|
const {
|
|
@@ -53,18 +55,30 @@ class VitestPlugin extends CiPlugin {
|
|
|
53
55
|
onDone(!testsForThisTestSuite.includes(testName))
|
|
54
56
|
})
|
|
55
57
|
|
|
58
|
+
this.addSub('ci:vitest:test:is-attempt-to-fix', ({
|
|
59
|
+
testManagementTests,
|
|
60
|
+
testSuiteAbsolutePath,
|
|
61
|
+
testName,
|
|
62
|
+
onDone
|
|
63
|
+
}) => {
|
|
64
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
65
|
+
const { isAttemptToFix } = this.getTestProperties(testManagementTests, testSuite, testName)
|
|
66
|
+
|
|
67
|
+
onDone(isAttemptToFix ?? false)
|
|
68
|
+
})
|
|
69
|
+
|
|
56
70
|
this.addSub('ci:vitest:test:is-disabled', ({ testManagementTests, testSuiteAbsolutePath, testName, onDone }) => {
|
|
57
71
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
58
72
|
const { isDisabled } = this.getTestProperties(testManagementTests, testSuite, testName)
|
|
59
73
|
|
|
60
|
-
onDone(isDisabled
|
|
74
|
+
onDone(isDisabled)
|
|
61
75
|
})
|
|
62
76
|
|
|
63
77
|
this.addSub('ci:vitest:test:is-quarantined', ({ testManagementTests, testSuiteAbsolutePath, testName, onDone }) => {
|
|
64
78
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
65
79
|
const { isQuarantined } = this.getTestProperties(testManagementTests, testSuite, testName)
|
|
66
80
|
|
|
67
|
-
onDone(isQuarantined
|
|
81
|
+
onDone(isQuarantined)
|
|
68
82
|
})
|
|
69
83
|
|
|
70
84
|
this.addSub('ci:vitest:is-early-flake-detection-faulty', ({
|
|
@@ -85,9 +99,12 @@ class VitestPlugin extends CiPlugin {
|
|
|
85
99
|
testSuiteAbsolutePath,
|
|
86
100
|
isRetry,
|
|
87
101
|
isNew,
|
|
102
|
+
isAttemptToFix,
|
|
88
103
|
isQuarantined,
|
|
104
|
+
isDisabled,
|
|
89
105
|
mightHitProbe,
|
|
90
|
-
isRetryReasonEfd
|
|
106
|
+
isRetryReasonEfd,
|
|
107
|
+
isRetryReasonAttemptToFix
|
|
91
108
|
}) => {
|
|
92
109
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
93
110
|
const store = storage('legacy').getStore()
|
|
@@ -104,9 +121,18 @@ class VitestPlugin extends CiPlugin {
|
|
|
104
121
|
if (isRetryReasonEfd) {
|
|
105
122
|
extraTags[TEST_RETRY_REASON] = 'efd'
|
|
106
123
|
}
|
|
124
|
+
if (isAttemptToFix) {
|
|
125
|
+
extraTags[TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX] = 'true'
|
|
126
|
+
}
|
|
127
|
+
if (isRetryReasonAttemptToFix) {
|
|
128
|
+
extraTags[TEST_RETRY_REASON] = 'attempt_to_fix'
|
|
129
|
+
}
|
|
107
130
|
if (isQuarantined) {
|
|
108
131
|
extraTags[TEST_MANAGEMENT_IS_QUARANTINED] = 'true'
|
|
109
132
|
}
|
|
133
|
+
if (isDisabled) {
|
|
134
|
+
extraTags[TEST_MANAGEMENT_IS_DISABLED] = 'true'
|
|
135
|
+
}
|
|
110
136
|
|
|
111
137
|
const span = this.startTestSpan(
|
|
112
138
|
testName,
|
|
@@ -124,7 +150,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
124
150
|
}
|
|
125
151
|
})
|
|
126
152
|
|
|
127
|
-
this.addSub('ci:vitest:test:finish-time', ({ status, task }) => {
|
|
153
|
+
this.addSub('ci:vitest:test:finish-time', ({ status, task, attemptToFixPassed }) => {
|
|
128
154
|
const store = storage('legacy').getStore()
|
|
129
155
|
const span = store?.span
|
|
130
156
|
|
|
@@ -132,6 +158,11 @@ class VitestPlugin extends CiPlugin {
|
|
|
132
158
|
// this is because the test might fail at a `afterEach` hook
|
|
133
159
|
if (span) {
|
|
134
160
|
span.setTag(TEST_STATUS, status)
|
|
161
|
+
|
|
162
|
+
if (attemptToFixPassed) {
|
|
163
|
+
span.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'true')
|
|
164
|
+
}
|
|
165
|
+
|
|
135
166
|
this.taskToFinishTime.set(task, span._getTime())
|
|
136
167
|
}
|
|
137
168
|
})
|
|
@@ -150,7 +181,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
150
181
|
}
|
|
151
182
|
})
|
|
152
183
|
|
|
153
|
-
this.addSub('ci:vitest:test:error', ({ duration, error, shouldSetProbe, promises }) => {
|
|
184
|
+
this.addSub('ci:vitest:test:error', ({ duration, error, shouldSetProbe, promises, hasFailedAllRetries }) => {
|
|
154
185
|
const store = storage('legacy').getStore()
|
|
155
186
|
const span = store?.span
|
|
156
187
|
|
|
@@ -172,6 +203,9 @@ class VitestPlugin extends CiPlugin {
|
|
|
172
203
|
if (error) {
|
|
173
204
|
span.setTag('error', error)
|
|
174
205
|
}
|
|
206
|
+
if (hasFailedAllRetries) {
|
|
207
|
+
span.setTag(TEST_HAS_FAILED_ALL_RETRIES, 'true')
|
|
208
|
+
}
|
|
175
209
|
if (duration) {
|
|
176
210
|
span.finish(span._startTime + duration - MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION) // milliseconds
|
|
177
211
|
} else {
|
|
@@ -203,9 +237,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
203
237
|
|
|
204
238
|
this.addSub('ci:vitest:test-suite:start', ({
|
|
205
239
|
testSuiteAbsolutePath,
|
|
206
|
-
frameworkVersion
|
|
207
|
-
isFlakyTestRetriesEnabled,
|
|
208
|
-
isEarlyFlakeDetectionEnabled
|
|
240
|
+
frameworkVersion
|
|
209
241
|
}) => {
|
|
210
242
|
this.command = process.env.DD_CIVISIBILITY_TEST_COMMAND
|
|
211
243
|
this.frameworkVersion = frameworkVersion
|
|
@@ -223,10 +255,10 @@ class VitestPlugin extends CiPlugin {
|
|
|
223
255
|
}
|
|
224
256
|
}
|
|
225
257
|
if (this.tracer._exporter.addMetadataTags) {
|
|
258
|
+
const libraryCapabilitiesTags = getLibraryCapabilitiesTags(this.constructor.id)
|
|
226
259
|
metadataTags.test = {
|
|
227
260
|
...metadataTags.test,
|
|
228
|
-
|
|
229
|
-
[DD_CAPABILITIES_AUTO_TEST_RETRIES]: isFlakyTestRetriesEnabled ? 'true' : 'false'
|
|
261
|
+
...libraryCapabilitiesTags
|
|
230
262
|
}
|
|
231
263
|
this.tracer._exporter.addMetadataTags(metadataTags)
|
|
232
264
|
}
|
|
@@ -327,10 +359,10 @@ class VitestPlugin extends CiPlugin {
|
|
|
327
359
|
}
|
|
328
360
|
|
|
329
361
|
getTestProperties (testManagementTests, testSuite, testName) {
|
|
330
|
-
const { disabled: isDisabled, quarantined: isQuarantined } =
|
|
362
|
+
const { attempt_to_fix: isAttemptToFix, disabled: isDisabled, quarantined: isQuarantined } =
|
|
331
363
|
testManagementTests?.vitest?.suites?.[testSuite]?.tests?.[testName]?.properties || {}
|
|
332
364
|
|
|
333
|
-
return { isDisabled, isQuarantined }
|
|
365
|
+
return { isAttemptToFix, isDisabled, isQuarantined }
|
|
334
366
|
}
|
|
335
367
|
}
|
|
336
368
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const log = require('../log')
|
|
4
4
|
const blockedTemplates = require('./blocked_templates')
|
|
5
|
+
const { updateBlockFailureMetric } = require('./telemetry')
|
|
5
6
|
|
|
6
7
|
const detectedSpecificEndpoints = {}
|
|
7
8
|
|
|
@@ -128,6 +129,7 @@ function block (req, res, rootSpan, abortController, actionParameters = defaultB
|
|
|
128
129
|
rootSpan?.setTag('_dd.appsec.block.failed', 1)
|
|
129
130
|
log.error('[ASM] Blocking error', err)
|
|
130
131
|
|
|
132
|
+
updateBlockFailureMetric(req)
|
|
131
133
|
return false
|
|
132
134
|
}
|
|
133
135
|
}
|
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
apolloChannel,
|
|
18
18
|
apolloServerCoreChannel
|
|
19
19
|
} = require('./channels')
|
|
20
|
+
const { updateBlockFailureMetric } = require('./telemetry')
|
|
20
21
|
|
|
21
22
|
const graphqlRequestData = new WeakMap()
|
|
22
23
|
|
|
@@ -106,8 +107,9 @@ function beforeWriteApolloGraphqlResponse ({ abortController, abortData }) {
|
|
|
106
107
|
abortController?.abort()
|
|
107
108
|
} catch (err) {
|
|
108
109
|
rootSpan.setTag('_dd.appsec.block.failed', 1)
|
|
109
|
-
|
|
110
110
|
log.error('[ASM] Blocking error', err)
|
|
111
|
+
|
|
112
|
+
updateBlockFailureMetric(req)
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
|
|
@@ -10,7 +10,8 @@ const {
|
|
|
10
10
|
updateRaspRequestsMetricTags,
|
|
11
11
|
incrementWafUpdatesMetric,
|
|
12
12
|
incrementWafRequestsMetric,
|
|
13
|
-
getRequestMetrics
|
|
13
|
+
getRequestMetrics,
|
|
14
|
+
updateRateLimitedMetric
|
|
14
15
|
} = require('./telemetry')
|
|
15
16
|
const zlib = require('zlib')
|
|
16
17
|
const { keepTrace } = require('../priority_sampler')
|
|
@@ -88,16 +89,18 @@ function formatHeaderName (name) {
|
|
|
88
89
|
.toLowerCase()
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}) {
|
|
92
|
-
|
|
92
|
+
function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}, success = false) {
|
|
93
|
+
if (success) {
|
|
94
|
+
metricsQueue.set('_dd.appsec.waf.version', wafVersion)
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
metricsQueue.set('_dd.appsec.event_rules.loaded', diagnosticsRules.loaded?.length || 0)
|
|
97
|
+
metricsQueue.set('_dd.appsec.event_rules.error_count', diagnosticsRules.failed?.length || 0)
|
|
98
|
+
if (diagnosticsRules.failed?.length) {
|
|
99
|
+
metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(diagnosticsRules.errors))
|
|
100
|
+
}
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
incrementWafInitMetric(wafVersion, rulesVersion)
|
|
103
|
+
incrementWafInitMetric(wafVersion, rulesVersion, success)
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
function reportMetrics (metrics, raspRule) {
|
|
@@ -147,6 +150,8 @@ function reportAttack (attackData) {
|
|
|
147
150
|
|
|
148
151
|
if (limiter.isAllowed()) {
|
|
149
152
|
keepTrace(rootSpan, ASM)
|
|
153
|
+
} else {
|
|
154
|
+
updateRateLimitedMetric(req)
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
// TODO: maybe add this to format.js later (to take decision as late as possible)
|
|
@@ -7,6 +7,7 @@ const waf = require('../waf')
|
|
|
7
7
|
const { keepTrace } = require('../../priority_sampler')
|
|
8
8
|
const addresses = require('../addresses')
|
|
9
9
|
const { ASM } = require('../../standalone/product')
|
|
10
|
+
const { incrementSdkEventMetric } = require('../telemetry')
|
|
10
11
|
|
|
11
12
|
function trackUserLoginSuccessEvent (tracer, user, metadata) {
|
|
12
13
|
// TODO: better user check here and in _setUser() ?
|
|
@@ -15,6 +16,8 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) {
|
|
|
15
16
|
return
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
incrementSdkEventMetric('login_success')
|
|
20
|
+
|
|
18
21
|
const rootSpan = getRootSpan(tracer)
|
|
19
22
|
if (!rootSpan) {
|
|
20
23
|
log.warn('[ASM] Root span not available in trackUserLoginSuccessEvent')
|
|
@@ -48,6 +51,8 @@ function trackUserLoginFailureEvent (tracer, userId, exists, metadata) {
|
|
|
48
51
|
trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan(tracer))
|
|
49
52
|
|
|
50
53
|
runWaf('users.login.failure', { login: userId })
|
|
54
|
+
|
|
55
|
+
incrementSdkEventMetric('login_failure')
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
function trackCustomEvent (tracer, eventName, metadata) {
|
|
@@ -57,6 +62,8 @@ function trackCustomEvent (tracer, eventName, metadata) {
|
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan(tracer))
|
|
65
|
+
|
|
66
|
+
incrementSdkEventMetric('custom')
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
function trackEvent (eventName, fields, sdkMethodName, rootSpan) {
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
const DD_TELEMETRY_REQUEST_METRICS = Symbol('_dd.appsec.telemetry.request.metrics')
|
|
4
4
|
|
|
5
5
|
const tags = {
|
|
6
|
+
BLOCK_FAILURE: 'block_failure',
|
|
7
|
+
EVENT_RULES_VERSION: 'event_rules_version',
|
|
8
|
+
INPUT_TRUNCATED: 'input_truncated',
|
|
9
|
+
RATE_LIMITED: 'rate_limited',
|
|
6
10
|
REQUEST_BLOCKED: 'request_blocked',
|
|
7
11
|
RULE_TRIGGERED: 'rule_triggered',
|
|
12
|
+
WAF_ERROR: 'waf_error',
|
|
8
13
|
WAF_TIMEOUT: 'waf_timeout',
|
|
9
|
-
WAF_VERSION: 'waf_version'
|
|
10
|
-
EVENT_RULES_VERSION: 'event_rules_version',
|
|
11
|
-
INPUT_TRUNCATED: 'input_truncated'
|
|
14
|
+
WAF_VERSION: 'waf_version'
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
function getVersionsTags (wafVersion, rulesVersion) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { DD_TELEMETRY_REQUEST_METRICS } = require('./common')
|
|
4
4
|
const { addRaspRequestMetrics, trackRaspMetrics } = require('./rasp')
|
|
5
|
-
const { incrementMissingUserId, incrementMissingUserLogin } = require('./user')
|
|
5
|
+
const { incrementMissingUserId, incrementMissingUserLogin, incrementSdkEvent } = require('./user')
|
|
6
6
|
const {
|
|
7
7
|
addWafRequestMetrics,
|
|
8
8
|
trackWafMetrics,
|
|
@@ -74,16 +74,30 @@ function updateWafRequestsMetricTags (metrics, req) {
|
|
|
74
74
|
return trackWafMetrics(store, metrics)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
function
|
|
77
|
+
function updateRateLimitedMetric (req) {
|
|
78
78
|
if (!enabled) return
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
const store = getStore(req)
|
|
81
|
+
trackWafMetrics(store, { rateLimited: true })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function updateBlockFailureMetric (req) {
|
|
85
|
+
if (!enabled) return
|
|
86
|
+
|
|
87
|
+
const store = getStore(req)
|
|
88
|
+
trackWafMetrics(store, { blockFailed: true })
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function incrementWafInitMetric (wafVersion, rulesVersion, success) {
|
|
92
|
+
if (!enabled) return
|
|
93
|
+
|
|
94
|
+
incrementWafInit(wafVersion, rulesVersion, success)
|
|
81
95
|
}
|
|
82
96
|
|
|
83
|
-
function incrementWafUpdatesMetric (wafVersion, rulesVersion) {
|
|
97
|
+
function incrementWafUpdatesMetric (wafVersion, rulesVersion, success) {
|
|
84
98
|
if (!enabled) return
|
|
85
99
|
|
|
86
|
-
incrementWafUpdates(wafVersion, rulesVersion)
|
|
100
|
+
incrementWafUpdates(wafVersion, rulesVersion, success)
|
|
87
101
|
}
|
|
88
102
|
|
|
89
103
|
function incrementWafRequestsMetric (req) {
|
|
@@ -107,6 +121,12 @@ function incrementMissingUserIdMetric (framework, eventType) {
|
|
|
107
121
|
incrementMissingUserId(framework, eventType)
|
|
108
122
|
}
|
|
109
123
|
|
|
124
|
+
function incrementSdkEventMetric (framework, eventType) {
|
|
125
|
+
if (!enabled) return
|
|
126
|
+
|
|
127
|
+
incrementSdkEvent(framework, eventType)
|
|
128
|
+
}
|
|
129
|
+
|
|
110
130
|
function getRequestMetrics (req) {
|
|
111
131
|
if (req) {
|
|
112
132
|
const store = getStore(req)
|
|
@@ -119,12 +139,15 @@ module.exports = {
|
|
|
119
139
|
disable,
|
|
120
140
|
|
|
121
141
|
updateWafRequestsMetricTags,
|
|
142
|
+
updateRateLimitedMetric,
|
|
143
|
+
updateBlockFailureMetric,
|
|
122
144
|
updateRaspRequestsMetricTags,
|
|
123
145
|
incrementWafInitMetric,
|
|
124
146
|
incrementWafUpdatesMetric,
|
|
125
147
|
incrementWafRequestsMetric,
|
|
126
148
|
incrementMissingUserLoginMetric,
|
|
127
149
|
incrementMissingUserIdMetric,
|
|
150
|
+
incrementSdkEventMetric,
|
|
128
151
|
|
|
129
152
|
getRequestMetrics
|
|
130
153
|
}
|
|
@@ -18,7 +18,15 @@ function incrementMissingUserId (framework, eventType) {
|
|
|
18
18
|
}).inc()
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function incrementSdkEvent (eventType) {
|
|
22
|
+
appsecMetrics.count('sdk.event', {
|
|
23
|
+
event_type: eventType,
|
|
24
|
+
sdk_version: 'v1'
|
|
25
|
+
}).inc()
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
module.exports = {
|
|
22
29
|
incrementMissingUserLogin,
|
|
23
|
-
incrementMissingUserId
|
|
30
|
+
incrementMissingUserId,
|
|
31
|
+
incrementSdkEvent
|
|
24
32
|
}
|
|
@@ -50,17 +50,28 @@ function trackWafMetrics (store, metrics) {
|
|
|
50
50
|
|
|
51
51
|
const metricTags = getOrCreateMetricTags(store, versionsTags)
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
if (metrics.blockFailed) {
|
|
54
|
+
metricTags[tags.BLOCK_FAILURE] = true
|
|
55
|
+
}
|
|
54
56
|
|
|
55
|
-
if (blockTriggered) {
|
|
57
|
+
if (metrics.blockTriggered) {
|
|
56
58
|
metricTags[tags.REQUEST_BLOCKED] = true
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
if (
|
|
61
|
+
if (metrics.rateLimited) {
|
|
62
|
+
metricTags[tags.RATE_LIMITED] = true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (metrics.ruleTriggered) {
|
|
60
66
|
metricTags[tags.RULE_TRIGGERED] = true
|
|
61
67
|
}
|
|
62
68
|
|
|
63
|
-
if (
|
|
69
|
+
if (metrics.errorCode) {
|
|
70
|
+
metricTags[tags.WAF_ERROR] = true
|
|
71
|
+
appsecMetrics.count('waf.error', { ...versionsTags, waf_error: metrics.errorCode }).inc()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (metrics.wafTimeout) {
|
|
64
75
|
metricTags[tags.WAF_TIMEOUT] = true
|
|
65
76
|
}
|
|
66
77
|
|
|
@@ -78,10 +89,13 @@ function getOrCreateMetricTags (store, versionsTags) {
|
|
|
78
89
|
|
|
79
90
|
if (!metricTags) {
|
|
80
91
|
metricTags = {
|
|
92
|
+
[tags.BLOCK_FAILURE]: false,
|
|
93
|
+
[tags.INPUT_TRUNCATED]: false,
|
|
94
|
+
[tags.RATE_LIMITED]: false,
|
|
81
95
|
[tags.REQUEST_BLOCKED]: false,
|
|
82
96
|
[tags.RULE_TRIGGERED]: false,
|
|
97
|
+
[tags.WAF_ERROR]: false,
|
|
83
98
|
[tags.WAF_TIMEOUT]: false,
|
|
84
|
-
[tags.INPUT_TRUNCATED]: false,
|
|
85
99
|
|
|
86
100
|
...versionsTags
|
|
87
101
|
}
|
|
@@ -91,16 +105,22 @@ function getOrCreateMetricTags (store, versionsTags) {
|
|
|
91
105
|
return metricTags
|
|
92
106
|
}
|
|
93
107
|
|
|
94
|
-
function incrementWafInit (wafVersion, rulesVersion) {
|
|
108
|
+
function incrementWafInit (wafVersion, rulesVersion, success) {
|
|
95
109
|
const versionsTags = getVersionsTags(wafVersion, rulesVersion)
|
|
110
|
+
appsecMetrics.count('waf.init', { ...versionsTags, success }).inc()
|
|
96
111
|
|
|
97
|
-
|
|
112
|
+
if (!success) {
|
|
113
|
+
appsecMetrics.count('waf.config_errors', versionsTags).inc()
|
|
114
|
+
}
|
|
98
115
|
}
|
|
99
116
|
|
|
100
|
-
function incrementWafUpdates (wafVersion, rulesVersion) {
|
|
117
|
+
function incrementWafUpdates (wafVersion, rulesVersion, success) {
|
|
101
118
|
const versionsTags = getVersionsTags(wafVersion, rulesVersion)
|
|
119
|
+
appsecMetrics.count('waf.updates', { ...versionsTags, success }).inc()
|
|
102
120
|
|
|
103
|
-
|
|
121
|
+
if (!success) {
|
|
122
|
+
appsecMetrics.count('waf.config_errors', versionsTags).inc()
|
|
123
|
+
}
|
|
104
124
|
}
|
|
105
125
|
|
|
106
126
|
function incrementWafRequests (store) {
|
|
@@ -11,20 +11,23 @@ class WAFManager {
|
|
|
11
11
|
this.config = config
|
|
12
12
|
this.wafTimeout = config.wafTimeout
|
|
13
13
|
this.ddwaf = this._loadDDWAF(rules)
|
|
14
|
-
this.ddwafVersion = this.ddwaf.constructor.version()
|
|
15
14
|
this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
|
|
16
15
|
|
|
17
|
-
Reporter.reportWafInit(this.ddwafVersion, this.rulesVersion, this.ddwaf.diagnostics.rules)
|
|
16
|
+
Reporter.reportWafInit(this.ddwafVersion, this.rulesVersion, this.ddwaf.diagnostics.rules, true)
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
_loadDDWAF (rules) {
|
|
21
20
|
try {
|
|
22
21
|
// require in `try/catch` because this can throw at require time
|
|
23
22
|
const { DDWAF } = require('@datadog/native-appsec')
|
|
23
|
+
this.ddwafVersion = DDWAF.version()
|
|
24
24
|
|
|
25
25
|
const { obfuscatorKeyRegex, obfuscatorValueRegex } = this.config
|
|
26
26
|
return new DDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex })
|
|
27
27
|
} catch (err) {
|
|
28
|
+
this.ddwafVersion = this.ddwafVersion || 'unknown'
|
|
29
|
+
Reporter.reportWafInit(this.ddwafVersion, 'unknown')
|
|
30
|
+
|
|
28
31
|
log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.')
|
|
29
32
|
|
|
30
33
|
throw err
|
|
@@ -49,13 +52,19 @@ class WAFManager {
|
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
update (newRules) {
|
|
52
|
-
|
|
55
|
+
try {
|
|
56
|
+
this.ddwaf.update(newRules)
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
if (this.ddwaf.diagnostics.ruleset_version) {
|
|
59
|
+
this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
|
|
60
|
+
}
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
Reporter.reportWafUpdate(this.ddwafVersion, this.rulesVersion, true)
|
|
63
|
+
} catch (error) {
|
|
64
|
+
Reporter.reportWafUpdate(this.ddwafVersion, 'unknown', false)
|
|
65
|
+
|
|
66
|
+
throw error
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
69
|
|
|
61
70
|
destroy () {
|
|
@@ -215,7 +215,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
215
215
|
isFlakyTestRetriesEnabled,
|
|
216
216
|
isDiEnabled,
|
|
217
217
|
isKnownTestsEnabled,
|
|
218
|
-
isTestManagementEnabled
|
|
218
|
+
isTestManagementEnabled,
|
|
219
|
+
testManagementAttemptToFixRetries
|
|
219
220
|
} = remoteConfiguration
|
|
220
221
|
return {
|
|
221
222
|
isCodeCoverageEnabled,
|
|
@@ -229,7 +230,9 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
229
230
|
flakyTestRetriesCount: this._config.flakyTestRetriesCount,
|
|
230
231
|
isDiEnabled: isDiEnabled && this._config.isTestDynamicInstrumentationEnabled,
|
|
231
232
|
isKnownTestsEnabled,
|
|
232
|
-
isTestManagementEnabled: isTestManagementEnabled && this._config.isTestManagementEnabled
|
|
233
|
+
isTestManagementEnabled: isTestManagementEnabled && this._config.isTestManagementEnabled,
|
|
234
|
+
testManagementAttemptToFixRetries:
|
|
235
|
+
testManagementAttemptToFixRetries ?? this._config.testManagementAttemptToFixRetries
|
|
233
236
|
}
|
|
234
237
|
}
|
|
235
238
|
|
|
@@ -113,7 +113,9 @@ function getLibraryConfiguration ({
|
|
|
113
113
|
isFlakyTestRetriesEnabled,
|
|
114
114
|
isDiEnabled: isDiEnabled && isFlakyTestRetriesEnabled,
|
|
115
115
|
isKnownTestsEnabled,
|
|
116
|
-
isTestManagementEnabled: (testManagementConfig?.enabled ?? false)
|
|
116
|
+
isTestManagementEnabled: (testManagementConfig?.enabled ?? false),
|
|
117
|
+
testManagementAttemptToFixRetries:
|
|
118
|
+
testManagementConfig?.attempt_to_fix_retries
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
log.debug(() => `Remote settings: ${JSON.stringify(settings)}`)
|
|
@@ -6,7 +6,8 @@ function getTestManagementTests ({
|
|
|
6
6
|
isEvpProxy,
|
|
7
7
|
evpProxyPrefix,
|
|
8
8
|
isGzipCompatible,
|
|
9
|
-
repositoryUrl
|
|
9
|
+
repositoryUrl,
|
|
10
|
+
commitMessage
|
|
10
11
|
}, done) {
|
|
11
12
|
const options = {
|
|
12
13
|
path: '/api/v2/test/libraries/test-management/tests',
|
|
@@ -39,7 +40,8 @@ function getTestManagementTests ({
|
|
|
39
40
|
id: id().toString(10),
|
|
40
41
|
type: 'ci_app_libraries_tests_request',
|
|
41
42
|
attributes: {
|
|
42
|
-
repository_url: repositoryUrl
|
|
43
|
+
repository_url: repositoryUrl,
|
|
44
|
+
commit_message: commitMessage
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
})
|