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.
Files changed (58) hide show
  1. package/package.json +4 -4
  2. package/packages/datadog-instrumentations/src/cucumber.js +61 -23
  3. package/packages/datadog-instrumentations/src/dd-trace-api.js +7 -0
  4. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  5. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  6. package/packages/datadog-instrumentations/src/jest.js +134 -48
  7. package/packages/datadog-instrumentations/src/mocha/main.js +20 -4
  8. package/packages/datadog-instrumentations/src/mocha/utils.js +89 -30
  9. package/packages/datadog-instrumentations/src/mocha/worker.js +3 -1
  10. package/packages/datadog-instrumentations/src/playwright.js +97 -17
  11. package/packages/datadog-instrumentations/src/router.js +1 -0
  12. package/packages/datadog-instrumentations/src/tedious.js +13 -10
  13. package/packages/datadog-instrumentations/src/vitest.js +77 -17
  14. package/packages/datadog-plugin-cucumber/src/index.js +24 -1
  15. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +69 -20
  16. package/packages/datadog-plugin-cypress/src/support.js +39 -10
  17. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +8 -186
  18. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +186 -0
  19. package/packages/datadog-plugin-google-cloud-vertexai/src/utils.js +19 -0
  20. package/packages/datadog-plugin-jest/src/index.js +38 -5
  21. package/packages/datadog-plugin-mocha/src/index.js +28 -5
  22. package/packages/datadog-plugin-playwright/src/index.js +22 -2
  23. package/packages/datadog-plugin-tedious/src/index.js +14 -9
  24. package/packages/datadog-plugin-vitest/src/index.js +46 -14
  25. package/packages/dd-trace/src/appsec/blocking.js +2 -0
  26. package/packages/dd-trace/src/appsec/graphql.js +3 -1
  27. package/packages/dd-trace/src/appsec/reporter.js +13 -8
  28. package/packages/dd-trace/src/appsec/sdk/track_event.js +7 -0
  29. package/packages/dd-trace/src/appsec/telemetry/common.js +6 -3
  30. package/packages/dd-trace/src/appsec/telemetry/index.js +28 -5
  31. package/packages/dd-trace/src/appsec/telemetry/user.js +9 -1
  32. package/packages/dd-trace/src/appsec/telemetry/waf.js +29 -9
  33. package/packages/dd-trace/src/appsec/waf/waf_manager.js +16 -7
  34. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -2
  35. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -1
  36. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
  37. package/packages/dd-trace/src/dogstatsd.js +94 -77
  38. package/packages/dd-trace/src/histogram.js +12 -23
  39. package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
  40. package/packages/dd-trace/src/llmobs/index.js +3 -0
  41. package/packages/dd-trace/src/llmobs/noop.js +3 -3
  42. package/packages/dd-trace/src/llmobs/plugins/base.js +1 -1
  43. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +2 -1
  44. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +196 -0
  45. package/packages/dd-trace/src/llmobs/sdk.js +2 -0
  46. package/packages/dd-trace/src/llmobs/span_processor.js +6 -0
  47. package/packages/dd-trace/src/llmobs/tagger.js +8 -2
  48. package/packages/dd-trace/src/llmobs/telemetry.js +108 -1
  49. package/packages/dd-trace/src/llmobs/writers/base.js +4 -0
  50. package/packages/dd-trace/src/llmobs/writers/spans/base.js +10 -1
  51. package/packages/dd-trace/src/plugin_manager.js +0 -3
  52. package/packages/dd-trace/src/plugins/ci_plugin.js +16 -26
  53. package/packages/dd-trace/src/plugins/database.js +4 -4
  54. package/packages/dd-trace/src/plugins/plugin.js +2 -0
  55. package/packages/dd-trace/src/plugins/util/test.js +62 -1
  56. package/packages/dd-trace/src/remote_config/manager.js +5 -0
  57. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +7 -6
  58. 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
- DD_CAPABILITIES_EARLY_FLAKE_DETECTION,
26
- DD_CAPABILITIES_AUTO_TEST_RETRIES
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 ?? false)
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 ?? false)
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
- [DD_CAPABILITIES_EARLY_FLAKE_DETECTION]: isEarlyFlakeDetectionEnabled ? 'true' : 'false',
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
- metricsQueue.set('_dd.appsec.waf.version', wafVersion)
92
+ function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}, success = false) {
93
+ if (success) {
94
+ metricsQueue.set('_dd.appsec.waf.version', wafVersion)
93
95
 
94
- metricsQueue.set('_dd.appsec.event_rules.loaded', diagnosticsRules.loaded?.length || 0)
95
- metricsQueue.set('_dd.appsec.event_rules.error_count', diagnosticsRules.failed?.length || 0)
96
- if (diagnosticsRules.failed?.length) {
97
- metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(diagnosticsRules.errors))
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 incrementWafInitMetric (wafVersion, rulesVersion) {
77
+ function updateRateLimitedMetric (req) {
78
78
  if (!enabled) return
79
79
 
80
- incrementWafInit(wafVersion, rulesVersion)
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
- const { blockTriggered, ruleTriggered, wafTimeout } = metrics
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 (ruleTriggered) {
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 (wafTimeout) {
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
- appsecMetrics.count('waf.init', versionsTags).inc()
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
- appsecMetrics.count('waf.updates', versionsTags).inc()
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
- this.ddwaf.update(newRules)
55
+ try {
56
+ this.ddwaf.update(newRules)
53
57
 
54
- if (this.ddwaf.diagnostics.ruleset_version) {
55
- this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
56
- }
58
+ if (this.ddwaf.diagnostics.ruleset_version) {
59
+ this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
60
+ }
57
61
 
58
- Reporter.reportWafUpdate(this.ddwafVersion, this.rulesVersion)
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
  })