dd-trace 5.73.0 → 5.75.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/LICENSE-3rdparty.csv +2 -0
- package/index.d.ts +39 -7
- package/loader-hook.mjs +52 -1
- package/package.json +8 -16
- package/packages/datadog-core/src/utils/src/set.js +5 -1
- package/packages/datadog-esbuild/index.js +105 -36
- package/packages/datadog-esbuild/src/utils.js +198 -0
- package/packages/datadog-instrumentations/src/cookie-parser.js +0 -2
- package/packages/datadog-instrumentations/src/cucumber.js +2 -2
- package/packages/datadog-instrumentations/src/express.js +82 -0
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +238 -0
- package/packages/datadog-instrumentations/src/jest.js +2 -1
- package/packages/datadog-instrumentations/src/mariadb.js +9 -7
- package/packages/datadog-instrumentations/src/playwright.js +226 -93
- package/packages/datadog-instrumentations/src/router.js +63 -6
- package/packages/datadog-instrumentations/src/vitest.js +44 -12
- package/packages/datadog-instrumentations/src/ws.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +0 -1
- package/packages/datadog-plugin-express/src/code_origin.js +2 -0
- package/packages/datadog-plugin-playwright/src/index.js +74 -31
- package/packages/datadog-plugin-ws/src/close.js +1 -1
- package/packages/datadog-shimmer/src/shimmer.js +2 -0
- package/packages/dd-trace/src/aiguard/sdk.js +25 -3
- package/packages/dd-trace/src/aiguard/tags.js +4 -1
- package/packages/dd-trace/src/config-helper.js +4 -1
- package/packages/dd-trace/src/config.js +599 -592
- package/packages/dd-trace/src/config_defaults.js +14 -12
- package/packages/dd-trace/src/plugins/util/ci.js +3 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +16 -1
- package/packages/dd-trace/src/proxy.js +1 -1
- package/packages/dd-trace/src/supported-configurations.json +1 -0
- package/packages/dd-trace/src/telemetry/endpoints.js +27 -1
- package/packages/dd-trace/src/telemetry/index.js +16 -13
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +5 -3
- package/register.js +1 -11
- package/scripts/preinstall.js +3 -1
- package/version.js +2 -1
|
@@ -153,6 +153,10 @@ function isCliApiPackage (vitestPackage) {
|
|
|
153
153
|
return vitestPackage.s?.name === 'startVitest'
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
function isTestPackage (testPackage) {
|
|
157
|
+
return testPackage.V?.name === 'VitestTestRunner'
|
|
158
|
+
}
|
|
159
|
+
|
|
156
160
|
function getSessionStatus (state) {
|
|
157
161
|
if (state.getCountOfFailedTests() > 0) {
|
|
158
162
|
return 'fail'
|
|
@@ -240,7 +244,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
240
244
|
if (isFlakyTestRetriesEnabled && !this.ctx.config.retry && flakyTestRetriesCount > 0) {
|
|
241
245
|
this.ctx.config.retry = flakyTestRetriesCount
|
|
242
246
|
try {
|
|
243
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
247
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
248
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
249
|
+
: this.ctx.getRootProject()
|
|
244
250
|
workspaceProject._provided._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
245
251
|
} catch {
|
|
246
252
|
log.warn('Could not send library configuration to workers.')
|
|
@@ -272,7 +278,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
272
278
|
// TODO: use this to pass session and module IDs to the worker, instead of polluting process.env
|
|
273
279
|
// Note: setting this.ctx.config.provide directly does not work because it's cached
|
|
274
280
|
try {
|
|
275
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
281
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
282
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
283
|
+
: this.ctx.getRootProject()
|
|
276
284
|
workspaceProject._provided._ddIsKnownTestsEnabled = isKnownTestsEnabled
|
|
277
285
|
workspaceProject._provided._ddKnownTests = knownTests
|
|
278
286
|
workspaceProject._provided._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
@@ -290,7 +298,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
290
298
|
|
|
291
299
|
if (isDiEnabled) {
|
|
292
300
|
try {
|
|
293
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
301
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
302
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
303
|
+
: this.ctx.getRootProject()
|
|
294
304
|
workspaceProject._provided._ddIsDiEnabled = isDiEnabled
|
|
295
305
|
} catch {
|
|
296
306
|
log.warn('Could not send Dynamic Instrumentation configuration to workers.')
|
|
@@ -305,7 +315,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
305
315
|
} else {
|
|
306
316
|
const testManagementTests = receivedTestManagementTests
|
|
307
317
|
try {
|
|
308
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
318
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
319
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
320
|
+
: this.ctx.getRootProject()
|
|
309
321
|
workspaceProject._provided._ddIsTestManagementTestsEnabled = isTestManagementTestsEnabled
|
|
310
322
|
workspaceProject._provided._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
|
|
311
323
|
workspaceProject._provided._ddTestManagementTests = testManagementTests
|
|
@@ -321,7 +333,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
321
333
|
log.error('Could not get modified tests.')
|
|
322
334
|
} else {
|
|
323
335
|
try {
|
|
324
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
336
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
337
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
338
|
+
: this.ctx.getRootProject()
|
|
325
339
|
workspaceProject._provided._ddIsImpactedTestsEnabled = isImpactedTestsEnabled
|
|
326
340
|
workspaceProject._provided._ddModifiedFiles = modifiedFiles
|
|
327
341
|
} catch {
|
|
@@ -443,13 +457,7 @@ function getStartVitestWrapper (cliApiPackage, frameworkVersion) {
|
|
|
443
457
|
return cliApiPackage
|
|
444
458
|
}
|
|
445
459
|
|
|
446
|
-
|
|
447
|
-
name: 'vitest',
|
|
448
|
-
versions: ['>=1.6.0'],
|
|
449
|
-
file: 'dist/runners.js'
|
|
450
|
-
}, (vitestPackage) => {
|
|
451
|
-
const { VitestTestRunner } = vitestPackage
|
|
452
|
-
|
|
460
|
+
function wrapVitestTestRunner (VitestTestRunner) {
|
|
453
461
|
// `onBeforeRunTask` is run before any repetition or attempt is run
|
|
454
462
|
// `onBeforeRunTask` is an async function
|
|
455
463
|
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeRunTask', onBeforeRunTask => function (task) {
|
|
@@ -744,6 +752,30 @@ addHook({
|
|
|
744
752
|
|
|
745
753
|
return result
|
|
746
754
|
})
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
addHook({
|
|
758
|
+
name: 'vitest',
|
|
759
|
+
versions: ['>=4.0.0'],
|
|
760
|
+
filePattern: 'dist/chunks/test.*'
|
|
761
|
+
}, (testPackage) => {
|
|
762
|
+
if (!isTestPackage(testPackage)) {
|
|
763
|
+
return testPackage
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
wrapVitestTestRunner(testPackage.V)
|
|
767
|
+
|
|
768
|
+
return testPackage
|
|
769
|
+
})
|
|
770
|
+
|
|
771
|
+
addHook({
|
|
772
|
+
name: 'vitest',
|
|
773
|
+
versions: ['>=1.6.0 <4.0.0'],
|
|
774
|
+
file: 'dist/runners.js'
|
|
775
|
+
}, (vitestPackage) => {
|
|
776
|
+
const { VitestTestRunner } = vitestPackage
|
|
777
|
+
|
|
778
|
+
wrapVitestTestRunner(VitestTestRunner)
|
|
747
779
|
|
|
748
780
|
return vitestPackage
|
|
749
781
|
})
|
|
@@ -41,7 +41,7 @@ function wrapSend (send) {
|
|
|
41
41
|
|
|
42
42
|
const [data, options, cb] = arguments
|
|
43
43
|
|
|
44
|
-
const ctx = { data, socket: this._sender
|
|
44
|
+
const ctx = { data, socket: this._sender?._socket }
|
|
45
45
|
|
|
46
46
|
return typeof cb === 'function'
|
|
47
47
|
? producerCh.traceCallback(send, undefined, ctx, this, data, options, cb)
|
|
@@ -70,7 +70,7 @@ function createWrappedHandler (handler) {
|
|
|
70
70
|
return function wrappedMessageHandler (data, binary) {
|
|
71
71
|
const byteLength = dataLength(data)
|
|
72
72
|
|
|
73
|
-
const ctx = { data, binary, socket: this._sender
|
|
73
|
+
const ctx = { data, binary, socket: this._sender?._socket, byteLength }
|
|
74
74
|
|
|
75
75
|
return receiverCh.traceSync(handler, ctx, this, data, binary)
|
|
76
76
|
}
|
|
@@ -93,7 +93,7 @@ function wrapClose (close) {
|
|
|
93
93
|
// if both are true then the self is sending the close event
|
|
94
94
|
const isPeerClose = this._closeFrameReceived === true && this._closeFrameSent === false
|
|
95
95
|
|
|
96
|
-
const ctx = { code, data, socket: this._sender
|
|
96
|
+
const ctx = { code, data, socket: this._sender?._socket, isPeerClose }
|
|
97
97
|
|
|
98
98
|
return closeCh.traceSync(close, ctx, this, ...arguments)
|
|
99
99
|
}
|
|
@@ -19,6 +19,7 @@ class ExpressCodeOriginForSpansPlugin extends Plugin {
|
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
this.addSub('apm:express:route:added', ({ topOfStackFunc, layer }) => {
|
|
22
|
+
if (!layer) return
|
|
22
23
|
if (layerTags.has(layer)) return
|
|
23
24
|
layerTags.set(layer, entryTags(topOfStackFunc))
|
|
24
25
|
})
|
|
@@ -30,6 +31,7 @@ class ExpressCodeOriginForSpansPlugin extends Plugin {
|
|
|
30
31
|
})
|
|
31
32
|
|
|
32
33
|
this.addSub('apm:router:route:added', ({ topOfStackFunc, layer }) => {
|
|
34
|
+
if (!layer) return
|
|
33
35
|
if (layerTags.has(layer)) return
|
|
34
36
|
layerTags.set(layer, entryTags(topOfStackFunc))
|
|
35
37
|
})
|
|
@@ -47,6 +47,7 @@ const {
|
|
|
47
47
|
TELEMETRY_EVENT_FINISHED
|
|
48
48
|
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
49
49
|
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
|
|
50
|
+
const log = require('../../dd-trace/src/log')
|
|
50
51
|
|
|
51
52
|
class PlaywrightPlugin extends CiPlugin {
|
|
52
53
|
static id = 'playwright'
|
|
@@ -174,7 +175,10 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
174
175
|
}) => {
|
|
175
176
|
const store = storage('legacy').getStore()
|
|
176
177
|
const span = store && store.span
|
|
177
|
-
if (!span)
|
|
178
|
+
if (!span) {
|
|
179
|
+
log.error('ci:playwright:test:page-goto: test span not found')
|
|
180
|
+
return
|
|
181
|
+
}
|
|
178
182
|
|
|
179
183
|
if (isRumActive) {
|
|
180
184
|
span.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
@@ -198,36 +202,6 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
198
202
|
}
|
|
199
203
|
})
|
|
200
204
|
|
|
201
|
-
this.addBind('ci:playwright:test:start', (ctx) => {
|
|
202
|
-
const {
|
|
203
|
-
testName,
|
|
204
|
-
testSuiteAbsolutePath,
|
|
205
|
-
testSourceLine,
|
|
206
|
-
browserName,
|
|
207
|
-
isDisabled
|
|
208
|
-
} = ctx
|
|
209
|
-
const store = storage('legacy').getStore()
|
|
210
|
-
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
|
|
211
|
-
const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
212
|
-
const span = this.startTestSpan(
|
|
213
|
-
testName,
|
|
214
|
-
testSuiteAbsolutePath,
|
|
215
|
-
testSuite,
|
|
216
|
-
testSourceFile,
|
|
217
|
-
testSourceLine,
|
|
218
|
-
browserName
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
if (isDisabled) {
|
|
222
|
-
span.setTag(TEST_MANAGEMENT_IS_DISABLED, 'true')
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
ctx.parentStore = store
|
|
226
|
-
ctx.currentStore = { ...store, span }
|
|
227
|
-
|
|
228
|
-
return ctx.currentStore
|
|
229
|
-
})
|
|
230
|
-
|
|
231
205
|
this.addSub('ci:playwright:worker:report', (serializedTraces) => {
|
|
232
206
|
const traces = JSON.parse(serializedTraces)
|
|
233
207
|
const formattedTraces = []
|
|
@@ -277,6 +251,36 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
277
251
|
})
|
|
278
252
|
})
|
|
279
253
|
|
|
254
|
+
this.addBind('ci:playwright:test:start', (ctx) => {
|
|
255
|
+
const {
|
|
256
|
+
testName,
|
|
257
|
+
testSuiteAbsolutePath,
|
|
258
|
+
testSourceLine,
|
|
259
|
+
browserName,
|
|
260
|
+
isDisabled
|
|
261
|
+
} = ctx
|
|
262
|
+
const store = storage('legacy').getStore()
|
|
263
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
|
|
264
|
+
const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
265
|
+
const span = this.startTestSpan(
|
|
266
|
+
testName,
|
|
267
|
+
testSuiteAbsolutePath,
|
|
268
|
+
testSuite,
|
|
269
|
+
testSourceFile,
|
|
270
|
+
testSourceLine,
|
|
271
|
+
browserName
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
if (isDisabled) {
|
|
275
|
+
span.setTag(TEST_MANAGEMENT_IS_DISABLED, 'true')
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
ctx.parentStore = store
|
|
279
|
+
ctx.currentStore = { ...store, span }
|
|
280
|
+
|
|
281
|
+
return ctx.currentStore
|
|
282
|
+
})
|
|
283
|
+
|
|
280
284
|
this.addSub('ci:playwright:test:finish', ({
|
|
281
285
|
span,
|
|
282
286
|
testStatus,
|
|
@@ -393,6 +397,45 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
393
397
|
this.tracer._exporter.flush(onDone)
|
|
394
398
|
}
|
|
395
399
|
})
|
|
400
|
+
|
|
401
|
+
this.addSub('ci:playwright:test:skip', ({
|
|
402
|
+
testName,
|
|
403
|
+
testSuiteAbsolutePath,
|
|
404
|
+
testSourceLine,
|
|
405
|
+
browserName,
|
|
406
|
+
isNew,
|
|
407
|
+
isDisabled,
|
|
408
|
+
isModified,
|
|
409
|
+
isQuarantined
|
|
410
|
+
}) => {
|
|
411
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
|
|
412
|
+
const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
413
|
+
const span = this.startTestSpan(
|
|
414
|
+
testName,
|
|
415
|
+
testSuiteAbsolutePath,
|
|
416
|
+
testSuite,
|
|
417
|
+
testSourceFile,
|
|
418
|
+
testSourceLine,
|
|
419
|
+
browserName
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
span.setTag(TEST_STATUS, 'skip')
|
|
423
|
+
|
|
424
|
+
if (isNew) {
|
|
425
|
+
span.setTag(TEST_IS_NEW, 'true')
|
|
426
|
+
}
|
|
427
|
+
if (isDisabled) {
|
|
428
|
+
span.setTag(TEST_MANAGEMENT_IS_DISABLED, 'true')
|
|
429
|
+
}
|
|
430
|
+
if (isModified) {
|
|
431
|
+
span.setTag(TEST_IS_MODIFIED, 'true')
|
|
432
|
+
}
|
|
433
|
+
if (isQuarantined) {
|
|
434
|
+
span.setTag(TEST_MANAGEMENT_IS_QUARANTINED, 'true')
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
span.finish()
|
|
438
|
+
})
|
|
396
439
|
}
|
|
397
440
|
|
|
398
441
|
// TODO: this runs both in worker and main process (main process: skipped tests that do not go through _runTest)
|
|
@@ -17,7 +17,7 @@ class WSClosePlugin extends TracingPlugin {
|
|
|
17
17
|
if (!traceWebsocketMessagesEnabled) return
|
|
18
18
|
|
|
19
19
|
const { code, data, socket, isPeerClose } = ctx
|
|
20
|
-
if (!socket
|
|
20
|
+
if (!socket?.spanContext) return
|
|
21
21
|
|
|
22
22
|
const spanKind = isPeerClose ? 'consumer' : 'producer'
|
|
23
23
|
const spanTags = socket.spanContext.spanTags
|
|
@@ -73,6 +73,8 @@ function copyObjectProperties (original, wrapped, skipKey) {
|
|
|
73
73
|
* @returns {Function} The wrapped function.
|
|
74
74
|
*/
|
|
75
75
|
function wrapFunction (original, wrapper) {
|
|
76
|
+
if (typeof original !== 'function') return original
|
|
77
|
+
|
|
76
78
|
const wrapped = wrapper(original)
|
|
77
79
|
|
|
78
80
|
if (typeof original === 'function') {
|
|
@@ -9,9 +9,15 @@ const {
|
|
|
9
9
|
AI_GUARD_ACTION_TAG_KEY,
|
|
10
10
|
AI_GUARD_BLOCKED_TAG_KEY,
|
|
11
11
|
AI_GUARD_META_STRUCT_KEY,
|
|
12
|
-
AI_GUARD_TOOL_NAME_TAG_KEY
|
|
12
|
+
AI_GUARD_TOOL_NAME_TAG_KEY,
|
|
13
|
+
AI_GUARD_TELEMETRY_REQUESTS,
|
|
14
|
+
AI_GUARD_TELEMETRY_TRUNCATED
|
|
13
15
|
} = require('./tags')
|
|
14
16
|
const log = require('../log')
|
|
17
|
+
const telemetryMetrics = require('../telemetry/metrics')
|
|
18
|
+
const tracerVersion = require('../../../../package.json').version
|
|
19
|
+
|
|
20
|
+
const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
|
|
15
21
|
|
|
16
22
|
const ALLOW = 'ALLOW'
|
|
17
23
|
|
|
@@ -58,6 +64,9 @@ class AIGuard extends NoopAIGuard {
|
|
|
58
64
|
this.#headers = {
|
|
59
65
|
'DD-API-KEY': config.apiKey,
|
|
60
66
|
'DD-APPLICATION-KEY': config.appKey,
|
|
67
|
+
'DD-AI-GUARD-VERSION': tracerVersion,
|
|
68
|
+
'DD-AI-GUARD-SOURCE': 'SDK',
|
|
69
|
+
'DD-AI-GUARD-LANGUAGE': 'nodejs'
|
|
61
70
|
}
|
|
62
71
|
const endpoint = config.experimental.aiguard.endpoint || `https://app.${config.site}/api/v2/ai-guard`
|
|
63
72
|
this.#evaluateUrl = `${endpoint}/evaluate`
|
|
@@ -70,14 +79,22 @@ class AIGuard extends NoopAIGuard {
|
|
|
70
79
|
|
|
71
80
|
#truncate (messages) {
|
|
72
81
|
const size = Math.min(messages.length, this.#maxMessagesLength)
|
|
82
|
+
if (messages.length > size) {
|
|
83
|
+
appsecMetrics.count(AI_GUARD_TELEMETRY_TRUNCATED, { type: 'messages' }).inc(1)
|
|
84
|
+
}
|
|
73
85
|
const result = messages.slice(-size)
|
|
74
86
|
|
|
87
|
+
let contentTruncated = false
|
|
75
88
|
for (let i = 0; i < size; i++) {
|
|
76
89
|
const message = result[i]
|
|
77
90
|
if (message.content?.length > this.#maxContentSize) {
|
|
91
|
+
contentTruncated = true
|
|
78
92
|
result[i] = { ...message, content: message.content.slice(0, this.#maxContentSize) }
|
|
79
93
|
}
|
|
80
94
|
}
|
|
95
|
+
if (contentTruncated) {
|
|
96
|
+
appsecMetrics.count(AI_GUARD_TELEMETRY_TRUNCATED, { type: 'content' }).inc(1)
|
|
97
|
+
}
|
|
81
98
|
return result
|
|
82
99
|
}
|
|
83
100
|
|
|
@@ -140,9 +157,11 @@ class AIGuard extends NoopAIGuard {
|
|
|
140
157
|
payload,
|
|
141
158
|
{ url: this.#evaluateUrl, headers: this.#headers, timeout: this.#timeout })
|
|
142
159
|
} catch (e) {
|
|
143
|
-
|
|
160
|
+
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
|
|
161
|
+
throw new AIGuardClientError(`Unexpected error calling AI Guard service: ${e.message}`, { cause: e })
|
|
144
162
|
}
|
|
145
163
|
if (response.status !== 200) {
|
|
164
|
+
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
|
|
146
165
|
throw new AIGuardClientError(
|
|
147
166
|
`AI Guard service call failed, status ${response.status}`,
|
|
148
167
|
{ errors: response.body?.errors })
|
|
@@ -157,11 +176,14 @@ class AIGuard extends NoopAIGuard {
|
|
|
157
176
|
reason = attr.reason
|
|
158
177
|
blockingEnabled = attr.is_blocking_enabled ?? false
|
|
159
178
|
} catch (e) {
|
|
179
|
+
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
|
|
160
180
|
throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}`, { cause: e })
|
|
161
181
|
}
|
|
182
|
+
const shouldBlock = block && blockingEnabled && action !== ALLOW
|
|
183
|
+
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { action, error: false, block: shouldBlock }).inc(1)
|
|
162
184
|
span.setTag(AI_GUARD_ACTION_TAG_KEY, action)
|
|
163
185
|
span.setTag(AI_GUARD_REASON_TAG_KEY, reason)
|
|
164
|
-
if (
|
|
186
|
+
if (shouldBlock) {
|
|
165
187
|
span.setTag(AI_GUARD_BLOCKED_TAG_KEY, 'true')
|
|
166
188
|
throw new AIGuardAbortError(reason)
|
|
167
189
|
}
|
|
@@ -7,5 +7,8 @@ module.exports = {
|
|
|
7
7
|
AI_GUARD_ACTION_TAG_KEY: 'ai_guard.action',
|
|
8
8
|
AI_GUARD_REASON_TAG_KEY: 'ai_guard.reason',
|
|
9
9
|
AI_GUARD_BLOCKED_TAG_KEY: 'ai_guard.blocked',
|
|
10
|
-
AI_GUARD_META_STRUCT_KEY: 'ai_guard'
|
|
10
|
+
AI_GUARD_META_STRUCT_KEY: 'ai_guard',
|
|
11
|
+
|
|
12
|
+
AI_GUARD_TELEMETRY_REQUESTS: 'ai_guard.requests',
|
|
13
|
+
AI_GUARD_TELEMETRY_TRUNCATED: 'ai_guard.truncated'
|
|
11
14
|
}
|
|
@@ -37,7 +37,9 @@ for (const deprecation of Object.keys(deprecations)) {
|
|
|
37
37
|
module.exports = {
|
|
38
38
|
/**
|
|
39
39
|
* Returns the environment variables that are supported by the tracer
|
|
40
|
-
* (including all non-Datadog/OTEL specific environment variables)
|
|
40
|
+
* (including all non-Datadog/OTEL specific environment variables).
|
|
41
|
+
*
|
|
42
|
+
* This should only be called once in config.js to avoid copying the object frequently.
|
|
41
43
|
*
|
|
42
44
|
* @returns {TracerEnv} The environment variables
|
|
43
45
|
*/
|
|
@@ -78,6 +80,7 @@ module.exports = {
|
|
|
78
80
|
* @returns {string|undefined}
|
|
79
81
|
* @throws {Error} if the configuration is not supported
|
|
80
82
|
*/
|
|
83
|
+
// This method, and callers of this method, need to be updated to check for declarative config sources as well.
|
|
81
84
|
getEnvironmentVariable (name) {
|
|
82
85
|
if ((name.startsWith('DD_') || name.startsWith('OTEL_') || aliasToCanonical[name]) &&
|
|
83
86
|
!supportedConfigurations[name]) {
|