dd-trace 6.10.0 → 6.11.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 +0 -17
- package/index.d.ts +108 -3
- package/initialize.mjs +28 -17
- package/openfeature.js +2 -2
- package/package.json +11 -8
- package/packages/datadog-esbuild/index.js +0 -34
- package/packages/datadog-instrumentations/src/anthropic.js +210 -15
- package/packages/datadog-instrumentations/src/aws-sdk.js +9 -1
- package/packages/datadog-instrumentations/src/browser-bunyan.js +11 -0
- package/packages/datadog-instrumentations/src/bunyan.js +3 -16
- package/packages/datadog-instrumentations/src/cucumber.js +26 -11
- package/packages/datadog-instrumentations/src/cypress-config.js +182 -16
- package/packages/datadog-instrumentations/src/cypress-legacy-finalizers.js +30 -0
- package/packages/datadog-instrumentations/src/cypress.js +2 -0
- package/packages/datadog-instrumentations/src/fastify.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bunyan.js +22 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +9 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -8
- package/packages/datadog-instrumentations/src/jest.js +25 -17
- package/packages/datadog-instrumentations/src/mariadb.js +278 -21
- package/packages/datadog-instrumentations/src/mocha/main.js +539 -55
- package/packages/datadog-instrumentations/src/mocha/utils.js +130 -17
- package/packages/datadog-instrumentations/src/playwright-reporter.js +99 -0
- package/packages/datadog-instrumentations/src/playwright.js +149 -2
- package/packages/datadog-instrumentations/src/router.js +2 -0
- package/packages/datadog-instrumentations/src/vitest-main.js +11 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +163 -44
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -8
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-browser-bunyan/src/index.js +9 -0
- package/packages/datadog-plugin-bunyan/src/index.js +5 -8
- package/packages/datadog-plugin-cucumber/src/index.js +11 -0
- package/packages/datadog-plugin-cypress/src/after-run.js +5 -1
- package/packages/datadog-plugin-cypress/src/after-spec.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +81 -29
- package/packages/datadog-plugin-cypress/src/finalization.js +76 -0
- package/packages/datadog-plugin-cypress/src/index.js +12 -6
- package/packages/datadog-plugin-cypress/src/plugin.js +16 -3
- package/packages/datadog-plugin-dd-trace-api/src/index.js +4 -0
- package/packages/datadog-plugin-electron/src/index.js +2 -0
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +6 -0
- package/packages/datadog-plugin-mocha/src/index.js +56 -1
- package/packages/datadog-plugin-nats/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/tracing.js +41 -30
- package/packages/datadog-plugin-openai-agents/src/integration.js +1 -0
- package/packages/datadog-plugin-playwright/src/index.js +42 -13
- package/packages/datadog-plugin-vitest/src/index.js +6 -0
- package/packages/datadog-webpack/index.js +0 -11
- package/packages/dd-trace/index.js +0 -1
- package/packages/dd-trace/src/agent/info.js +6 -5
- package/packages/dd-trace/src/aiguard/client.js +100 -1
- package/packages/dd-trace/src/aiguard/errors.js +41 -0
- package/packages/dd-trace/src/aiguard/evaluation.js +357 -0
- package/packages/dd-trace/src/aiguard/integrations/anthropic.js +70 -0
- package/packages/dd-trace/src/aiguard/integrations/index.js +4 -0
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +423 -0
- package/packages/dd-trace/src/aiguard/messages/openai.js +1 -24
- package/packages/dd-trace/src/aiguard/messages/utils.js +28 -0
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +1 -11
- package/packages/dd-trace/src/aiguard/sdk.js +22 -278
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -12
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +1 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +27 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +21 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +164 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +365 -32
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +201 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -5
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +39 -0
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +6 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
- package/packages/dd-trace/src/config/index.js +13 -2
- package/packages/dd-trace/src/config/major-overrides.js +7 -0
- package/packages/dd-trace/src/config/supported-configurations.json +14 -0
- package/packages/dd-trace/src/datastreams/index.js +2 -0
- package/packages/dd-trace/src/datastreams/manager.js +9 -2
- package/packages/dd-trace/src/datastreams/processor.js +15 -13
- package/packages/dd-trace/src/datastreams/size.js +5 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +49 -9
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +6 -4
- package/packages/dd-trace/src/exporters/common/writer.js +11 -6
- package/packages/dd-trace/src/llmobs/experiments/client.js +163 -5
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +241 -87
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +280 -20
- package/packages/dd-trace/src/llmobs/experiments/index.js +58 -59
- package/packages/dd-trace/src/llmobs/experiments/noop.js +71 -3
- package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/util.js +41 -5
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +12 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -2
- package/packages/dd-trace/src/noop/proxy.js +3 -4
- package/packages/dd-trace/src/openfeature/flagging_provider.js +18 -2
- package/packages/dd-trace/src/openfeature/remote_config.js +1 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +7 -7
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +2 -1
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +67 -11
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +14 -3
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +25 -12
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +2 -5
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +96 -43
- package/packages/dd-trace/src/opentracing/tracer.js +5 -2
- package/packages/dd-trace/src/otel-thread-ctx.js +387 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/jest.js +4 -3
- package/packages/dd-trace/src/plugins/util/test.js +9 -9
- package/packages/dd-trace/src/plugins/util/web.js +3 -0
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +37 -90
- package/packages/dd-trace/src/profiling/webspan-utils.js +45 -0
- package/packages/dd-trace/src/proxy.js +38 -29
- package/packages/dd-trace/src/ritm.js +9 -2
- package/packages/dd-trace/src/serverless.js +37 -0
- package/packages/dd-trace/src/span_format.js +1 -0
- package/packages/dd-trace/src/span_stats.js +30 -3
- package/packages/dd-trace/src/storage-channels.js +86 -0
- package/packages/dd-trace/src/tracer.js +9 -2
- package/packages/dd-trace/src/tracer_metadata.js +14 -1
- package/packages/dd-trace/src/web-tags-cache.js +132 -0
- package/vendor/dist/@datadog/openfeature-node-server/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +0 -65
- package/packages/datadog-webpack/src/optional-peer-loader.js +0 -17
- package/packages/dd-trace/src/feature-registry.js +0 -29
- package/packages/dd-trace/src/openfeature/register.js +0 -35
- package/packages/dd-trace/src/openfeature/require-provider.js +0 -18
|
@@ -25,6 +25,13 @@ const KNOWN_CHANNEL_SUFFIXES = new Set([
|
|
|
25
25
|
'bedrockruntime',
|
|
26
26
|
])
|
|
27
27
|
|
|
28
|
+
// Older SDK clients report EventBridge under its CloudWatch Events name or its `events` endpoint
|
|
29
|
+
// prefix; both share the EventBridge channels.
|
|
30
|
+
const CHANNEL_SUFFIX_ALIASES = new Map([
|
|
31
|
+
['cloudwatchevents', 'eventbridge'],
|
|
32
|
+
['events', 'eventbridge'],
|
|
33
|
+
])
|
|
34
|
+
|
|
28
35
|
/**
|
|
29
36
|
* @typedef {object} ChannelBag
|
|
30
37
|
* @property {ReturnType<typeof channel>} start
|
|
@@ -314,7 +321,8 @@ function addResponse (ctx, error, result) {
|
|
|
314
321
|
function getChannelSuffix (name) {
|
|
315
322
|
// some resource identifiers have spaces between ex: bedrock runtime
|
|
316
323
|
name = String(name).replaceAll(' ', '')
|
|
317
|
-
|
|
324
|
+
if (KNOWN_CHANNEL_SUFFIXES.has(name)) return name
|
|
325
|
+
return CHANNEL_SUFFIX_ALIASES.get(name) ?? 'default'
|
|
318
326
|
}
|
|
319
327
|
|
|
320
328
|
addHook({ name: '@smithy/smithy-client', versions: ['>=1.0.3'] }, smithy => {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const wrapLogger = require('./helpers/bunyan')
|
|
4
|
+
const { addHook } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
addHook({ name: 'browser-bunyan', versions: ['>=1'] }, browserBunyan => {
|
|
7
|
+
// Published versions generate `_emit` through different bundle shapes,
|
|
8
|
+
// so Orchestrion has no stable function to match.
|
|
9
|
+
wrapLogger(browserBunyan.Logger, 'browser-bunyan')
|
|
10
|
+
return browserBunyan
|
|
11
|
+
})
|
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
channel,
|
|
6
|
-
addHook,
|
|
7
|
-
} = require('./helpers/instrument')
|
|
3
|
+
const wrapLogger = require('./helpers/bunyan')
|
|
4
|
+
const { addHook } = require('./helpers/instrument')
|
|
8
5
|
|
|
9
6
|
addHook({ name: 'bunyan', versions: ['>=1'] }, Logger => {
|
|
10
|
-
|
|
11
|
-
shimmer.wrap(Logger.prototype, '_emit', emit => {
|
|
12
|
-
return function wrappedEmit (rec) {
|
|
13
|
-
if (logCh.hasSubscribers) {
|
|
14
|
-
const payload = { message: rec }
|
|
15
|
-
logCh.publish(payload)
|
|
16
|
-
arguments[0] = payload.message
|
|
17
|
-
}
|
|
18
|
-
return emit.apply(this, arguments)
|
|
19
|
-
}
|
|
20
|
-
})
|
|
7
|
+
wrapLogger(Logger, 'bunyan')
|
|
21
8
|
return Logger
|
|
22
9
|
})
|
|
@@ -116,7 +116,7 @@ let pickleByFile = {}
|
|
|
116
116
|
const pickleResultByFile = {}
|
|
117
117
|
|
|
118
118
|
let skippableSuites = []
|
|
119
|
-
let skippableSuitesCoverage
|
|
119
|
+
let skippableSuitesCoverage
|
|
120
120
|
let skippedSuitesCoverage = {}
|
|
121
121
|
let itrCorrelationId = ''
|
|
122
122
|
let isForcedToRun = false
|
|
@@ -153,12 +153,6 @@ function isValidKnownTests (receivedKnownTests) {
|
|
|
153
153
|
return !!receivedKnownTests.cucumber
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
function hasSkippableSuitesCoverage () {
|
|
157
|
-
return skippableSuitesCoverage &&
|
|
158
|
-
typeof skippableSuitesCoverage === 'object' &&
|
|
159
|
-
Object.keys(skippableSuitesCoverage).length > 0
|
|
160
|
-
}
|
|
161
|
-
|
|
162
156
|
function isTiaCoverageBackfillEnabled () {
|
|
163
157
|
return isItrEnabled && isCoverageReportUploadEnabled
|
|
164
158
|
}
|
|
@@ -172,7 +166,7 @@ function shouldReportCodeCoverageLinesPct (hasBackfilledCoverage) {
|
|
|
172
166
|
}
|
|
173
167
|
|
|
174
168
|
function getSkippedSuitesCoverageForRun () {
|
|
175
|
-
return isSuitesSkipped && isTiaCoverageBackfillEnabled() &&
|
|
169
|
+
return isSuitesSkipped && isTiaCoverageBackfillEnabled() && skippableSuitesCoverage !== undefined
|
|
176
170
|
? skippableSuitesCoverage
|
|
177
171
|
: {}
|
|
178
172
|
}
|
|
@@ -188,7 +182,7 @@ function getCucumberTestSessionCoverageFiles () {
|
|
|
188
182
|
|
|
189
183
|
function resetSuiteSkippingRunState () {
|
|
190
184
|
skippableSuites = []
|
|
191
|
-
skippableSuitesCoverage =
|
|
185
|
+
skippableSuitesCoverage = undefined
|
|
192
186
|
skippedSuitesCoverage = {}
|
|
193
187
|
skippedSuites = []
|
|
194
188
|
isSuitesSkipped = false
|
|
@@ -1143,7 +1137,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
1143
1137
|
|
|
1144
1138
|
errorSkippableRequest = skippableResponse.err
|
|
1145
1139
|
skippableSuites = skippableResponse.skippableSuites ?? []
|
|
1146
|
-
skippableSuitesCoverage = skippableResponse.skippableSuitesCoverage
|
|
1140
|
+
skippableSuitesCoverage = skippableResponse.skippableSuitesCoverage
|
|
1147
1141
|
|
|
1148
1142
|
if (!errorSkippableRequest) {
|
|
1149
1143
|
const filteredPickles = isCoordinator
|
|
@@ -1222,7 +1216,28 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
1222
1216
|
itrSkippedSuitesCh.publish({ skippedSuites, frameworkVersion })
|
|
1223
1217
|
}
|
|
1224
1218
|
|
|
1225
|
-
|
|
1219
|
+
let result
|
|
1220
|
+
try {
|
|
1221
|
+
result = await start.apply(this, arguments)
|
|
1222
|
+
} catch (error) {
|
|
1223
|
+
try {
|
|
1224
|
+
await getChannelPromise(sessionFinishCh, {
|
|
1225
|
+
status: 'fail',
|
|
1226
|
+
error,
|
|
1227
|
+
isSuitesSkipped,
|
|
1228
|
+
numSkippedSuites: skippedSuites.length,
|
|
1229
|
+
hasUnskippableSuites: isUnskippable,
|
|
1230
|
+
hasForcedToRunSuites: isForcedToRun,
|
|
1231
|
+
isEarlyFlakeDetectionEnabled,
|
|
1232
|
+
isEarlyFlakeDetectionFaulty,
|
|
1233
|
+
isTestManagementTestsEnabled,
|
|
1234
|
+
isParallel,
|
|
1235
|
+
})
|
|
1236
|
+
} catch (finalizationError) {
|
|
1237
|
+
log.error('Cucumber test session finalization error: %s', finalizationError)
|
|
1238
|
+
}
|
|
1239
|
+
throw error
|
|
1240
|
+
}
|
|
1226
1241
|
const success = satisfies(frameworkVersion, '>=13.1.0') ? result.success : result
|
|
1227
1242
|
|
|
1228
1243
|
let untestedCoverage
|
|
@@ -7,9 +7,18 @@ const { pathToFileURL } = require('url')
|
|
|
7
7
|
|
|
8
8
|
const log = require('../../dd-trace/src/log')
|
|
9
9
|
const { getSegment } = require('../../dd-trace/src/util')
|
|
10
|
+
const {
|
|
11
|
+
finalizeAfterUserHandlers,
|
|
12
|
+
manualPluginOwner,
|
|
13
|
+
runUserHandler,
|
|
14
|
+
} = require('../../datadog-plugin-cypress/src/finalization')
|
|
10
15
|
const { channel } = require('./helpers/instrument')
|
|
11
16
|
|
|
12
17
|
const DD_CONFIG_WRAPPED = Symbol.for('dd-trace.cypress.config.wrapped')
|
|
18
|
+
const DD_CYPRESS_AFTER_SPEC_HANDLER = Symbol.for('dd-trace.cypress.after-spec.handler')
|
|
19
|
+
const DD_CYPRESS_AFTER_RUN_HANDLER = Symbol.for('dd-trace.cypress.after-run.handler')
|
|
20
|
+
const DD_CYPRESS_TASK_HANDLER = Symbol.for('dd-trace.cypress.task.handler')
|
|
21
|
+
const DD_CYPRESS_NOOP_TASK_HANDLER = Symbol.for('dd-trace.cypress.noop-task.handler')
|
|
13
22
|
const BROWSER_INSTRUMENTATION_NOT_INSTALLED =
|
|
14
23
|
'Browser-side Cypress Test Optimization instrumentation was not installed.'
|
|
15
24
|
const CONFIG_INSTRUMENTATION_NOT_INSTALLED =
|
|
@@ -184,6 +193,47 @@ function isDatadogTaskRegistration (handler) {
|
|
|
184
193
|
typeof handler['dd:addTags'] === 'function'
|
|
185
194
|
}
|
|
186
195
|
|
|
196
|
+
/**
|
|
197
|
+
* @param {unknown} handler Cypress after:run handler
|
|
198
|
+
* @returns {boolean} whether this is the handler registered by the manual Datadog plugin
|
|
199
|
+
*/
|
|
200
|
+
function isDatadogAfterRunHandler (handler) {
|
|
201
|
+
return typeof handler === 'function' && handler[DD_CYPRESS_AFTER_RUN_HANDLER] === true
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {unknown} handler Cypress after:spec handler
|
|
206
|
+
* @returns {boolean} whether this is the handler registered by the manual Datadog plugin
|
|
207
|
+
*/
|
|
208
|
+
function isDatadogAfterSpecHandler (handler) {
|
|
209
|
+
return typeof handler === 'function' && handler[DD_CYPRESS_AFTER_SPEC_HANDLER] === true
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @param {object} manualPlugin manual plugin registration state
|
|
214
|
+
* @returns {boolean} whether the manual plugin supports error-aware finalization
|
|
215
|
+
*/
|
|
216
|
+
function supportsErrorAwareFinalization (manualPlugin) {
|
|
217
|
+
return isDatadogAfterSpecHandler(manualPlugin.afterSpecHandler) &&
|
|
218
|
+
isDatadogAfterRunHandler(manualPlugin.afterRunHandler)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @param {unknown} handler Cypress task handler map
|
|
223
|
+
* @returns {boolean} whether the current manual Datadog plugin owns the task map
|
|
224
|
+
*/
|
|
225
|
+
function isCurrentDatadogTaskRegistration (handler) {
|
|
226
|
+
return !!handler && handler[DD_CYPRESS_TASK_HANDLER] === manualPluginOwner
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @param {unknown} handler Cypress task handler map
|
|
231
|
+
* @returns {boolean} whether the manual plugin registered only fallback tasks
|
|
232
|
+
*/
|
|
233
|
+
function isDatadogNoopTaskRegistration (handler) {
|
|
234
|
+
return !!handler && handler[DD_CYPRESS_NOOP_TASK_HANDLER] === true
|
|
235
|
+
}
|
|
236
|
+
|
|
187
237
|
/**
|
|
188
238
|
* @param {unknown} value
|
|
189
239
|
* @returns {boolean}
|
|
@@ -393,15 +443,61 @@ function registerManualAfterScreenshotHandlers (on, handlers, datadogHandler) {
|
|
|
393
443
|
*
|
|
394
444
|
* @param {Function} on Cypress event registration function
|
|
395
445
|
* @param {Function[]} handlers collected after:spec handlers
|
|
446
|
+
* @param {Function} [datadogHandler] manual Datadog after:spec handler
|
|
447
|
+
* @param {Function} [cleanup] removes generated support files after an error
|
|
396
448
|
* @returns {void}
|
|
397
449
|
*/
|
|
398
|
-
function registerAfterSpecHandlers (on, handlers) {
|
|
399
|
-
|
|
450
|
+
function registerAfterSpecHandlers (on, handlers, datadogHandler, cleanup) {
|
|
451
|
+
const userHandlers = datadogHandler
|
|
452
|
+
? handlers.filter(handler => handler !== datadogHandler)
|
|
453
|
+
: handlers
|
|
400
454
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
455
|
+
if (userHandlers.length === 0) {
|
|
456
|
+
if (datadogHandler) {
|
|
457
|
+
if (cleanup) {
|
|
458
|
+
on('after:spec', (...args) => Promise.resolve().then(() => datadogHandler(...args)).catch((error) => {
|
|
459
|
+
cleanup()
|
|
460
|
+
throw error
|
|
461
|
+
}))
|
|
462
|
+
} else {
|
|
463
|
+
on('after:spec', datadogHandler)
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
on('after:spec', (spec, results) => {
|
|
470
|
+
const callHandler = datadogHandler
|
|
471
|
+
? handler => runUserHandler(() => handler(spec, results))
|
|
472
|
+
: handler => handler(spec, results)
|
|
473
|
+
const chain = userHandlers.reduce(
|
|
474
|
+
(promise, handler) => promise.then(() => callHandler(handler)),
|
|
475
|
+
Promise.resolve()
|
|
476
|
+
)
|
|
477
|
+
if (!datadogHandler) return chain
|
|
478
|
+
const finalization = finalizeAfterUserHandlers(chain, (...args) => datadogHandler(spec, results, ...args))
|
|
479
|
+
if (!cleanup) return finalization
|
|
480
|
+
return finalization.catch((error) => {
|
|
481
|
+
cleanup()
|
|
482
|
+
throw error
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Enables the Cypress lifecycle events needed to finish Test Optimization
|
|
489
|
+
* sessions in interactive mode.
|
|
490
|
+
*
|
|
491
|
+
* @param {object} config Cypress resolved config object
|
|
492
|
+
* @returns {void}
|
|
493
|
+
*/
|
|
494
|
+
function enableInteractiveRunEvents (config) {
|
|
495
|
+
if (config.isInteractive && config.experimentalInteractiveRunEvents !== true) {
|
|
496
|
+
config.experimentalInteractiveRunEvents = true
|
|
497
|
+
log.warn(
|
|
498
|
+
'Datadog enabled Cypress experimentalInteractiveRunEvents so Test Optimization can finish the test session.'
|
|
499
|
+
)
|
|
500
|
+
}
|
|
405
501
|
}
|
|
406
502
|
|
|
407
503
|
/**
|
|
@@ -412,6 +508,7 @@ function registerAfterSpecHandlers (on, handlers) {
|
|
|
412
508
|
*
|
|
413
509
|
* @param {Function} on Cypress event registration function
|
|
414
510
|
* @param {object} config Cypress resolved config object
|
|
511
|
+
* @param {Function[]} userBeforeRunHandlers user's before:run handlers collected from wrappedOn
|
|
415
512
|
* @param {Function[]} userAfterSpecHandlers user's after:spec handlers collected from wrappedOn
|
|
416
513
|
* @param {Function[]} userAfterRunHandlers user's after:run handlers collected from wrappedOn
|
|
417
514
|
* @param {Function[]} userAfterScreenshotHandlers user's after:screenshot handlers collected from wrappedOn
|
|
@@ -421,6 +518,7 @@ function registerAfterSpecHandlers (on, handlers) {
|
|
|
421
518
|
function registerDdTraceHooks (
|
|
422
519
|
on,
|
|
423
520
|
config,
|
|
521
|
+
userBeforeRunHandlers,
|
|
424
522
|
userAfterSpecHandlers,
|
|
425
523
|
userAfterRunHandlers,
|
|
426
524
|
userAfterScreenshotHandlers,
|
|
@@ -433,13 +531,23 @@ function registerDdTraceHooks (
|
|
|
433
531
|
if (generatedSupportFiles) cleanupGeneratedFiles(generatedSupportFiles)
|
|
434
532
|
}
|
|
435
533
|
|
|
436
|
-
const registerAfterRunWithCleanup = () => {
|
|
534
|
+
const registerAfterRunWithCleanup = (datadogHandler) => {
|
|
535
|
+
const handlers = datadogHandler
|
|
536
|
+
? userAfterRunHandlers.filter(handler => handler !== datadogHandler)
|
|
537
|
+
: userAfterRunHandlers
|
|
538
|
+
|
|
437
539
|
on('after:run', (results) => {
|
|
438
|
-
const
|
|
439
|
-
|
|
540
|
+
const callHandler = datadogHandler
|
|
541
|
+
? handler => runUserHandler(() => handler(results))
|
|
542
|
+
: handler => handler(results)
|
|
543
|
+
const chain = handlers.reduce(
|
|
544
|
+
(promise, handler) => promise.then(() => callHandler(handler)),
|
|
440
545
|
Promise.resolve()
|
|
441
546
|
)
|
|
442
|
-
return chain.finally(cleanupWrapper)
|
|
547
|
+
if (!datadogHandler) return chain.finally(cleanupWrapper)
|
|
548
|
+
|
|
549
|
+
return finalizeAfterUserHandlers(chain, (...args) => datadogHandler(results, ...args))
|
|
550
|
+
.finally(cleanupWrapper)
|
|
443
551
|
})
|
|
444
552
|
}
|
|
445
553
|
|
|
@@ -450,13 +558,36 @@ function registerDdTraceHooks (
|
|
|
450
558
|
on('task', noopTask)
|
|
451
559
|
}
|
|
452
560
|
|
|
453
|
-
if (manualPlugin.detected
|
|
454
|
-
|
|
561
|
+
if (manualPlugin.detected &&
|
|
562
|
+
(manualPlugin.isNoop ||
|
|
563
|
+
manualPlugin.ownsCurrentPlugin ||
|
|
564
|
+
supportsErrorAwareFinalization(manualPlugin) ||
|
|
565
|
+
!setupNodeEventsCh.hasSubscribers)) {
|
|
566
|
+
if (manualPlugin.afterRunHandler) {
|
|
567
|
+
enableInteractiveRunEvents(config)
|
|
568
|
+
if (manualPlugin.initialConfig !== config) {
|
|
569
|
+
manualPlugin.initialConfig.experimentalInteractiveRunEvents = config.experimentalInteractiveRunEvents
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
for (const handler of userBeforeRunHandlers) on('before:run', handler)
|
|
573
|
+
registerAfterSpecHandlers(on, userAfterSpecHandlers, manualPlugin.afterSpecHandler, cleanupWrapper)
|
|
455
574
|
registerManualAfterScreenshotHandlers(on, userAfterScreenshotHandlers, manualPlugin.afterScreenshotHandler)
|
|
456
|
-
registerAfterRunWithCleanup()
|
|
575
|
+
registerAfterRunWithCleanup(manualPlugin.afterRunHandler)
|
|
576
|
+
on('task', manualPlugin.taskHandler)
|
|
457
577
|
return config
|
|
458
578
|
}
|
|
459
579
|
|
|
580
|
+
if (manualPlugin.detected) {
|
|
581
|
+
userBeforeRunHandlers = userBeforeRunHandlers.filter(handler => handler !== manualPlugin.beforeRunHandler)
|
|
582
|
+
userAfterSpecHandlers = userAfterSpecHandlers.filter(handler => handler !== manualPlugin.afterSpecHandler)
|
|
583
|
+
userAfterRunHandlers = userAfterRunHandlers.filter(handler => handler !== manualPlugin.afterRunHandler)
|
|
584
|
+
userAfterScreenshotHandlers = userAfterScreenshotHandlers.filter(
|
|
585
|
+
handler => handler !== manualPlugin.afterScreenshotHandler
|
|
586
|
+
)
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
for (const handler of userBeforeRunHandlers) on('before:run', handler)
|
|
590
|
+
|
|
460
591
|
if (!setupNodeEventsCh.hasSubscribers) {
|
|
461
592
|
registerNoopHandlers()
|
|
462
593
|
return config
|
|
@@ -483,6 +614,7 @@ function registerDdTraceHooks (
|
|
|
483
614
|
return config
|
|
484
615
|
}
|
|
485
616
|
|
|
617
|
+
enableInteractiveRunEvents(config)
|
|
486
618
|
return payload.configPromise || config
|
|
487
619
|
}
|
|
488
620
|
|
|
@@ -492,28 +624,60 @@ function registerDdTraceHooks (
|
|
|
492
624
|
*/
|
|
493
625
|
function wrapSetupNodeEvents (originalSetupNodeEvents) {
|
|
494
626
|
return function ddSetupNodeEvents (on, config) {
|
|
627
|
+
const userBeforeRunHandlers = []
|
|
495
628
|
const userAfterSpecHandlers = []
|
|
496
629
|
const userAfterRunHandlers = []
|
|
497
630
|
const userAfterScreenshotHandlers = []
|
|
498
631
|
const manualPlugin = {
|
|
499
632
|
detected: false,
|
|
633
|
+
initialConfig: config,
|
|
634
|
+
beforeRunHandler: undefined,
|
|
635
|
+
afterSpecHandler: undefined,
|
|
636
|
+
afterRunHandler: undefined,
|
|
500
637
|
afterScreenshotHandler: undefined,
|
|
638
|
+
taskHandler: undefined,
|
|
639
|
+
ownsCurrentPlugin: false,
|
|
640
|
+
isNoop: false,
|
|
501
641
|
}
|
|
642
|
+
const recentRegistrations = []
|
|
502
643
|
|
|
503
644
|
const wrappedOn = (event, handler) => {
|
|
504
|
-
if (event === '
|
|
645
|
+
if (event === 'before:run') {
|
|
646
|
+
userBeforeRunHandlers.push(handler)
|
|
647
|
+
} else if (event === 'after:spec') {
|
|
505
648
|
userAfterSpecHandlers.push(handler)
|
|
649
|
+
if (isDatadogAfterSpecHandler(handler)) manualPlugin.afterSpecHandler = handler
|
|
506
650
|
} else if (event === 'after:run') {
|
|
507
651
|
userAfterRunHandlers.push(handler)
|
|
652
|
+
if (isDatadogAfterRunHandler(handler)) manualPlugin.afterRunHandler = handler
|
|
508
653
|
} else if (event === 'after:screenshot') {
|
|
509
654
|
userAfterScreenshotHandlers.push(handler)
|
|
510
655
|
} else {
|
|
511
656
|
if (event === 'task' && isDatadogTaskRegistration(handler)) {
|
|
512
657
|
manualPlugin.detected = true
|
|
513
|
-
manualPlugin.
|
|
658
|
+
manualPlugin.ownsCurrentPlugin = isCurrentDatadogTaskRegistration(handler)
|
|
659
|
+
manualPlugin.isNoop = isDatadogNoopTaskRegistration(handler)
|
|
660
|
+
const afterRun = recentRegistrations.at(-1)
|
|
661
|
+
const afterSpec = recentRegistrations.at(-2)
|
|
662
|
+
const possibleAfterScreenshot = recentRegistrations.at(-3)
|
|
663
|
+
const hasAfterScreenshot = possibleAfterScreenshot?.event === 'after:screenshot'
|
|
664
|
+
const beforeRun = hasAfterScreenshot ? recentRegistrations.at(-4) : possibleAfterScreenshot
|
|
665
|
+
if (!manualPlugin.isNoop &&
|
|
666
|
+
beforeRun?.event === 'before:run' &&
|
|
667
|
+
afterSpec?.event === 'after:spec' &&
|
|
668
|
+
afterRun?.event === 'after:run') {
|
|
669
|
+
manualPlugin.beforeRunHandler ||= beforeRun.handler
|
|
670
|
+
manualPlugin.afterSpecHandler ||= afterSpec.handler
|
|
671
|
+
manualPlugin.afterRunHandler ||= afterRun.handler
|
|
672
|
+
if (hasAfterScreenshot) manualPlugin.afterScreenshotHandler ||= possibleAfterScreenshot.handler
|
|
673
|
+
}
|
|
674
|
+
manualPlugin.taskHandler = handler
|
|
675
|
+
} else {
|
|
676
|
+
on(event, handler)
|
|
514
677
|
}
|
|
515
|
-
on(event, handler)
|
|
516
678
|
}
|
|
679
|
+
recentRegistrations.push({ event, handler })
|
|
680
|
+
if (recentRegistrations.length > 4) recentRegistrations.shift()
|
|
517
681
|
}
|
|
518
682
|
|
|
519
683
|
const maybePromise = originalSetupNodeEvents
|
|
@@ -525,6 +689,7 @@ function wrapSetupNodeEvents (originalSetupNodeEvents) {
|
|
|
525
689
|
return registerDdTraceHooks(
|
|
526
690
|
on,
|
|
527
691
|
mergeReturnedConfig(config, result),
|
|
692
|
+
userBeforeRunHandlers,
|
|
528
693
|
userAfterSpecHandlers,
|
|
529
694
|
userAfterRunHandlers,
|
|
530
695
|
userAfterScreenshotHandlers,
|
|
@@ -536,6 +701,7 @@ function wrapSetupNodeEvents (originalSetupNodeEvents) {
|
|
|
536
701
|
return registerDdTraceHooks(
|
|
537
702
|
on,
|
|
538
703
|
mergeReturnedConfig(config, maybePromise),
|
|
704
|
+
userBeforeRunHandlers,
|
|
539
705
|
userAfterSpecHandlers,
|
|
540
706
|
userAfterRunHandlers,
|
|
541
707
|
userAfterScreenshotHandlers,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { shouldDeferLegacyFinalization } = require('../../datadog-plugin-cypress/src/finalization')
|
|
4
|
+
const Hook = require('./helpers/hook')
|
|
5
|
+
|
|
6
|
+
const DD_CYPRESS_LEGACY_FINALIZER_WRAPPED = Symbol.for('dd-trace.cypress.legacy-finalizer.wrapped')
|
|
7
|
+
const LEGACY_FINALIZER_MODULES = new Set([
|
|
8
|
+
'dd-trace/packages/datadog-plugin-cypress/src/after-run.js',
|
|
9
|
+
'dd-trace/packages/datadog-plugin-cypress/src/after-spec.js',
|
|
10
|
+
])
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {Function} finalizer standalone Datadog Cypress finalizer
|
|
14
|
+
* @returns {Function} context-aware finalizer
|
|
15
|
+
*/
|
|
16
|
+
function wrapLegacyFinalizer (finalizer) {
|
|
17
|
+
if (finalizer[DD_CYPRESS_LEGACY_FINALIZER_WRAPPED]) return finalizer
|
|
18
|
+
|
|
19
|
+
function wrappedLegacyFinalizer () {
|
|
20
|
+
if (shouldDeferLegacyFinalization()) return
|
|
21
|
+
return finalizer.apply(this, arguments)
|
|
22
|
+
}
|
|
23
|
+
wrappedLegacyFinalizer[DD_CYPRESS_LEGACY_FINALIZER_WRAPPED] = true
|
|
24
|
+
return wrappedLegacyFinalizer
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Hook(['dd-trace'], { internals: true }, (moduleExports, moduleName) => {
|
|
28
|
+
if (!LEGACY_FINALIZER_MODULES.has(moduleName.replaceAll('\\', '/'))) return moduleExports
|
|
29
|
+
return wrapLegacyFinalizer(moduleExports)
|
|
30
|
+
})
|
|
@@ -146,6 +146,7 @@ function wrapHookDone (ctx, request, reply, req, name, doneCallback) {
|
|
|
146
146
|
ctx.error = error
|
|
147
147
|
publishError(ctx)
|
|
148
148
|
|
|
149
|
+
// eslint-disable-next-line no-restricted-syntax -- arbitrary cookie names; publishing {} sets a WAF address
|
|
149
150
|
const hasCookies = request.cookies && Object.keys(request.cookies).length > 0
|
|
150
151
|
|
|
151
152
|
if (cookieParserReadCh.hasSubscribers && hasCookies && !cookiesPublished.has(req)) {
|
|
@@ -193,6 +194,7 @@ function preHandler (request, reply, done) {
|
|
|
193
194
|
const res = getRes(reply)
|
|
194
195
|
const ctx = { req, res }
|
|
195
196
|
|
|
197
|
+
// eslint-disable-next-line no-restricted-syntax -- arbitrary body keys; publishing {} sets a WAF address
|
|
196
198
|
const hasBody = request.body && Object.keys(request.body).length > 0
|
|
197
199
|
|
|
198
200
|
// For multipart/form-data, the body is not available until after preValidation hook
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../../datadog-shimmer')
|
|
4
|
+
const { channel } = require('./instrument')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {{ prototype: object }} Logger
|
|
8
|
+
* @param {string} id
|
|
9
|
+
*/
|
|
10
|
+
module.exports = function wrapLogger (Logger, id) {
|
|
11
|
+
const logCh = channel(`apm:${id}:log`)
|
|
12
|
+
shimmer.wrap(Logger.prototype, '_emit', emit => {
|
|
13
|
+
return function wrappedEmit (rec) {
|
|
14
|
+
if (logCh.hasSubscribers) {
|
|
15
|
+
const payload = { message: rec }
|
|
16
|
+
logCh.publish(payload)
|
|
17
|
+
arguments[0] = payload.message
|
|
18
|
+
}
|
|
19
|
+
return emit.apply(this, arguments)
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}
|
|
@@ -70,6 +70,7 @@ module.exports = {
|
|
|
70
70
|
'aws-sdk': () => require('../aws-sdk'),
|
|
71
71
|
bluebird: () => require('../bluebird'),
|
|
72
72
|
'body-parser': () => require('../body-parser'),
|
|
73
|
+
'browser-bunyan': () => require('../browser-bunyan'),
|
|
73
74
|
bullmq: () => require('../bullmq'),
|
|
74
75
|
bunyan: () => require('../bunyan'),
|
|
75
76
|
'cassandra-driver': () => require('../cassandra-driver'),
|
|
@@ -110,7 +111,7 @@ module.exports = {
|
|
|
110
111
|
'light-my-request': () => require('../light-my-request'),
|
|
111
112
|
'limitd-client': () => require('../limitd-client'),
|
|
112
113
|
lodash: () => require('../lodash'),
|
|
113
|
-
mariadb: () => require('../mariadb'),
|
|
114
|
+
mariadb: { esmFirst: true, fn: () => require('../mariadb') },
|
|
114
115
|
memcached: () => require('../memcached'),
|
|
115
116
|
mercurius: () => require('../mercurius'),
|
|
116
117
|
'microgateway-core': () => require('../microgateway-core'),
|
|
@@ -518,10 +518,11 @@ function runPoolQueryConnectionCallback (
|
|
|
518
518
|
* @param {unknown} error
|
|
519
519
|
* @param {Record<string, unknown>} acquireCtx
|
|
520
520
|
* @param {AcquireErrorChannels} channels
|
|
521
|
+
* @param {number} [poolWaitTime]
|
|
521
522
|
*/
|
|
522
|
-
function reportPoolAcquireError (start, error, acquireCtx, channels) {
|
|
523
|
+
function reportPoolAcquireError (start, error, acquireCtx, channels, poolWaitTime) {
|
|
523
524
|
acquireCtx.error = error
|
|
524
|
-
acquireCtx.poolWaitTime = acquireWait(start)
|
|
525
|
+
acquireCtx.poolWaitTime = poolWaitTime ?? acquireWait(start)
|
|
525
526
|
if (start !== undefined) acquireCtx.startTime = performance.timeOrigin + start
|
|
526
527
|
channels.acquireStartCh.publish(acquireCtx)
|
|
527
528
|
channels.acquireFinishCh.publish(acquireCtx)
|
|
@@ -536,11 +537,14 @@ function reportPoolAcquireError (start, error, acquireCtx, channels) {
|
|
|
536
537
|
* @param {Function} callback
|
|
537
538
|
* @param {unknown} thisArg
|
|
538
539
|
* @param {ArgumentsLike} args
|
|
540
|
+
* @param {number} [poolWaitTime]
|
|
539
541
|
* @returns {unknown}
|
|
540
542
|
*/
|
|
541
|
-
function runPoolAcquireError (
|
|
543
|
+
function runPoolAcquireError (
|
|
544
|
+
start, error, acquireCtx, channels, connectionCtx, callback, thisArg, args, poolWaitTime
|
|
545
|
+
) {
|
|
542
546
|
return channels.connectionFinishCh.runStores(connectionCtx, () => {
|
|
543
|
-
reportPoolAcquireError(start, error, acquireCtx, channels)
|
|
547
|
+
reportPoolAcquireError(start, error, acquireCtx, channels, poolWaitTime)
|
|
544
548
|
return callback.apply(thisArg, args)
|
|
545
549
|
})
|
|
546
550
|
}
|
|
@@ -613,6 +617,7 @@ function takeClusterAcquire (key) {
|
|
|
613
617
|
}
|
|
614
618
|
|
|
615
619
|
module.exports = {
|
|
620
|
+
acquireWait,
|
|
616
621
|
clearPoolWaitTime,
|
|
617
622
|
dispatchesAcquireSynchronously,
|
|
618
623
|
isPoolQueryAcquire,
|
|
@@ -112,14 +112,6 @@ for (const name of names) {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
for (const { file, versions, hook, filePattern, patchDefault } of instrumentations[name]) {
|
|
115
|
-
if (isIitm && patchDefault === !!moduleExports.default) {
|
|
116
|
-
if (patchDefault) {
|
|
117
|
-
moduleExports = moduleExports.default
|
|
118
|
-
} else {
|
|
119
|
-
return moduleExports
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
115
|
const fullFilename = filename(name, file)
|
|
124
116
|
|
|
125
117
|
let matchesFile = moduleName === fullFilename
|
|
@@ -134,6 +126,16 @@ for (const name of names) {
|
|
|
134
126
|
}
|
|
135
127
|
|
|
136
128
|
if (matchesFile && matchVersion(moduleVersion, versions)) {
|
|
129
|
+
// IITM invokes this callback for every module in the package. Only unwrap the namespace after its file and
|
|
130
|
+
// version match, otherwise a default export from an unrelated internal module can replace that module.
|
|
131
|
+
if (isIitm && patchDefault === !!moduleExports.default) {
|
|
132
|
+
if (patchDefault) {
|
|
133
|
+
moduleExports = moduleExports.default
|
|
134
|
+
} else {
|
|
135
|
+
return moduleExports
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
137
139
|
// Do not log in case of an error to prevent duplicate telemetry for the same integration version.
|
|
138
140
|
instrumentedIntegrationsSuccess.set(`${name}@${moduleVersion}`, true)
|
|
139
141
|
try {
|