dd-trace 5.109.0 → 5.111.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 +13 -8
- package/ci/init.js +25 -5
- package/ci/vitest-no-worker-init-setup.mjs +430 -0
- package/ext/tags.js +2 -0
- package/index.d.ts +79 -24
- package/initialize.mjs +5 -6
- package/loader-hook.mjs +154 -47
- package/package.json +20 -16
- package/packages/datadog-esbuild/index.js +26 -0
- package/packages/datadog-esbuild/src/utils.js +46 -3
- package/packages/datadog-instrumentations/src/connect.js +4 -3
- package/packages/datadog-instrumentations/src/fastify.js +4 -12
- package/packages/datadog-instrumentations/src/fs.js +8 -6
- package/packages/datadog-instrumentations/src/graphql.js +26 -484
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +81 -8
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -2
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +65 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +6 -4
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +17 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +201 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +18 -2
- package/packages/datadog-instrumentations/src/koa.js +3 -2
- package/packages/datadog-instrumentations/src/mariadb.js +4 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +14 -2
- package/packages/datadog-instrumentations/src/next.js +10 -10
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +7 -6
- package/packages/datadog-instrumentations/src/playwright.js +1 -1
- package/packages/datadog-instrumentations/src/restify.js +4 -3
- package/packages/datadog-instrumentations/src/router.js +18 -5
- package/packages/datadog-instrumentations/src/selenium.js +1 -2
- package/packages/datadog-instrumentations/src/tedious.js +28 -0
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +1293 -0
- package/packages/datadog-instrumentations/src/vitest-main.js +1567 -0
- package/packages/datadog-instrumentations/src/vitest-util.js +249 -0
- package/packages/datadog-instrumentations/src/vitest-worker.js +753 -0
- package/packages/datadog-instrumentations/src/vitest.js +11 -1598
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/client.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +18 -10
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +47 -11
- package/packages/datadog-plugin-aws-sdk/src/base.js +13 -9
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +43 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +83 -91
- package/packages/datadog-plugin-cucumber/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +19 -5
- package/packages/datadog-plugin-cypress/src/support.js +45 -1
- package/packages/datadog-plugin-express/src/code_origin.js +1 -1
- package/packages/datadog-plugin-fastify/src/code_origin.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +627 -11
- package/packages/datadog-plugin-graphql/src/index.js +20 -8
- package/packages/datadog-plugin-graphql/src/parse.js +24 -4
- package/packages/datadog-plugin-graphql/src/validate.js +16 -5
- package/packages/datadog-plugin-http/src/client.js +8 -3
- package/packages/datadog-plugin-http/src/index.js +6 -8
- package/packages/datadog-plugin-http2/src/client.js +5 -2
- package/packages/datadog-plugin-jest/src/index.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +1 -1
- package/packages/datadog-plugin-mysql/src/index.js +7 -2
- package/packages/datadog-plugin-openai/src/services.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +2 -2
- package/packages/datadog-plugin-undici/src/index.js +5 -2
- package/packages/datadog-plugin-vitest/src/index.js +76 -64
- package/packages/datadog-shimmer/src/shimmer.js +37 -16
- package/packages/datadog-webpack/index.js +17 -1
- package/packages/datadog-webpack/src/optional-peer-loader.js +17 -0
- package/packages/dd-trace/src/aiguard/sdk.js +15 -3
- package/packages/dd-trace/src/appsec/api_security/index.js +55 -0
- package/packages/dd-trace/src/appsec/api_security/sampler.js +147 -0
- package/packages/dd-trace/src/appsec/channels.js +3 -1
- package/packages/dd-trace/src/appsec/downstream_requests.js +4 -4
- package/packages/dd-trace/src/appsec/graphql.js +5 -5
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +26 -19
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/index.js +2 -1
- package/packages/dd-trace/src/appsec/index.js +20 -7
- package/packages/dd-trace/src/appsec/lambda.js +135 -0
- package/packages/dd-trace/src/appsec/reporter.js +50 -10
- package/packages/dd-trace/src/appsec/telemetry/api_security.js +34 -0
- package/packages/dd-trace/src/appsec/telemetry/index.js +27 -1
- package/packages/dd-trace/src/appsec/waf/index.js +16 -4
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +4 -4
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +21 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +3 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -13
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +17 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +47 -26
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +64 -53
- package/packages/dd-trace/src/ci-visibility/requests/request.js +1 -17
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +3 -3
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +23 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +128 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +287 -0
- package/packages/dd-trace/src/config/defaults.js +25 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +596 -58
- package/packages/dd-trace/src/config/helper.js +134 -33
- package/packages/dd-trace/src/config/index.js +39 -23
- package/packages/dd-trace/src/config/major-overrides.js +4 -2
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +109 -57
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/datastreams/processor.js +11 -3
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +47 -35
- package/packages/dd-trace/src/debugger/devtools_client/index.js +31 -66
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +83 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -0
- package/packages/dd-trace/src/debugger/index.js +5 -0
- package/packages/dd-trace/src/debugger/probe_sampler.js +112 -0
- package/packages/dd-trace/src/debugger/probe_sampler_constants.js +19 -0
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +77 -26
- package/packages/dd-trace/src/exporters/agent/index.js +1 -1
- package/packages/dd-trace/src/exporters/agentless/writer.js +4 -4
- package/packages/dd-trace/src/exporters/common/request.js +1 -20
- package/packages/dd-trace/src/exporters/common/url.js +34 -0
- package/packages/dd-trace/src/exporters/span-stats/writer.js +1 -3
- package/packages/dd-trace/src/guardrails/index.js +8 -5
- package/packages/dd-trace/src/index.js +6 -4
- package/packages/dd-trace/src/llmobs/constants/tags.js +6 -0
- package/packages/dd-trace/src/llmobs/index.js +17 -6
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -4
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +3 -3
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +8 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +5 -1
- package/packages/dd-trace/src/llmobs/tagger.js +58 -3
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
- package/packages/dd-trace/src/log/index.js +18 -20
- package/packages/dd-trace/src/openfeature/flagging_provider.js +2 -7
- package/packages/dd-trace/src/opentelemetry/bridge-span-base.js +5 -4
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +54 -5
- package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +2 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +40 -0
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +169 -0
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +4 -3
- package/packages/dd-trace/src/opentelemetry/metrics/time.js +19 -0
- package/packages/dd-trace/src/opentelemetry/otlp/common.proto +2 -2
- package/packages/dd-trace/src/opentelemetry/otlp/logs.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/logs_service.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/metrics.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/metrics_service.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +44 -38
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +29 -13
- package/packages/dd-trace/src/opentelemetry/span.js +14 -3
- package/packages/dd-trace/src/opentelemetry/span_context.js +1 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +3 -2
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +26 -13
- package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +3 -3
- package/packages/dd-trace/src/opentracing/span_context.js +17 -0
- package/packages/dd-trace/src/opentracing/tracer.js +6 -1
- package/packages/dd-trace/src/plugin_manager.js +14 -8
- package/packages/dd-trace/src/plugins/ci_plugin.js +21 -4
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +276 -0
- package/packages/dd-trace/src/plugins/util/llm.js +6 -1
- package/packages/dd-trace/src/plugins/util/test.js +91 -9
- package/packages/dd-trace/src/plugins/util/url.js +68 -1
- package/packages/dd-trace/src/plugins/util/web.js +19 -36
- package/packages/dd-trace/src/priority_sampler.js +1 -13
- package/packages/dd-trace/src/profiling/config.js +129 -198
- package/packages/dd-trace/src/profiling/constants.js +4 -7
- package/packages/dd-trace/src/profiling/exporter_cli.js +10 -10
- package/packages/dd-trace/src/profiling/exporters/agent.js +23 -16
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +45 -14
- package/packages/dd-trace/src/profiling/exporters/file.js +16 -5
- package/packages/dd-trace/src/profiling/oom.js +71 -0
- package/packages/dd-trace/src/profiling/profiler.js +35 -23
- package/packages/dd-trace/src/profiling/profilers/events.js +14 -7
- package/packages/dd-trace/src/profiling/profilers/space.js +27 -18
- package/packages/dd-trace/src/profiling/profilers/wall.js +35 -25
- package/packages/dd-trace/src/proxy.js +8 -8
- package/packages/dd-trace/src/ritm.js +4 -2
- package/packages/dd-trace/src/serverless.js +1 -2
- package/packages/dd-trace/src/service-naming/schemas/util.js +36 -5
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +5 -3
- package/packages/dd-trace/src/span_format.js +2 -1
- package/packages/dd-trace/src/span_processor.js +11 -6
- package/packages/dd-trace/src/span_stats.js +96 -78
- package/packages/dd-trace/src/startup-log.js +2 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +6 -4
- package/packages/dd-trace/src/telemetry/index.js +2 -2
- package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/telemetry/send-data.js +20 -18
- package/packages/dd-trace/src/telemetry/session-propagation.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +9 -9
- package/packages/dd-trace/src/tracer.js +15 -1
- package/packages/dd-trace/src/util.js +14 -0
- package/register.js +58 -1
- 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/pprof-format/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-plugin-graphql/src/resolve.js +0 -170
- package/packages/dd-trace/src/appsec/api_security_sampler.js +0 -117
|
@@ -43,9 +43,9 @@ class SchemaExtractor {
|
|
|
43
43
|
let type
|
|
44
44
|
let format
|
|
45
45
|
let enumValues
|
|
46
|
-
let description
|
|
47
46
|
let ref
|
|
48
47
|
|
|
48
|
+
const description = field.doc
|
|
49
49
|
const fieldType = field.type?.types ?? field.type?.typeName ?? field.type
|
|
50
50
|
|
|
51
51
|
if (Array.isArray(fieldType)) {
|
|
@@ -129,7 +129,7 @@ class SchemaExtractor {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
iterateOverSchema (builder) {
|
|
132
|
-
|
|
132
|
+
SchemaExtractor.extractSchema(this.schema, builder, 0)
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
static attachSchemaOnSpan (args, span, operation, tracer) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const ClientPlugin = require('../../dd-trace/src/plugins/client')
|
|
4
|
-
const { addOpMeta, unwrapDurableError } = require('./util')
|
|
4
|
+
const { addOpMeta, getStepDataForNext, unwrapDurableError } = require('./util')
|
|
5
5
|
|
|
6
6
|
class AwsDurableExecutionSdkJsClientPlugin extends ClientPlugin {
|
|
7
7
|
static id = 'aws-durable-execution-sdk-js'
|
|
@@ -29,7 +29,7 @@ class AwsDurableExecutionSdkJsClientPlugin extends ClientPlugin {
|
|
|
29
29
|
if (operationName) {
|
|
30
30
|
meta['aws.durable.operation_name'] = operationName
|
|
31
31
|
}
|
|
32
|
-
addOpMeta(meta, ctx.self)
|
|
32
|
+
addOpMeta(meta, getStepDataForNext(ctx.self))
|
|
33
33
|
|
|
34
34
|
this.startSpan(this.operationName(), {
|
|
35
35
|
resource: operationName,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { storage } = require('../../datadog-core')
|
|
4
4
|
const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
|
|
5
|
-
const { addOpMeta, unwrapDurableError } = require('./util')
|
|
5
|
+
const { addOpMeta, getOperationAttempt, getStepDataForNext, unwrapDurableError } = require('./util')
|
|
6
6
|
|
|
7
7
|
// Span names whose direct children must keep the default resource.
|
|
8
8
|
// These can have very high cardinality which is undesireable in the resource.
|
|
@@ -41,12 +41,18 @@ class BaseContextPlugin extends TracingPlugin {
|
|
|
41
41
|
if (operationName) {
|
|
42
42
|
meta['aws.durable.operation_name'] = operationName
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
const stepInfo = getStepDataForNext(ctx.self)
|
|
45
|
+
addOpMeta(meta, stepInfo)
|
|
46
|
+
|
|
47
|
+
const metrics = this.constructor.retryable
|
|
48
|
+
? { 'aws.durable.operation_attempt': getOperationAttempt(stepInfo.stepData) }
|
|
49
|
+
: undefined
|
|
45
50
|
|
|
46
51
|
this.startSpan(spanName, {
|
|
47
52
|
resource,
|
|
48
53
|
kind: this.constructor.kind,
|
|
49
54
|
meta,
|
|
55
|
+
metrics,
|
|
50
56
|
}, ctx)
|
|
51
57
|
|
|
52
58
|
return ctx.currentStore
|
|
@@ -71,11 +77,12 @@ class BaseContextPlugin extends TracingPlugin {
|
|
|
71
77
|
}
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
function makeContextPlugin (method, spanName) {
|
|
80
|
+
function makeContextPlugin (method, spanName, { retryable }) {
|
|
75
81
|
return class extends BaseContextPlugin {
|
|
76
82
|
static prefix = `tracing:orchestrion:@aws/durable-execution-sdk-js:DurableContextImpl_${method}`
|
|
77
83
|
static settleChannel = `apm:aws-durable-execution-sdk-js:${method}:settle`
|
|
78
84
|
static spanName = spanName
|
|
85
|
+
static retryable = retryable
|
|
79
86
|
}
|
|
80
87
|
}
|
|
81
88
|
|
|
@@ -83,6 +90,7 @@ class RunInChildContextPlugin extends BaseContextPlugin {
|
|
|
83
90
|
static prefix = 'tracing:orchestrion:@aws/durable-execution-sdk-js:DurableContextImpl_runInChildContext'
|
|
84
91
|
static settleChannel = 'apm:aws-durable-execution-sdk-js:runInChildContext:settle'
|
|
85
92
|
static spanName = 'aws.durable.child_context'
|
|
93
|
+
static retryable = false
|
|
86
94
|
|
|
87
95
|
bindStart (ctx) {
|
|
88
96
|
if (SUPPRESSED_CHILD_CONTEXT_SUBTYPES.has(getRunInChildContextSubType(ctx))) {
|
|
@@ -103,12 +111,12 @@ function getRunInChildContextSubType (ctx) {
|
|
|
103
111
|
}
|
|
104
112
|
|
|
105
113
|
module.exports = {
|
|
106
|
-
step: makeContextPlugin('step', 'aws.durable.step'),
|
|
107
|
-
wait: makeContextPlugin('wait', 'aws.durable.wait'),
|
|
108
|
-
waitForCondition: makeContextPlugin('waitForCondition', 'aws.durable.wait_for_condition'),
|
|
109
|
-
waitForCallback: makeContextPlugin('waitForCallback', 'aws.durable.wait_for_callback'),
|
|
110
|
-
createCallback: makeContextPlugin('createCallback', 'aws.durable.create_callback'),
|
|
111
|
-
map: makeContextPlugin('map', 'aws.durable.map'),
|
|
112
|
-
parallel: makeContextPlugin('parallel', 'aws.durable.parallel'),
|
|
114
|
+
step: makeContextPlugin('step', 'aws.durable.step', { retryable: true }),
|
|
115
|
+
wait: makeContextPlugin('wait', 'aws.durable.wait', { retryable: false }),
|
|
116
|
+
waitForCondition: makeContextPlugin('waitForCondition', 'aws.durable.wait_for_condition', { retryable: true }),
|
|
117
|
+
waitForCallback: makeContextPlugin('waitForCallback', 'aws.durable.wait_for_callback', { retryable: false }),
|
|
118
|
+
createCallback: makeContextPlugin('createCallback', 'aws.durable.create_callback', { retryable: false }),
|
|
119
|
+
map: makeContextPlugin('map', 'aws.durable.map', { retryable: false }),
|
|
120
|
+
parallel: makeContextPlugin('parallel', 'aws.durable.parallel', { retryable: false }),
|
|
113
121
|
runInChildContext: RunInChildContextPlugin,
|
|
114
122
|
}
|
|
@@ -2,27 +2,63 @@
|
|
|
2
2
|
|
|
3
3
|
const { createHash } = require('node:crypto')
|
|
4
4
|
|
|
5
|
+
// A checkpoint in one of these terminal states means the operation is served from the checkpoint
|
|
6
|
+
// on a replay rather than executed: the SDK reloads a SUCCEEDED result or re-raises a FAILED error
|
|
7
|
+
// without running the user function. Both also carry the 1-indexed attempt that reached the terminal
|
|
8
|
+
// state, so both need the same normalization to agree with the 0-indexed live run.
|
|
9
|
+
const REPLAYED_STATUSES = new Set(['SUCCEEDED', 'FAILED'])
|
|
10
|
+
|
|
5
11
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* be served from the SDK's checkpoint). `aws.durable.operation_id` — the 16-hex-char MD5 of
|
|
10
|
-
* the stepId, mirroring the SDK's internal calculation — is only added when a stepId exists.
|
|
11
|
-
* @param {Record<string, string>} meta - The span meta/tags object to populate.
|
|
12
|
+
* Resolves the SDK's next stepId and its checkpoint entry in a single pass, so one span start can
|
|
13
|
+
* feed both addOpMeta and getOperationAttempt without traversing the SDK internals twice. `stepData`
|
|
14
|
+
* is undefined when there is no next stepId, or no checkpoint entry exists for it yet.
|
|
12
15
|
* @param {object} [ctxImpl] - The DurableContextImpl about to run the op.
|
|
13
|
-
* @returns {
|
|
16
|
+
* @returns {{ stepId: string | undefined, stepData: object | undefined }}
|
|
14
17
|
*/
|
|
15
|
-
function
|
|
18
|
+
function getStepDataForNext (ctxImpl) {
|
|
16
19
|
const stepId = ctxImpl?.getNextStepId?.()
|
|
20
|
+
const stepData = stepId ? ctxImpl?._executionContext?.getStepData?.(stepId) : undefined
|
|
21
|
+
return { stepId, stepData }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Populates the replay and operation_id tags from a pre-resolved step lookup (see
|
|
26
|
+
* getStepDataForNext). `aws.durable.replayed` is always set ('true' when the next stepId already
|
|
27
|
+
* has a terminal checkpoint entry — SUCCEEDED or FAILED — i.e. the op will be served from the SDK's
|
|
28
|
+
* checkpoint rather than executed). `aws.durable.operation_id` — the 16-hex-char MD5 of the stepId,
|
|
29
|
+
* mirroring the SDK's internal calculation — is only added when a stepId exists.
|
|
30
|
+
* @param {Record<string, string>} meta - The span meta/tags object to populate.
|
|
31
|
+
* @param {{ stepId?: string, stepData?: object }} stepInfo - Resolved next stepId and checkpoint entry.
|
|
32
|
+
* @returns {void}
|
|
33
|
+
*/
|
|
34
|
+
function addOpMeta (meta, { stepId, stepData }) {
|
|
17
35
|
if (!stepId) {
|
|
18
36
|
meta['aws.durable.replayed'] = 'false'
|
|
19
37
|
return
|
|
20
38
|
}
|
|
21
|
-
|
|
22
|
-
meta['aws.durable.replayed'] = String(stepData?.Status === 'SUCCEEDED')
|
|
39
|
+
meta['aws.durable.replayed'] = String(REPLAYED_STATUSES.has(stepData?.Status))
|
|
23
40
|
meta['aws.durable.operation_id'] = createHash('md5').update(stepId).digest('hex').slice(0, 16)
|
|
24
41
|
}
|
|
25
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Returns the 0-indexed attempt number for the op (0 original, 1 first retry, …) from a pre-resolved
|
|
45
|
+
* checkpoint entry (see getStepDataForNext), defaulting to 0 before any checkpoint exists.
|
|
46
|
+
*
|
|
47
|
+
* StepDetails.Attempt is indexed differently depending on checkpoint status: on a pending/retry
|
|
48
|
+
* checkpoint it's the count of prior failed attempts (already 0-indexed), but on a terminal
|
|
49
|
+
* checkpoint read on replay (SUCCEEDED or FAILED) it's the 1-indexed attempt that reached that
|
|
50
|
+
* state. We subtract 1 in the terminal case so a replay agrees with the original run, flooring at
|
|
51
|
+
* 0 since the 1-indexing is observed server behavior, not an SDK guarantee.
|
|
52
|
+
*
|
|
53
|
+
* @param {object} [stepData] - The checkpoint entry for the next stepId.
|
|
54
|
+
* @returns {number}
|
|
55
|
+
*/
|
|
56
|
+
function getOperationAttempt (stepData) {
|
|
57
|
+
const attempt = stepData?.StepDetails?.Attempt
|
|
58
|
+
if (!Number.isFinite(attempt)) return 0
|
|
59
|
+
return REPLAYED_STATUSES.has(stepData.Status) ? Math.max(0, attempt - 1) : attempt
|
|
60
|
+
}
|
|
61
|
+
|
|
26
62
|
/**
|
|
27
63
|
* The SDK wraps user errors in typed classes (StepError, ChildContextError, etc.); we follow the
|
|
28
64
|
* `.cause` chain to recover the user's original Error. SDK wrappers expose a string `errorType`
|
|
@@ -40,4 +76,4 @@ function unwrapDurableError (ctx) {
|
|
|
40
76
|
return err
|
|
41
77
|
}
|
|
42
78
|
|
|
43
|
-
module.exports = { addOpMeta, unwrapDurableError }
|
|
79
|
+
module.exports = { addOpMeta, getOperationAttempt, getStepDataForNext, unwrapDurableError }
|
|
@@ -108,7 +108,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
108
108
|
const span = this.startSpan(this.operationFromRequest(request), {
|
|
109
109
|
childOf,
|
|
110
110
|
meta,
|
|
111
|
-
service: this.serviceName(),
|
|
111
|
+
service: this.serviceName(request),
|
|
112
112
|
integrationName: 'aws-sdk',
|
|
113
113
|
}, ctx)
|
|
114
114
|
|
|
@@ -216,14 +216,18 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
216
216
|
})
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
219
|
+
/**
|
|
220
|
+
* @param {{ params?: object }} request
|
|
221
|
+
*/
|
|
222
|
+
serviceName (request) {
|
|
223
|
+
return super.serviceName({
|
|
224
|
+
id: 'aws',
|
|
225
|
+
type: 'web',
|
|
226
|
+
kind: 'client',
|
|
227
|
+
awsService: this.serviceIdentifier,
|
|
228
|
+
pluginConfig: this.config,
|
|
229
|
+
params: request.params,
|
|
230
|
+
})
|
|
227
231
|
}
|
|
228
232
|
|
|
229
233
|
isEnabled (request) {
|
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
const log = require('../../../dd-trace/src/log')
|
|
3
3
|
const BaseAwsSdkPlugin = require('../base')
|
|
4
4
|
|
|
5
|
+
// EventBridge enforces this limit over the whole PutEvents request (the sum of
|
|
6
|
+
// every entry), not over a single entry. 1 MiB == 1,048,576 bytes.
|
|
7
|
+
const MAX_PUT_EVENTS_BYTES = 1024 * 1024
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Size a single `PutEventsRequestEntry` the way EventBridge does server-side:
|
|
11
|
+
* the UTF-8 byte length of `Source`, `DetailType`, `Detail`, and each
|
|
12
|
+
* `Resources` ARN, plus a flat 14 bytes when `Time` is set.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} entry a single PutEvents request entry
|
|
15
|
+
* @param {string} [detail] overrides `entry.Detail`, used to size the entry as
|
|
16
|
+
* it would be sent with the injected `_datadog` context
|
|
17
|
+
* @returns {number}
|
|
18
|
+
* @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevents.html
|
|
19
|
+
*/
|
|
20
|
+
function putEventEntrySize (entry, detail = entry.Detail) {
|
|
21
|
+
let size = entry.Time == null ? 0 : 14
|
|
22
|
+
if (entry.Source != null) size += Buffer.byteLength(entry.Source)
|
|
23
|
+
if (entry.DetailType != null) size += Buffer.byteLength(entry.DetailType)
|
|
24
|
+
if (detail != null) size += Buffer.byteLength(detail)
|
|
25
|
+
if (entry.Resources != null) {
|
|
26
|
+
for (const resource of entry.Resources) {
|
|
27
|
+
if (resource != null) size += Buffer.byteLength(resource)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return size
|
|
31
|
+
}
|
|
32
|
+
|
|
5
33
|
class EventBridge extends BaseAwsSdkPlugin {
|
|
6
34
|
static id = 'eventbridge'
|
|
7
35
|
static isPayloadReporter = true
|
|
@@ -25,7 +53,8 @@ class EventBridge extends BaseAwsSdkPlugin {
|
|
|
25
53
|
* Docs: https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEventsRequestEntry.html
|
|
26
54
|
* We cannot use the traceHeader field as that's reserved for X-Ray.
|
|
27
55
|
* Detail must be a valid JSON string
|
|
28
|
-
* Max
|
|
56
|
+
* Max PutEvents request size is 1mb, summed over all entries
|
|
57
|
+
* (https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevent-size.html)
|
|
29
58
|
*/
|
|
30
59
|
requestInject (span, request) {
|
|
31
60
|
const operation = request.operation
|
|
@@ -34,6 +63,7 @@ class EventBridge extends BaseAwsSdkPlugin {
|
|
|
34
63
|
request.params.Entries &&
|
|
35
64
|
request.params.Entries.length > 0 &&
|
|
36
65
|
request.params.Entries[0].Detail) {
|
|
66
|
+
const entries = request.params.Entries
|
|
37
67
|
const injected = {}
|
|
38
68
|
this.tracer.inject(span, 'text_map', injected)
|
|
39
69
|
|
|
@@ -42,19 +72,26 @@ class EventBridge extends BaseAwsSdkPlugin {
|
|
|
42
72
|
// it so the rest of the body stays in V8's optimisable surface.
|
|
43
73
|
let finalData
|
|
44
74
|
try {
|
|
45
|
-
finalData = BaseAwsSdkPlugin.injectFieldIntoJsonObject(
|
|
46
|
-
request.params.Entries[0].Detail, '_datadog', injected
|
|
47
|
-
)
|
|
75
|
+
finalData = BaseAwsSdkPlugin.injectFieldIntoJsonObject(entries[0].Detail, '_datadog', injected)
|
|
48
76
|
} catch (error) {
|
|
49
77
|
log.error('EventBridge error injecting request', error)
|
|
50
78
|
return
|
|
51
79
|
}
|
|
52
80
|
|
|
53
|
-
|
|
81
|
+
// EventBridge applies the 1 MiB cap to the whole request, so size every
|
|
82
|
+
// entry as it would be sent (the first with `_datadog` injected) and skip
|
|
83
|
+
// rather than tip a request AWS would otherwise accept over the limit. The
|
|
84
|
+
// running total only needs to clear the cap, so stop summing the moment it
|
|
85
|
+
// does instead of byte-counting the rest of a batch we already know is over.
|
|
86
|
+
let requestSize = putEventEntrySize(entries[0], finalData)
|
|
87
|
+
for (let i = 1; requestSize < MAX_PUT_EVENTS_BYTES && i < entries.length; i++) {
|
|
88
|
+
requestSize += putEventEntrySize(entries[i])
|
|
89
|
+
}
|
|
90
|
+
if (requestSize >= MAX_PUT_EVENTS_BYTES) {
|
|
54
91
|
log.info('Payload size too large to pass context')
|
|
55
92
|
return
|
|
56
93
|
}
|
|
57
|
-
|
|
94
|
+
entries[0].Detail = finalData
|
|
58
95
|
}
|
|
59
96
|
}
|
|
60
97
|
}
|
|
@@ -72,44 +72,53 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
72
72
|
})
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Start the consumer (`aws.response`) span for a receive. The first message carrying trace
|
|
77
|
+
* context becomes the parent; every additional one fans in as a span link.
|
|
78
|
+
*
|
|
79
|
+
* @param {{ request: object, response: object, needsFinish?: boolean, currentStore?: object }} ctx
|
|
80
|
+
* @returns {object | undefined} The store to activate for the consumer span, else the parent store.
|
|
81
|
+
*/
|
|
75
82
|
#startResponseSpan (ctx) {
|
|
76
83
|
const { request, response } = ctx
|
|
77
|
-
const
|
|
84
|
+
const carriers = this.responseExtract(request.params, request.operation, response)
|
|
78
85
|
|
|
79
86
|
let store = this._parentMap.get(request)
|
|
80
87
|
let span
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
|
|
89
|
+
if (carriers !== undefined) {
|
|
90
|
+
// request:start records requestTags only after the isEnabled gate, so an absent entry
|
|
91
|
+
// means this consumer is disabled — gate on it instead of paying isEnabled again here.
|
|
92
|
+
const requestTags = this.requestTags.get(request)
|
|
93
|
+
if (requestTags !== undefined) {
|
|
94
|
+
// A receive can return messages from many producers; fanning the extra ones in as span
|
|
95
|
+
// links is the shape dd-trace-java and dd-trace-py use for batch SQS receives.
|
|
96
|
+
for (const carrier of carriers) {
|
|
97
|
+
if (carrier === undefined) continue
|
|
98
|
+
const datadogContext = this.tracer.extract('text_map', carrier)
|
|
99
|
+
// A DSM-only carrier (a non-first sendMessageBatch entry when batchPropagationEnabled
|
|
100
|
+
// is off) extracts to null; span.addLink dereferences the context and would throw on it.
|
|
101
|
+
if (datadogContext === null) continue
|
|
102
|
+
if (span === undefined) {
|
|
103
|
+
ctx.needsFinish = true
|
|
104
|
+
span = this.startSpan('aws.response', {
|
|
105
|
+
childOf: datadogContext,
|
|
106
|
+
meta: {
|
|
107
|
+
...requestTags,
|
|
108
|
+
'span.kind': 'server',
|
|
109
|
+
},
|
|
110
|
+
integrationName: 'aws-sdk',
|
|
111
|
+
}, ctx)
|
|
112
|
+
store = ctx.currentStore
|
|
113
|
+
} else {
|
|
114
|
+
span.addLink({ context: datadogContext })
|
|
101
115
|
}
|
|
102
|
-
span = this.startSpan('aws.response', options, ctx)
|
|
103
|
-
store = ctx.currentStore
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
// Extract DSM context after, as we might not have a parent-child but may have a DSM context.
|
|
109
|
-
this.responseExtractDSMContext(
|
|
110
|
-
request.operation, request.params, response, span ?? null,
|
|
111
|
-
{ parsedAttributes: parsedMessageAttributes, parsedFirstBody, firstBodyChecked }
|
|
112
|
-
)
|
|
121
|
+
this.responseExtractDSMContext(request.operation, request.params, response, span ?? null, carriers)
|
|
113
122
|
|
|
114
123
|
return store
|
|
115
124
|
}
|
|
@@ -183,19 +192,39 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
183
192
|
return tags
|
|
184
193
|
}
|
|
185
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Parse the trace-context carrier of every received message, in message order.
|
|
197
|
+
* Entries are `undefined` for messages that carry no `_datadog` context.
|
|
198
|
+
*
|
|
199
|
+
* @param {{ MaxNumberOfMessages?: number }} params
|
|
200
|
+
* @param {string} operation
|
|
201
|
+
* @param {{ Messages?: object[] }} response
|
|
202
|
+
* @returns {Array<Record<string, string> | undefined> | undefined}
|
|
203
|
+
*/
|
|
186
204
|
responseExtract (params, operation, response) {
|
|
187
205
|
if (operation !== 'receiveMessage') return
|
|
188
|
-
if (
|
|
189
|
-
if (!response || !response.Messages || !response.Messages[0]) return
|
|
206
|
+
if (!response?.Messages?.length) return
|
|
190
207
|
|
|
191
|
-
|
|
192
|
-
|
|
208
|
+
return response.Messages.map(message => this.parseMessageCarrier(message))
|
|
209
|
+
}
|
|
193
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Resolve the trace-context carrier for a single received message. The
|
|
213
|
+
* `MessageAttributes._datadog` text map (direct SQS or SNS to SQS) wins;
|
|
214
|
+
* otherwise the EventBridge envelope, optionally wrapped in an SNS
|
|
215
|
+
* `Notification` (see getEventBridgeContext). Checking MessageAttributes first
|
|
216
|
+
* avoids parsing a large SNS `Message` just to rule out an EventBridge envelope.
|
|
217
|
+
*
|
|
218
|
+
* @param {object} message A single `response.Messages` entry.
|
|
219
|
+
* @returns {Record<string, string> | undefined}
|
|
220
|
+
*/
|
|
221
|
+
parseMessageCarrier (message) {
|
|
222
|
+
let parsedBody
|
|
194
223
|
if (message.Body) {
|
|
195
224
|
try {
|
|
196
225
|
parsedBody = JSON.parse(message.Body)
|
|
197
226
|
} catch {
|
|
198
|
-
// SQS to SQS
|
|
227
|
+
// Opaque, non-JSON body (SQS to SQS).
|
|
199
228
|
}
|
|
200
229
|
// SNS to SQS
|
|
201
230
|
if (parsedBody?.Type === 'Notification') {
|
|
@@ -203,34 +232,9 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
203
232
|
}
|
|
204
233
|
}
|
|
205
234
|
|
|
206
|
-
// Check MessageAttributes first (common direct-SQS/SNS path): avoids parsing
|
|
207
|
-
// the body (e.g. a large SNS `Message`) just to rule out an EventBridge
|
|
208
|
-
// envelope. Precedence matches responseExtractDSMContext.
|
|
209
235
|
const datadogAttribute = message.MessageAttributes?._datadog
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (parsedAttributes) {
|
|
213
|
-
return {
|
|
214
|
-
datadogContext: this.tracer.extract('text_map', parsedAttributes),
|
|
215
|
-
parsedAttributes,
|
|
216
|
-
parsedBody,
|
|
217
|
-
bodyChecked: true,
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Then the EventBridge envelope (optionally via SNS); see getEventBridgeContext.
|
|
223
|
-
const eventBridgeContext = getEventBridgeContext(parsedBody)
|
|
224
|
-
if (eventBridgeContext) {
|
|
225
|
-
return {
|
|
226
|
-
datadogContext: this.tracer.extract('text_map', eventBridgeContext),
|
|
227
|
-
parsedAttributes: eventBridgeContext,
|
|
228
|
-
parsedBody,
|
|
229
|
-
bodyChecked: true,
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return { parsedBody, bodyChecked: true }
|
|
236
|
+
const carrier = datadogAttribute ? this.parseDatadogAttributes(datadogAttribute) : undefined
|
|
237
|
+
return carrier ?? getEventBridgeContext(parsedBody)
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
parseDatadogAttributes (attributes) {
|
|
@@ -247,51 +251,39 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
247
251
|
}
|
|
248
252
|
}
|
|
249
253
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
254
|
+
/**
|
|
255
|
+
* @param {string} operation
|
|
256
|
+
* @param {{ QueueUrl: string }} params
|
|
257
|
+
* @param {{ Messages?: object[] }} response
|
|
258
|
+
* @param {import('../../../dd-trace/src/opentracing/span') | null} span
|
|
259
|
+
* @param {Array<Record<string, string> | undefined>} [carriers] Per-message carriers already
|
|
260
|
+
* parsed by `responseExtract`; reused so each message body is parsed once. When omitted, the
|
|
261
|
+
* carriers are parsed here.
|
|
262
|
+
*/
|
|
263
|
+
responseExtractDSMContext (operation, params, response, span, carriers) {
|
|
253
264
|
if (!this.config.dsmEnabled) return
|
|
254
265
|
if (operation !== 'receiveMessage') return
|
|
255
|
-
if (!response
|
|
266
|
+
if (!response?.Messages?.length) return
|
|
256
267
|
|
|
268
|
+
const messages = response.Messages
|
|
257
269
|
// Only attribute payloadSize to the span when there is a single message.
|
|
258
|
-
span =
|
|
270
|
+
span = messages.length > 1 ? null : span
|
|
259
271
|
|
|
260
272
|
// QueueUrl is the same for the whole receive batch.
|
|
261
273
|
const queue = params.QueueUrl.slice(params.QueueUrl.lastIndexOf('/') + 1)
|
|
262
274
|
|
|
263
|
-
for (let i = 0; i <
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
} else if (message.Body) {
|
|
271
|
-
try {
|
|
272
|
-
body = JSON.parse(message.Body)
|
|
273
|
-
} catch {
|
|
274
|
-
// SQS to SQS
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
// SNS to SQS
|
|
278
|
-
if (body?.Type === 'Notification') {
|
|
279
|
-
message = body
|
|
280
|
-
}
|
|
281
|
-
// MessageAttributes for direct SQS/SNS; else the EventBridge envelope.
|
|
282
|
-
parsedAttributes = message.MessageAttributes?._datadog
|
|
283
|
-
? this.parseDatadogAttributes(message.MessageAttributes._datadog)
|
|
284
|
-
: getEventBridgeContext(body)
|
|
275
|
+
for (let i = 0; i < messages.length; i++) {
|
|
276
|
+
const message = messages[i]
|
|
277
|
+
const carrier = carriers === undefined ? this.parseMessageCarrier(message) : carriers[i]
|
|
278
|
+
if (carrier) {
|
|
279
|
+
// Inert for EventBridge until its producer emits a pathway (separate
|
|
280
|
+
// change) — no `dd-pathway-ctx-base64` to decode yet; SQS/SNS decode now.
|
|
281
|
+
this.tracer.decodeDataStreamsContext(carrier)
|
|
285
282
|
}
|
|
286
283
|
const payloadSize = getHeadersSize({
|
|
287
284
|
Body: message.Body,
|
|
288
285
|
MessageAttributes: message.MessageAttributes,
|
|
289
286
|
})
|
|
290
|
-
if (parsedAttributes) {
|
|
291
|
-
// Inert for EventBridge until its producer emits a pathway (separate
|
|
292
|
-
// change) — no `dd-pathway-ctx-base64` to decode yet; SQS/SNS decode now.
|
|
293
|
-
this.tracer.decodeDataStreamsContext(parsedAttributes)
|
|
294
|
-
}
|
|
295
287
|
this.tracer
|
|
296
288
|
.setCheckpoint(['direction:in', `topic:${queue}`, 'type:sqs'], span, payloadSize)
|
|
297
289
|
}
|
|
@@ -130,7 +130,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
130
130
|
finishAllTraceSpans(this.testSessionSpan)
|
|
131
131
|
this.telemetry.count(TELEMETRY_TEST_SESSION, {
|
|
132
132
|
provider: this.ciProviderName,
|
|
133
|
-
autoInjected: !!this._tracerConfig.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
133
|
+
autoInjected: !!this._tracerConfig.testOptimization.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
134
134
|
})
|
|
135
135
|
|
|
136
136
|
this.libraryConfig = null
|
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
TEST_IS_RUM_ACTIVE,
|
|
12
12
|
TEST_CODE_OWNERS,
|
|
13
13
|
getTestEnvironmentMetadata,
|
|
14
|
+
getTestLevelsMetadataTags,
|
|
14
15
|
CI_APP_ORIGIN,
|
|
15
16
|
getTestParentSpan,
|
|
16
17
|
getCodeOwnersFileEntries,
|
|
@@ -23,6 +24,7 @@ const {
|
|
|
23
24
|
TEST_MODULE_ID,
|
|
24
25
|
TEST_SESSION_ID,
|
|
25
26
|
TEST_COMMAND,
|
|
27
|
+
TEST_LEVELS_METADATA,
|
|
26
28
|
TEST_MODULE,
|
|
27
29
|
TEST_SOURCE_START,
|
|
28
30
|
finishAllTraceSpans,
|
|
@@ -388,6 +390,7 @@ class CypressPlugin {
|
|
|
388
390
|
earlyFlakeDetectionFaultyThreshold = 0
|
|
389
391
|
testsToSkip = []
|
|
390
392
|
skippedTests = []
|
|
393
|
+
skippedTestIds = new Set()
|
|
391
394
|
skippableTestsCoverage = {}
|
|
392
395
|
testSessionCoverageMap = createCoverageMap()
|
|
393
396
|
hasForcedToRunSuites = false
|
|
@@ -471,6 +474,7 @@ class CypressPlugin {
|
|
|
471
474
|
this.earlyFlakeDetectionFaultyThreshold = 0
|
|
472
475
|
this.testsToSkip = []
|
|
473
476
|
this.skippedTests = []
|
|
477
|
+
this.skippedTestIds = new Set()
|
|
474
478
|
this.skippableTestsCoverage = {}
|
|
475
479
|
this.testSessionCoverageMap = createCoverageMap()
|
|
476
480
|
this.hasForcedToRunSuites = false
|
|
@@ -635,7 +639,7 @@ class CypressPlugin {
|
|
|
635
639
|
|
|
636
640
|
this.isTestIsolationEnabled = getIsTestIsolationEnabled(cypressConfig)
|
|
637
641
|
|
|
638
|
-
this.rumFlushWaitMillis = getConfig().DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS
|
|
642
|
+
this.rumFlushWaitMillis = getConfig().testOptimization.DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS
|
|
639
643
|
|
|
640
644
|
if (!this.isTestIsolationEnabled) {
|
|
641
645
|
log.warn('Test isolation is disabled, retries will not be enabled')
|
|
@@ -1043,7 +1047,13 @@ class CypressPlugin {
|
|
|
1043
1047
|
)
|
|
1044
1048
|
|
|
1045
1049
|
if (this.tracer._tracer._exporter?.addMetadataTags) {
|
|
1046
|
-
const metadataTags = {
|
|
1050
|
+
const metadataTags = {
|
|
1051
|
+
[TEST_LEVELS_METADATA]: {
|
|
1052
|
+
[TEST_COMMAND]: this.command,
|
|
1053
|
+
[TEST_SESSION_NAME]: testSessionName,
|
|
1054
|
+
...getTestLevelsMetadataTags(this.testEnvironmentMetadata),
|
|
1055
|
+
},
|
|
1056
|
+
}
|
|
1047
1057
|
const libraryCapabilitiesTags = getLibraryCapabilitiesTags(this.constructor.id, this.frameworkVersion)
|
|
1048
1058
|
metadataTags.test = {
|
|
1049
1059
|
...libraryCapabilitiesTags,
|
|
@@ -1140,7 +1150,7 @@ class CypressPlugin {
|
|
|
1140
1150
|
this.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
1141
1151
|
incrementCountMetric(TELEMETRY_TEST_SESSION, {
|
|
1142
1152
|
provider: this.ciProviderName,
|
|
1143
|
-
autoInjected: !!getConfig().DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
1153
|
+
autoInjected: !!getConfig().testOptimization.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
1144
1154
|
})
|
|
1145
1155
|
|
|
1146
1156
|
finishAllTraceSpans(this.testSessionSpan)
|
|
@@ -1378,7 +1388,7 @@ class CypressPlugin {
|
|
|
1378
1388
|
return suitePayload
|
|
1379
1389
|
},
|
|
1380
1390
|
'dd:beforeEach': (test) => {
|
|
1381
|
-
const { testName, testSuite, isEfdRetry, efdRetryIndex } = test
|
|
1391
|
+
const { testId, testName, testSuite, isEfdRetry, efdRetryIndex } = test
|
|
1382
1392
|
if (isEfdRetry && this.shouldSkipEfdRetry(testSuite, testName, efdRetryIndex)) {
|
|
1383
1393
|
return { shouldSkip: true, shouldDiscard: true }
|
|
1384
1394
|
}
|
|
@@ -1390,7 +1400,11 @@ class CypressPlugin {
|
|
|
1390
1400
|
const { isAttemptToFix, isDisabled, isQuarantined } = this.getTestProperties(testSuite, testName)
|
|
1391
1401
|
// skip test
|
|
1392
1402
|
if (shouldSkip && !isUnskippable) {
|
|
1393
|
-
|
|
1403
|
+
const skippedTestId = `${testSuite}:${testId || testName}`
|
|
1404
|
+
if (!this.skippedTestIds.has(skippedTestId)) {
|
|
1405
|
+
this.skippedTestIds.add(skippedTestId)
|
|
1406
|
+
this.skippedTests.push(test)
|
|
1407
|
+
}
|
|
1394
1408
|
this.isTestsSkipped = true
|
|
1395
1409
|
return { shouldSkip: true }
|
|
1396
1410
|
}
|