dd-trace 6.3.0 → 6.5.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.electron.md +7 -0
- package/README.md +17 -0
- package/ci/diagnose.js +2100 -0
- package/ci/init.js +23 -2
- package/ci/runbook.md +198 -0
- package/ci/test-optimization-validation/approval-artifacts.js +143 -0
- package/ci/test-optimization-validation/approval.js +299 -0
- package/ci/test-optimization-validation/artifact-id.js +20 -0
- package/ci/test-optimization-validation/bounded-json.js +121 -0
- package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
- package/ci/test-optimization-validation/ci-discovery.js +181 -0
- package/ci/test-optimization-validation/ci-remediation.js +210 -0
- package/ci/test-optimization-validation/cli.js +903 -0
- package/ci/test-optimization-validation/command-blocker.js +81 -0
- package/ci/test-optimization-validation/command-output-policy.js +206 -0
- package/ci/test-optimization-validation/command-runner.js +707 -0
- package/ci/test-optimization-validation/command-suitability.js +471 -0
- package/ci/test-optimization-validation/executable-approval.js +48 -0
- package/ci/test-optimization-validation/executable.js +480 -0
- package/ci/test-optimization-validation/generated-file-policy.js +63 -0
- package/ci/test-optimization-validation/generated-files.js +351 -0
- package/ci/test-optimization-validation/generated-verifier.js +196 -0
- package/ci/test-optimization-validation/init-probe-preload.js +163 -0
- package/ci/test-optimization-validation/init-probe.js +246 -0
- package/ci/test-optimization-validation/late-initialization.js +63 -0
- package/ci/test-optimization-validation/local-command.js +163 -0
- package/ci/test-optimization-validation/manifest-loader.js +133 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
- package/ci/test-optimization-validation/manifest-schema.js +862 -0
- package/ci/test-optimization-validation/offline-fixtures.js +327 -0
- package/ci/test-optimization-validation/offline-output.js +406 -0
- package/ci/test-optimization-validation/payload-normalizer.js +72 -0
- package/ci/test-optimization-validation/plan-writer.js +1120 -0
- package/ci/test-optimization-validation/preflight-runner.js +114 -0
- package/ci/test-optimization-validation/redaction.js +331 -0
- package/ci/test-optimization-validation/report-writer.js +1508 -0
- package/ci/test-optimization-validation/safe-files.js +203 -0
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
- package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
- package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
- package/ci/test-optimization-validation/setup-runner.js +97 -0
- package/ci/test-optimization-validation/static-diagnosis.js +159 -0
- package/ci/test-optimization-validation/test-output.js +129 -0
- package/ci/test-optimization-validation-manifest.schema.json +1 -0
- package/ci/validate-test-optimization.js +3 -0
- package/ext/exporters.js +1 -0
- package/index.d.ts +121 -8
- package/index.electron.js +3 -0
- package/init.js +18 -0
- package/initialize.mjs +1 -1
- package/loader-hook.mjs +28 -18
- package/openfeature.d.ts +1 -0
- package/openfeature.js +4 -0
- package/package.json +15 -8
- package/packages/datadog-instrumentations/src/ai.js +37 -26
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
- package/packages/datadog-instrumentations/src/cucumber.js +24 -10
- package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
- package/packages/datadog-instrumentations/src/express.js +20 -2
- package/packages/datadog-instrumentations/src/fastify.js +7 -11
- package/packages/datadog-instrumentations/src/grpc/server.js +18 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +8 -8
- package/packages/datadog-instrumentations/src/http2/server.js +143 -17
- package/packages/datadog-instrumentations/src/jest.js +36 -4
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +0 -2
- package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
- package/packages/datadog-instrumentations/src/mongodb.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/mquery.js +2 -2
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +24 -0
- package/packages/datadog-instrumentations/src/nyc.js +0 -2
- package/packages/datadog-instrumentations/src/oracledb.js +2 -2
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/playwright.js +159 -22
- package/packages/datadog-instrumentations/src/process.js +3 -0
- package/packages/datadog-instrumentations/src/router.js +191 -106
- package/packages/datadog-instrumentations/src/selenium.js +52 -26
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +2 -2
- package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
- package/packages/datadog-instrumentations/src/ws.js +2 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +41 -16
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +21 -21
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +14 -8
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -24
- package/packages/datadog-plugin-cucumber/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +24 -62
- package/packages/datadog-plugin-cypress/src/index.js +6 -1
- package/packages/datadog-plugin-cypress/src/support.js +92 -26
- package/packages/datadog-plugin-electron/src/ipc.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +177 -59
- package/packages/datadog-plugin-graphql/src/parse.js +22 -1
- package/packages/datadog-plugin-graphql/src/request.js +32 -1
- package/packages/datadog-plugin-graphql/src/utils.js +42 -0
- package/packages/datadog-plugin-graphql/src/validate.js +15 -3
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +38 -6
- package/packages/datadog-plugin-jest/src/util.js +21 -6
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +177 -64
- package/packages/datadog-plugin-router/src/index.js +11 -2
- package/packages/datadog-plugin-selenium/src/index.js +5 -36
- package/packages/datadog-plugin-vitest/src/index.js +4 -2
- package/packages/datadog-plugin-ws/src/close.js +2 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -1
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/datadog-plugin-ws/src/server.js +2 -1
- package/packages/dd-trace/index.electron.js +3 -0
- package/packages/dd-trace/index.js +2 -37
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
- package/packages/dd-trace/src/azure_metadata.js +2 -1
- package/packages/dd-trace/src/bootstrap.js +39 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -5
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +5 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +62 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -2
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
- package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +173 -9
- package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +20 -0
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +10 -0
- package/packages/dd-trace/src/config/supported-configurations.json +83 -0
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/datastreams/pathway.js +6 -4
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
- package/packages/dd-trace/src/exporters/common/request.js +59 -30
- package/packages/dd-trace/src/exporters/common/url.js +15 -1
- package/packages/dd-trace/src/feature-registry.js +29 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
- package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
- package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
- package/packages/dd-trace/src/llmobs/index.js +10 -2
- package/packages/dd-trace/src/llmobs/noop.js +6 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
- package/packages/dd-trace/src/llmobs/sdk.js +17 -0
- package/packages/dd-trace/src/llmobs/tagger.js +79 -7
- package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
- package/packages/dd-trace/src/llmobs/util.js +32 -0
- package/packages/dd-trace/src/noop/proxy.js +5 -4
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
- package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
- package/packages/dd-trace/src/openfeature/index.js +0 -2
- package/packages/dd-trace/src/openfeature/noop.js +1 -28
- package/packages/dd-trace/src/openfeature/register.js +35 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
- package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
- package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
- package/packages/dd-trace/src/opentelemetry/span.js +5 -0
- package/packages/dd-trace/src/opentracing/propagation/log.js +11 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +80 -14
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +10 -1
- package/packages/dd-trace/src/opentracing/tracer.js +7 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
- package/packages/dd-trace/src/plugins/util/git.js +3 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
- package/packages/dd-trace/src/plugins/util/test.js +65 -8
- package/packages/dd-trace/src/plugins/util/web.js +12 -0
- package/packages/dd-trace/src/proxy.js +99 -10
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/standalone/index.js +0 -36
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +26 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
|
@@ -122,28 +122,43 @@ function isMarkedAsUnskippable (test) {
|
|
|
122
122
|
return false
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
function getJestSuitesToRun (skippableSuites, originalTests, rootDir) {
|
|
125
|
+
function getJestSuitesToRun (skippableSuites, originalTests, rootDir, fallbackRootDir) {
|
|
126
126
|
const unskippableSuites = {}
|
|
127
127
|
const forcedToRunSuites = {}
|
|
128
128
|
|
|
129
129
|
const skippedSuites = []
|
|
130
130
|
const suitesToRun = []
|
|
131
|
+
const normalizedSkippableSuites = new Set(skippableSuites.map(suite => suite.replaceAll('\\', '/')))
|
|
131
132
|
|
|
132
133
|
for (const test of originalTests) {
|
|
133
134
|
const relativePath = getTestSuitePath(test.path, rootDir)
|
|
134
|
-
const
|
|
135
|
+
const testRootDir = test?.context?.config?.rootDir || fallbackRootDir
|
|
136
|
+
let fallbackRelativePath
|
|
137
|
+
let skippedSuite = normalizedSkippableSuites.has(relativePath) ? relativePath : undefined
|
|
138
|
+
if (testRootDir && testRootDir !== rootDir) {
|
|
139
|
+
fallbackRelativePath = getTestSuitePath(test.path, testRootDir)
|
|
140
|
+
if (skippedSuite === undefined && normalizedSkippableSuites.has(fallbackRelativePath)) {
|
|
141
|
+
skippedSuite = fallbackRelativePath
|
|
142
|
+
}
|
|
143
|
+
}
|
|
135
144
|
if (isMarkedAsUnskippable(test)) {
|
|
136
145
|
suitesToRun.push(test)
|
|
137
146
|
unskippableSuites[relativePath] = true
|
|
138
|
-
if (
|
|
147
|
+
if (fallbackRelativePath !== undefined) {
|
|
148
|
+
unskippableSuites[fallbackRelativePath] = true
|
|
149
|
+
}
|
|
150
|
+
if (skippedSuite !== undefined) {
|
|
139
151
|
forcedToRunSuites[relativePath] = true
|
|
152
|
+
if (fallbackRelativePath !== undefined) {
|
|
153
|
+
forcedToRunSuites[fallbackRelativePath] = true
|
|
154
|
+
}
|
|
140
155
|
}
|
|
141
156
|
continue
|
|
142
157
|
}
|
|
143
|
-
if (
|
|
144
|
-
skippedSuites.push(relativePath)
|
|
145
|
-
} else {
|
|
158
|
+
if (skippedSuite === undefined) {
|
|
146
159
|
suitesToRun.push(test)
|
|
160
|
+
} else {
|
|
161
|
+
skippedSuites.push(skippedSuite)
|
|
147
162
|
}
|
|
148
163
|
}
|
|
149
164
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { getSegment } = require('../../../dd-trace/src/util')
|
|
3
4
|
const LangChainHandler = require('./default')
|
|
4
5
|
|
|
5
6
|
class LangChainEmbeddingHandler extends LangChainHandler {
|
|
6
7
|
extractProvider (instance) {
|
|
7
|
-
return instance.constructor.name
|
|
8
|
+
return getSegment(instance.constructor.name, 'Embeddings', 0).toLowerCase()
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
extractModel (instance) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { getSegment } = require('../../../dd-trace/src/util')
|
|
3
4
|
const LangChainHandler = require('./default')
|
|
4
5
|
|
|
5
6
|
class LangChainLanguageModelHandler extends LangChainHandler {
|
|
6
7
|
extractProvider (instance) {
|
|
7
|
-
return typeof instance._llmType === 'function' && instance._llmType()
|
|
8
|
+
return typeof instance._llmType === 'function' && getSegment(instance._llmType(), '-', 0)
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
extractModel (instance) {
|
|
@@ -15,10 +15,10 @@ function getTokensFromLlmOutput (result) {
|
|
|
15
15
|
for (const tokenNames of [['input', 'prompt'], ['output', 'completion'], ['total']]) {
|
|
16
16
|
let token = 0
|
|
17
17
|
for (const tokenName of tokenNames) {
|
|
18
|
-
const
|
|
18
|
+
const underscore = `${tokenName}_tokens`
|
|
19
19
|
const camelCase = `${tokenName}Tokens`
|
|
20
20
|
|
|
21
|
-
token = tokenUsage[
|
|
21
|
+
token = tokenUsage[underscore] || tokenUsage[camelCase] || token
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
tokens[tokenNames[0]] = token
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { basename } = require('node:path')
|
|
4
|
+
|
|
3
5
|
const { storage } = require('../../datadog-core')
|
|
4
6
|
const id = require('../../dd-trace/src/id')
|
|
5
7
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
8
|
+
const getConfig = require('../../dd-trace/src/config')
|
|
9
|
+
const {
|
|
10
|
+
SCREENSHOT_UPLOAD_RESULT_ERROR,
|
|
11
|
+
SCREENSHOT_UPLOAD_RESULT_UPLOADED,
|
|
12
|
+
getScreenshotCapturedAtMs,
|
|
13
|
+
getScreenshotUploadResult,
|
|
14
|
+
getScreenshotUploadTag,
|
|
15
|
+
} = require('../../dd-trace/src/ci-visibility/test-screenshot')
|
|
6
16
|
|
|
7
17
|
const {
|
|
8
18
|
finishAllTraceSpans,
|
|
9
19
|
getTestSuiteCommonTags,
|
|
10
20
|
getTestSuitePath,
|
|
11
21
|
isModifiedTest,
|
|
22
|
+
setRumTestCorrelation,
|
|
12
23
|
TEST_BROWSER_NAME,
|
|
13
|
-
TEST_BROWSER_VERSION,
|
|
14
24
|
TEST_CODE_OWNERS,
|
|
15
25
|
TEST_EARLY_FLAKE_ABORT_REASON,
|
|
16
26
|
TEST_EARLY_FLAKE_ENABLED,
|
|
@@ -51,6 +61,21 @@ const {
|
|
|
51
61
|
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
|
|
52
62
|
const log = require('../../dd-trace/src/log')
|
|
53
63
|
|
|
64
|
+
const PLAYWRIGHT_FAILURE_SCREENSHOT_RE = /^test-failed-\d+\.png$/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns whether an attachment is an automatic Playwright failure screenshot.
|
|
68
|
+
*
|
|
69
|
+
* @param {object} attachment - Playwright test attachment
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
72
|
+
function isPlaywrightFailureScreenshot (attachment) {
|
|
73
|
+
return attachment?.name === 'screenshot' &&
|
|
74
|
+
attachment.contentType === 'image/png' &&
|
|
75
|
+
typeof attachment.path === 'string' &&
|
|
76
|
+
PLAYWRIGHT_FAILURE_SCREENSHOT_RE.test(basename(attachment.path))
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
class PlaywrightPlugin extends CiPlugin {
|
|
55
80
|
static id = 'playwright'
|
|
56
81
|
|
|
@@ -60,6 +85,8 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
60
85
|
this._testSuiteSpansByTestSuiteAbsolutePath = new Map()
|
|
61
86
|
this.numFailedTests = 0
|
|
62
87
|
this.numFailedSuites = 0
|
|
88
|
+
this.pendingTestFinishes = 0
|
|
89
|
+
this.finishSession = undefined
|
|
63
90
|
|
|
64
91
|
this.addSub('ci:playwright:test:is-modified', ({
|
|
65
92
|
filePath,
|
|
@@ -71,6 +98,30 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
71
98
|
onDone(isModified)
|
|
72
99
|
})
|
|
73
100
|
|
|
101
|
+
this.addSub('ci:playwright:session:start', ({ isFailureScreenshotEnabled }) => {
|
|
102
|
+
if (!getConfig().testOptimization.DD_TEST_FAILURE_SCREENSHOTS_ENABLED) return
|
|
103
|
+
|
|
104
|
+
if (!isFailureScreenshotEnabled) {
|
|
105
|
+
log.warn(
|
|
106
|
+
'%s %s',
|
|
107
|
+
'DD_TEST_FAILURE_SCREENSHOTS_ENABLED is true, but Playwright screenshot capture is disabled.',
|
|
108
|
+
'Set Playwright use.screenshot to "only-on-failure", "on-first-failure", or "on".'
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
this.addSub('ci:playwright:session:configuration', ({ isFailureScreenshotEnabled }) => {
|
|
114
|
+
if (!getConfig().testOptimization.DD_TEST_FAILURE_SCREENSHOTS_ENABLED || !isFailureScreenshotEnabled) return
|
|
115
|
+
|
|
116
|
+
if (!this.tracer._exporter?.canUploadTestScreenshots?.()) {
|
|
117
|
+
log.warn(
|
|
118
|
+
'%s %s',
|
|
119
|
+
'DD_TEST_FAILURE_SCREENSHOTS_ENABLED is true, but Playwright screenshot upload is not supported',
|
|
120
|
+
'by the active Test Optimization transport.'
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
74
125
|
this.addSub('ci:playwright:session:finish', ({
|
|
75
126
|
status,
|
|
76
127
|
isEarlyFlakeDetectionEnabled,
|
|
@@ -78,42 +129,51 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
78
129
|
isTestManagementTestsEnabled,
|
|
79
130
|
onDone,
|
|
80
131
|
}) => {
|
|
81
|
-
|
|
82
|
-
|
|
132
|
+
const finishSession = () => {
|
|
133
|
+
this.testModuleSpan.setTag(TEST_STATUS, status)
|
|
134
|
+
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
83
135
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
136
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
137
|
+
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
|
|
138
|
+
}
|
|
139
|
+
if (isEarlyFlakeDetectionFaulty) {
|
|
140
|
+
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
|
|
141
|
+
}
|
|
142
|
+
if (status === 'fail' && this.numFailedSuites > 0) {
|
|
143
|
+
let errorMessage = `Test suites failed: ${this.numFailedSuites}.`
|
|
144
|
+
if (this.numFailedTests > 0) {
|
|
145
|
+
errorMessage += ` Tests failed: ${this.numFailedTests}`
|
|
146
|
+
}
|
|
147
|
+
const error = new Error(errorMessage)
|
|
148
|
+
this.testModuleSpan.setTag('error', error)
|
|
149
|
+
this.testSessionSpan.setTag('error', error)
|
|
94
150
|
}
|
|
95
|
-
const error = new Error(errorMessage)
|
|
96
|
-
this.testModuleSpan.setTag('error', error)
|
|
97
|
-
this.testSessionSpan.setTag('error', error)
|
|
98
|
-
}
|
|
99
151
|
|
|
100
|
-
|
|
101
|
-
|
|
152
|
+
if (isTestManagementTestsEnabled) {
|
|
153
|
+
this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.testModuleSpan.finish()
|
|
157
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
158
|
+
this.testSessionSpan.finish()
|
|
159
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
160
|
+
finishAllTraceSpans(this.testSessionSpan)
|
|
161
|
+
this.telemetry.count(TELEMETRY_TEST_SESSION, {
|
|
162
|
+
provider: this.ciProviderName,
|
|
163
|
+
autoInjected: !!this._tracerConfig.testOptimization.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
164
|
+
})
|
|
165
|
+
appClosingTelemetry()
|
|
166
|
+
this.tracer._exporter.flush(onDone)
|
|
167
|
+
this.numFailedTests = 0
|
|
168
|
+
this.numFailedSuites = 0
|
|
169
|
+
this.finishSession = undefined
|
|
102
170
|
}
|
|
103
171
|
|
|
104
|
-
this.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.telemetry.count(TELEMETRY_TEST_SESSION, {
|
|
110
|
-
provider: this.ciProviderName,
|
|
111
|
-
autoInjected: !!this._tracerConfig.testOptimization.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
112
|
-
})
|
|
113
|
-
appClosingTelemetry()
|
|
114
|
-
this.tracer._exporter.flush(onDone)
|
|
115
|
-
this.numFailedTests = 0
|
|
116
|
-
this.numFailedSuites = 0
|
|
172
|
+
if (this.pendingTestFinishes > 0) {
|
|
173
|
+
this.finishSession = finishSession
|
|
174
|
+
} else {
|
|
175
|
+
finishSession()
|
|
176
|
+
}
|
|
117
177
|
})
|
|
118
178
|
|
|
119
179
|
this.addBind('ci:playwright:test-suite:start', (ctx) => {
|
|
@@ -178,42 +238,17 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
178
238
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
179
239
|
})
|
|
180
240
|
|
|
181
|
-
this.addSub('ci:playwright:test:page-goto', ({
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}) => {
|
|
185
|
-
const store = storage('legacy').getStore()
|
|
186
|
-
const span = store && store.span
|
|
187
|
-
if (!span) {
|
|
241
|
+
this.addSub('ci:playwright:test:page-goto', (ctx) => {
|
|
242
|
+
const activeSpan = storage('legacy').getStore()?.span
|
|
243
|
+
if (!setRumTestCorrelation(ctx, activeSpan)) {
|
|
188
244
|
log.error('ci:playwright:test:page-goto: test span not found')
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (isRumActive) {
|
|
193
|
-
span.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
194
|
-
|
|
195
|
-
if (page) {
|
|
196
|
-
const browserVersion = page.context().browser().version()
|
|
197
|
-
|
|
198
|
-
if (browserVersion) {
|
|
199
|
-
span.setTag(TEST_BROWSER_VERSION, browserVersion)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const url = page.url()
|
|
203
|
-
const domain = new URL(url).hostname
|
|
204
|
-
page.context().addCookies([{
|
|
205
|
-
name: 'datadog-ci-visibility-test-execution-id',
|
|
206
|
-
value: span.context().toTraceId(),
|
|
207
|
-
domain,
|
|
208
|
-
path: '/',
|
|
209
|
-
}])
|
|
210
|
-
}
|
|
211
245
|
}
|
|
212
246
|
})
|
|
213
247
|
|
|
214
|
-
this.addSub('ci:playwright:worker:report', (serializedTraces) => {
|
|
248
|
+
this.addSub('ci:playwright:worker:report', ({ serializedTraces, screenshots }) => {
|
|
215
249
|
const traces = JSON.parse(serializedTraces)
|
|
216
250
|
const formattedTraces = []
|
|
251
|
+
let formattedTestSpan
|
|
217
252
|
|
|
218
253
|
for (const trace of traces) {
|
|
219
254
|
const formattedTrace = []
|
|
@@ -228,6 +263,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
228
263
|
formattedSpan.meta[TEST_HAS_DYNAMIC_NAME] = 'true'
|
|
229
264
|
}
|
|
230
265
|
if (span.name === 'playwright.test') {
|
|
266
|
+
formattedTestSpan = formattedSpan
|
|
231
267
|
// TODO: remove this comment
|
|
232
268
|
// TODO: Let's pass rootDir, repositoryRoot, command, session id and module id as env vars
|
|
233
269
|
// so we don't need this re-serialization logic. This can be passed just once, since they're unique
|
|
@@ -262,9 +298,36 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
262
298
|
formattedTraces.push(formattedTrace)
|
|
263
299
|
}
|
|
264
300
|
|
|
265
|
-
|
|
266
|
-
|
|
301
|
+
const exportTraces = () => {
|
|
302
|
+
for (const trace of formattedTraces) {
|
|
303
|
+
this.tracer._exporter.export(trace)
|
|
304
|
+
}
|
|
267
305
|
}
|
|
306
|
+
|
|
307
|
+
if (!formattedTestSpan || !screenshots) {
|
|
308
|
+
exportTraces()
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
this.pendingTestFinishes++
|
|
313
|
+
const uploadStarted = this.uploadTestScreenshots({
|
|
314
|
+
screenshots,
|
|
315
|
+
traceId: formattedTestSpan.trace_id.toString(10),
|
|
316
|
+
}, (screenshotUploadResult) => {
|
|
317
|
+
const screenshotUploadTag = getScreenshotUploadTag(screenshotUploadResult)
|
|
318
|
+
if (screenshotUploadTag) {
|
|
319
|
+
formattedTestSpan.meta[screenshotUploadTag] = 'true'
|
|
320
|
+
}
|
|
321
|
+
exportTraces()
|
|
322
|
+
this.pendingTestFinishes--
|
|
323
|
+
if (this.pendingTestFinishes === 0 && this.finishSession) {
|
|
324
|
+
this.finishSession()
|
|
325
|
+
}
|
|
326
|
+
})
|
|
327
|
+
if (uploadStarted) return
|
|
328
|
+
|
|
329
|
+
this.pendingTestFinishes--
|
|
330
|
+
exportTraces()
|
|
268
331
|
})
|
|
269
332
|
|
|
270
333
|
this.addBind('ci:playwright:test:start', (ctx) => {
|
|
@@ -480,6 +543,56 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
480
543
|
})
|
|
481
544
|
}
|
|
482
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Uploads automatic failure screenshots for a Playwright test attempt.
|
|
548
|
+
*
|
|
549
|
+
* @param {object} options - Upload options
|
|
550
|
+
* @param {Array<object>} options.screenshots - Playwright test attachments
|
|
551
|
+
* @param {string} options.traceId - Test trace id used as the screenshot key
|
|
552
|
+
* @param {(result: string|undefined) => void} onDone - Completion callback
|
|
553
|
+
* @returns {boolean} Whether at least one upload was started
|
|
554
|
+
*/
|
|
555
|
+
uploadTestScreenshots ({ screenshots, traceId }, onDone) {
|
|
556
|
+
const exporter = this.tracer?._exporter
|
|
557
|
+
if (!Array.isArray(screenshots) || !screenshots.length ||
|
|
558
|
+
!exporter?.canUploadTestScreenshots?.() ||
|
|
559
|
+
!exporter.uploadTestScreenshot) {
|
|
560
|
+
return false
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const screenshotPaths = new Set()
|
|
564
|
+
for (const screenshot of screenshots) {
|
|
565
|
+
if (isPlaywrightFailureScreenshot(screenshot)) {
|
|
566
|
+
screenshotPaths.add(screenshot.path)
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (!screenshotPaths.size) return false
|
|
570
|
+
|
|
571
|
+
const uploadResults = new Array(screenshotPaths.size)
|
|
572
|
+
let pendingUploads = screenshotPaths.size
|
|
573
|
+
let index = 0
|
|
574
|
+
for (const filePath of screenshotPaths) {
|
|
575
|
+
const resultIndex = index++
|
|
576
|
+
exporter.uploadTestScreenshot({
|
|
577
|
+
filePath,
|
|
578
|
+
traceId,
|
|
579
|
+
idempotencyKey: `${traceId}:${basename(filePath)}`,
|
|
580
|
+
capturedAtMs: getScreenshotCapturedAtMs(filePath, filePath),
|
|
581
|
+
}, (error, uploaded = true) => {
|
|
582
|
+
if (uploaded) {
|
|
583
|
+
uploadResults[resultIndex] = error
|
|
584
|
+
? SCREENSHOT_UPLOAD_RESULT_ERROR
|
|
585
|
+
: SCREENSHOT_UPLOAD_RESULT_UPLOADED
|
|
586
|
+
}
|
|
587
|
+
pendingUploads--
|
|
588
|
+
if (pendingUploads === 0) {
|
|
589
|
+
onDone(getScreenshotUploadResult(uploadResults))
|
|
590
|
+
}
|
|
591
|
+
})
|
|
592
|
+
}
|
|
593
|
+
return true
|
|
594
|
+
}
|
|
595
|
+
|
|
483
596
|
// TODO: this runs both in worker and main process (main process: skipped tests that do not go through _runTest)
|
|
484
597
|
startTestSpan (
|
|
485
598
|
testName,
|
|
@@ -24,7 +24,7 @@ class RouterPlugin extends WebPlugin {
|
|
|
24
24
|
let childOf
|
|
25
25
|
if (context !== undefined) {
|
|
26
26
|
const middleware = context.middleware
|
|
27
|
-
childOf = middleware.length === 0 ? context.span : middleware
|
|
27
|
+
childOf = middleware.length === 0 ? context.span : middleware.at(-1)
|
|
28
28
|
} else if (store) {
|
|
29
29
|
childOf = store.span
|
|
30
30
|
}
|
|
@@ -75,12 +75,21 @@ class RouterPlugin extends WebPlugin {
|
|
|
75
75
|
const context = this.#contexts.get(req)
|
|
76
76
|
if (!context) return
|
|
77
77
|
const middleware = context.middleware
|
|
78
|
-
const span = middleware.length === 0 ? context.span : middleware
|
|
78
|
+
const span = middleware.length === 0 ? context.span : middleware.at(-1)
|
|
79
79
|
if (!span) return
|
|
80
80
|
|
|
81
81
|
span.setTag('error', error)
|
|
82
82
|
})
|
|
83
83
|
|
|
84
|
+
this.addSub(`apm:${this.constructor.id}:middleware:repeat`, ({ req, name, error }) => {
|
|
85
|
+
// The middleware span already finished on the first `next`, so record the
|
|
86
|
+
// repeat on the still-live request span instead of a finished one.
|
|
87
|
+
web.root(req)?.addEvent('middleware.next_called_again', {
|
|
88
|
+
'middleware.name': name || '<anonymous>',
|
|
89
|
+
with_error: Boolean(error && error !== 'route' && error !== 'router'),
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
84
93
|
this.addSub('apm:http:server:request:finish', ({ req }) => {
|
|
85
94
|
const context = this.#contexts.get(req)
|
|
86
95
|
|
|
@@ -4,27 +4,12 @@ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
|
-
|
|
7
|
+
setRumTestCorrelation,
|
|
8
8
|
TEST_BROWSER_DRIVER,
|
|
9
9
|
TEST_BROWSER_DRIVER_VERSION,
|
|
10
10
|
TEST_BROWSER_NAME,
|
|
11
|
-
TEST_BROWSER_VERSION,
|
|
12
11
|
TEST_TYPE,
|
|
13
12
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
14
|
-
const { SPAN_TYPE } = require('../../../ext/tags')
|
|
15
|
-
|
|
16
|
-
function isTestSpan (span) {
|
|
17
|
-
return span.context().getTag(SPAN_TYPE) === 'test'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function getTestSpanFromTrace (trace) {
|
|
21
|
-
for (const span of trace.started) {
|
|
22
|
-
if (isTestSpan(span)) {
|
|
23
|
-
return span
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return null
|
|
27
|
-
}
|
|
28
13
|
|
|
29
14
|
class SeleniumPlugin extends CiPlugin {
|
|
30
15
|
static id = 'selenium'
|
|
@@ -32,32 +17,16 @@ class SeleniumPlugin extends CiPlugin {
|
|
|
32
17
|
constructor (...args) {
|
|
33
18
|
super(...args)
|
|
34
19
|
|
|
35
|
-
this.addSub('ci:selenium:driver:get', ({
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
browserVersion,
|
|
40
|
-
isRumActive,
|
|
41
|
-
}) => {
|
|
42
|
-
const store = storage('legacy').getStore()
|
|
43
|
-
const span = store?.span
|
|
44
|
-
if (!span) {
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
const testSpan = isTestSpan(span) ? span : getTestSpanFromTrace(span.context()._trace)
|
|
20
|
+
this.addSub('ci:selenium:driver:get', (ctx) => {
|
|
21
|
+
const { seleniumVersion, browserName } = ctx
|
|
22
|
+
const activeSpan = storage('legacy').getStore()?.span
|
|
23
|
+
const testSpan = setRumTestCorrelation(ctx, activeSpan)
|
|
48
24
|
if (!testSpan) {
|
|
49
25
|
return
|
|
50
26
|
}
|
|
51
|
-
if (setTraceId) {
|
|
52
|
-
setTraceId(testSpan.context().toTraceId())
|
|
53
|
-
}
|
|
54
|
-
if (isRumActive) {
|
|
55
|
-
testSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
56
|
-
}
|
|
57
27
|
testSpan.setTag(TEST_BROWSER_DRIVER, 'selenium')
|
|
58
28
|
testSpan.setTag(TEST_BROWSER_DRIVER_VERSION, seleniumVersion)
|
|
59
29
|
testSpan.setTag(TEST_BROWSER_NAME, browserName)
|
|
60
|
-
testSpan.setTag(TEST_BROWSER_VERSION, browserVersion)
|
|
61
30
|
testSpan.setTag(TEST_TYPE, 'browser')
|
|
62
31
|
})
|
|
63
32
|
}
|
|
@@ -264,8 +264,10 @@ class VitestPlugin extends CiPlugin {
|
|
|
264
264
|
span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
|
|
265
265
|
}
|
|
266
266
|
const finish = () => {
|
|
267
|
-
if (duration) {
|
|
268
|
-
span.finish(
|
|
267
|
+
if (Number.isFinite(duration) && duration >= 0) {
|
|
268
|
+
span.finish(
|
|
269
|
+
span._startTime + Math.max(duration - MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION, 0)
|
|
270
|
+
) // milliseconds
|
|
269
271
|
} else {
|
|
270
272
|
span.finish() // `duration` is empty for retries, so we'll use clock time
|
|
271
273
|
}
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
SPAN_POINTER_DIRECTION,
|
|
7
7
|
SPAN_POINTER_DIRECTION_NAME,
|
|
8
8
|
} = require('../../dd-trace/src/constants')
|
|
9
|
+
const { getSegment } = require('../../dd-trace/src/util')
|
|
9
10
|
const {
|
|
10
11
|
incrementWebSocketCounter,
|
|
11
12
|
buildWebSocketSpanPointerHash,
|
|
@@ -29,7 +30,7 @@ class WSClosePlugin extends TracingPlugin {
|
|
|
29
30
|
|
|
30
31
|
const spanKind = isPeerClose ? 'consumer' : 'producer'
|
|
31
32
|
const spanTags = socket.spanTags
|
|
32
|
-
const path = spanTags['resource.name']
|
|
33
|
+
const path = getSegment(spanTags['resource.name'], ' ', 1)
|
|
33
34
|
const service = this.serviceName({ pluginConfig: this.config })
|
|
34
35
|
const span = this.startSpan(this.operationName(), {
|
|
35
36
|
service,
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
SPAN_POINTER_DIRECTION,
|
|
7
7
|
SPAN_POINTER_DIRECTION_NAME,
|
|
8
8
|
} = require('../../dd-trace/src/constants')
|
|
9
|
+
const { getSegment } = require('../../dd-trace/src/util')
|
|
9
10
|
const {
|
|
10
11
|
incrementWebSocketCounter,
|
|
11
12
|
buildWebSocketSpanPointerHash,
|
|
@@ -23,7 +24,7 @@ class WSProducerPlugin extends TracingPlugin {
|
|
|
23
24
|
if (!socket.spanContext) return
|
|
24
25
|
|
|
25
26
|
const spanTags = socket.spanTags
|
|
26
|
-
const path = spanTags['resource.name']
|
|
27
|
+
const path = getSegment(spanTags['resource.name'], ' ', 1)
|
|
27
28
|
const opCode = binary ? 'binary' : 'text'
|
|
28
29
|
const service = this.serviceName({ pluginConfig: this.config })
|
|
29
30
|
const span = this.startSpan(this.operationName(), {
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
SPAN_POINTER_DIRECTION,
|
|
7
7
|
SPAN_POINTER_DIRECTION_NAME,
|
|
8
8
|
} = require('../../dd-trace/src/constants')
|
|
9
|
+
const { getSegment } = require('../../dd-trace/src/util')
|
|
9
10
|
const {
|
|
10
11
|
incrementWebSocketCounter,
|
|
11
12
|
buildWebSocketSpanPointerHash,
|
|
@@ -28,7 +29,7 @@ class WSReceiverPlugin extends TracingPlugin {
|
|
|
28
29
|
if (!socket.spanContext) return
|
|
29
30
|
|
|
30
31
|
const spanTags = socket.spanTags
|
|
31
|
-
const path = spanTags['resource.name']
|
|
32
|
+
const path = getSegment(spanTags['resource.name'], ' ', 1)
|
|
32
33
|
const opCode = binary ? 'binary' : 'text'
|
|
33
34
|
|
|
34
35
|
const service = this.serviceName({ pluginConfig: this.config })
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const TracingPlugin = require('../../dd-trace/src/plugins/tracing.js')
|
|
4
4
|
const tags = require('../../../ext/tags.js')
|
|
5
5
|
const { HTTP_HEADERS } = require('../../../ext/formats')
|
|
6
|
+
const { getSegment } = require('../../dd-trace/src/util')
|
|
6
7
|
const {
|
|
7
8
|
createWebSocketSpanContext,
|
|
8
9
|
hasTraceHeaders,
|
|
@@ -94,7 +95,7 @@ function getRequestProtocol (req, fallback = 'ws') {
|
|
|
94
95
|
|
|
95
96
|
// 2. Check for a trusted header set by a proxy
|
|
96
97
|
if (req.headers && req.headers['x-forwarded-proto']) {
|
|
97
|
-
const proto = req.headers['x-forwarded-proto']
|
|
98
|
+
const proto = getSegment(req.headers['x-forwarded-proto'], ',', 0).trim()
|
|
98
99
|
if (proto === 'https') return 'wss'
|
|
99
100
|
if (proto === 'http') return 'ws'
|
|
100
101
|
}
|
|
@@ -1,39 +1,4 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// Set up beforeExitHandlers before loading the tracer so that modules loaded
|
|
7
|
-
// during require('./src') can register handlers.
|
|
8
|
-
Object.defineProperty(globalThis, ddTraceSymbol, {
|
|
9
|
-
value: {
|
|
10
|
-
beforeExitHandlers: new Set(),
|
|
11
|
-
},
|
|
12
|
-
enumerable: false,
|
|
13
|
-
configurable: true,
|
|
14
|
-
writable: false,
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
process.once('beforeExit', function mainBeforeExit () {
|
|
18
|
-
if (globalThis[ddTraceSymbol]?.beforeExitHandlers) {
|
|
19
|
-
for (const handler of globalThis[ddTraceSymbol].beforeExitHandlers) {
|
|
20
|
-
handler()
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const TracerProxy = require('./src')
|
|
26
|
-
|
|
27
|
-
Object.defineProperty(global, '_ddtrace', {
|
|
28
|
-
value: new TracerProxy(),
|
|
29
|
-
enumerable: false,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = global._ddtrace
|
|
36
|
-
// Static aliases so cjs-module-lexer surfaces them as ESM named exports
|
|
37
|
-
// (`import { tracer } from 'dd-trace'`).
|
|
38
|
-
module.exports.tracer = global._ddtrace
|
|
39
|
-
module.exports.default = global._ddtrace
|
|
3
|
+
require('./src/openfeature/register')
|
|
4
|
+
module.exports = require('./src/bootstrap')
|
|
@@ -230,7 +230,7 @@ class AIGuard extends NoopAIGuard {
|
|
|
230
230
|
// still applies for SDK callers that don't supply an explicit parent.
|
|
231
231
|
const traceOpts = childOf ? { childOf } : {}
|
|
232
232
|
return this.#tracer.trace(TAGS.RESOURCE, traceOpts, async (span) => {
|
|
233
|
-
const last = messages
|
|
233
|
+
const last = messages.at(-1)
|
|
234
234
|
const target = this.#isToolCall(last) ? 'tool' : 'prompt'
|
|
235
235
|
span.setTag(TAGS.TARGET_TAG_KEY, target)
|
|
236
236
|
if (target === 'tool') {
|
|
@@ -190,7 +190,7 @@ class TaintTrackingPlugin extends SourceIastPlugin {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
addURLParsingSubscriptions () {
|
|
193
|
-
const urlResultTaintedProperties = ['host', 'origin', 'hostname']
|
|
193
|
+
const urlResultTaintedProperties = new Set(['host', 'origin', 'hostname'])
|
|
194
194
|
this.addSub(
|
|
195
195
|
{ channelName: 'datadog:url:parse:finish' },
|
|
196
196
|
({ input, base, parsed, isURL }) => {
|
|
@@ -212,7 +212,7 @@ class TaintTrackingPlugin extends SourceIastPlugin {
|
|
|
212
212
|
this.addSub(
|
|
213
213
|
{ channelName: 'datadog:url:getter:finish' },
|
|
214
214
|
(context) => {
|
|
215
|
-
if (!urlResultTaintedProperties.
|
|
215
|
+
if (!urlResultTaintedProperties.has(context.property)) return
|
|
216
216
|
|
|
217
217
|
const origRange = this._taintedURLs.get(context.urlObject)
|
|
218
218
|
if (!origRange) return
|