dd-trace 5.54.0 → 5.55.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/ci/cypress/plugin.js +8 -0
- package/ci/cypress/polyfills.js +23 -0
- package/ci/init.js +8 -7
- package/initialize.mjs +2 -2
- package/package.json +6 -6
- package/packages/datadog-code-origin/index.js +22 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +3 -3
- package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -6
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +2 -3
- package/packages/datadog-instrumentations/src/cookie-parser.js +1 -1
- package/packages/datadog-instrumentations/src/couchbase.js +3 -6
- package/packages/datadog-instrumentations/src/cucumber.js +21 -28
- package/packages/datadog-instrumentations/src/dns.js +4 -4
- package/packages/datadog-instrumentations/src/elasticsearch.js +9 -10
- package/packages/datadog-instrumentations/src/fastify.js +7 -9
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +14 -16
- package/packages/datadog-instrumentations/src/hapi.js +10 -11
- package/packages/datadog-instrumentations/src/helpers/fetch.js +4 -5
- package/packages/datadog-instrumentations/src/helpers/hook.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +6 -5
- package/packages/datadog-instrumentations/src/jest.js +67 -98
- package/packages/datadog-instrumentations/src/koa.js +2 -3
- package/packages/datadog-instrumentations/src/mariadb.js +11 -4
- package/packages/datadog-instrumentations/src/mocha/main.js +79 -75
- package/packages/datadog-instrumentations/src/mocha.js +3 -1
- package/packages/datadog-instrumentations/src/mysql.js +11 -2
- package/packages/datadog-instrumentations/src/nyc.js +2 -1
- package/packages/datadog-instrumentations/src/openai.js +2 -2
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -3
- package/packages/datadog-instrumentations/src/pg.js +2 -3
- package/packages/datadog-instrumentations/src/playwright.js +19 -22
- package/packages/datadog-instrumentations/src/protobufjs.js +3 -4
- package/packages/datadog-instrumentations/src/redis.js +1 -1
- package/packages/datadog-instrumentations/src/restify.js +9 -13
- package/packages/datadog-instrumentations/src/router.js +12 -11
- package/packages/datadog-instrumentations/src/tedious.js +1 -2
- package/packages/datadog-instrumentations/src/vitest.js +15 -29
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +12 -12
- package/packages/datadog-plugin-aws-sdk/src/base.js +12 -8
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +12 -20
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -5
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -10
- package/packages/datadog-plugin-cucumber/src/index.js +3 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -1
- package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -1
- package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +1 -1
- package/packages/datadog-plugin-graphql/src/index.js +3 -2
- package/packages/datadog-plugin-graphql/src/resolve.js +17 -10
- package/packages/datadog-plugin-http/src/client.js +5 -6
- package/packages/datadog-plugin-http2/src/client.js +7 -8
- package/packages/datadog-plugin-jest/src/index.js +3 -2
- package/packages/datadog-plugin-mocha/src/index.js +6 -1
- package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
- package/packages/datadog-plugin-mysql/src/index.js +11 -0
- package/packages/datadog-plugin-next/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/tracing.js +2 -4
- package/packages/datadog-plugin-playwright/src/index.js +3 -2
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +8 -9
- package/packages/datadog-plugin-redis/src/index.js +1 -3
- package/packages/datadog-plugin-vitest/src/index.js +5 -4
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +1 -2
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +11 -12
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +10 -11
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +0 -4
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +0 -1
- package/packages/dd-trace/src/appsec/index.js +4 -4
- package/packages/dd-trace/src/appsec/reporter.js +5 -7
- package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -3
- package/packages/dd-trace/src/appsec/telemetry/index.js +31 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -2
- package/packages/dd-trace/src/azure_metadata.js +8 -3
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +8 -7
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +4 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +7 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -3
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -1
- package/packages/dd-trace/src/config-helper.js +89 -0
- package/packages/dd-trace/src/config.js +77 -78
- package/packages/dd-trace/src/config_stable.js +7 -4
- package/packages/dd-trace/src/datastreams/fnv.js +1 -1
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +6 -6
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +1 -1
- package/packages/dd-trace/src/debugger/index.js +1 -0
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +5 -2
- package/packages/dd-trace/src/encode/0.5.js +3 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -5
- package/packages/dd-trace/src/exporter.js +2 -1
- package/packages/dd-trace/src/exporters/common/docker.js +3 -2
- package/packages/dd-trace/src/exporters/common/request.js +4 -1
- package/packages/dd-trace/src/exporters/common/util.js +3 -1
- package/packages/dd-trace/src/id.js +3 -3
- package/packages/dd-trace/src/index.js +4 -3
- package/packages/dd-trace/src/lambda/handler.js +2 -1
- package/packages/dd-trace/src/lambda/index.js +2 -1
- package/packages/dd-trace/src/lambda/runtime/patch.js +3 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/index.js +21 -5
- package/packages/dd-trace/src/llmobs/noop.js +18 -20
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +11 -13
- package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -2
- package/packages/dd-trace/src/llmobs/sdk.js +2 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +19 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
- package/packages/dd-trace/src/log/index.js +5 -4
- package/packages/dd-trace/src/log/writer.js +1 -2
- package/packages/dd-trace/src/msgpack/encoder.js +3 -3
- package/packages/dd-trace/src/noop/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +4 -5
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -18
- package/packages/dd-trace/src/opentracing/span.js +7 -6
- package/packages/dd-trace/src/payload-tagging/config/index.js +17 -21
- package/packages/dd-trace/src/plugin_manager.js +4 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +25 -1
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +7 -7
- package/packages/dd-trace/src/plugins/util/git.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +8 -1
- package/packages/dd-trace/src/plugins/util/test.js +4 -3
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -1
- package/packages/dd-trace/src/plugins/util/web.js +3 -4
- package/packages/dd-trace/src/priority_sampler.js +46 -35
- package/packages/dd-trace/src/profiling/config.js +12 -32
- package/packages/dd-trace/src/profiling/exporter_cli.js +20 -20
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -1
- package/packages/dd-trace/src/profiling/index.js +2 -1
- package/packages/dd-trace/src/profiling/profiler.js +7 -4
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +3 -1
- package/packages/dd-trace/src/profiling/tagger.js +22 -12
- package/packages/dd-trace/src/proxy.js +2 -1
- package/packages/dd-trace/src/ritm.js +4 -4
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -2
- package/packages/dd-trace/src/sampler.js +10 -2
- package/packages/dd-trace/src/serverless.js +11 -4
- package/packages/dd-trace/src/span_processor.js +2 -1
- package/packages/dd-trace/src/standalone/tracesource.js +1 -2
- package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +1 -2
- package/packages/dd-trace/src/startup-log.js +5 -17
- package/packages/dd-trace/src/supported-configurations.json +439 -0
- package/packages/dd-trace/src/telemetry/dependencies.js +62 -57
- package/packages/dd-trace/src/telemetry/send-data.js +7 -6
- package/packages/dd-trace/src/telemetry/telemetry.js +12 -25
- package/packages/dd-trace/src/tracer.js +3 -7
- package/packages/dd-trace/src/util.js +0 -5
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +0 -120
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +0 -20
|
@@ -239,8 +239,8 @@ class TextMapPropagator {
|
|
|
239
239
|
|
|
240
240
|
if (typeof origin === 'string') {
|
|
241
241
|
const originValue = origin
|
|
242
|
-
.
|
|
243
|
-
.
|
|
242
|
+
.replaceAll(tracestateOriginFilter, '_')
|
|
243
|
+
.replaceAll(/[\x3D]/g, '~')
|
|
244
244
|
|
|
245
245
|
state.set('o', originValue)
|
|
246
246
|
}
|
|
@@ -249,12 +249,12 @@ class TextMapPropagator {
|
|
|
249
249
|
if (!tags[key] || !key.startsWith('_dd.p.')) continue
|
|
250
250
|
|
|
251
251
|
const tagKey = 't.' + key.slice(6)
|
|
252
|
-
.
|
|
252
|
+
.replaceAll(tracestateTagKeyFilter, '_')
|
|
253
253
|
|
|
254
254
|
const tagValue = tags[key]
|
|
255
255
|
.toString()
|
|
256
|
-
.
|
|
257
|
-
.
|
|
256
|
+
.replaceAll(tracestateTagValueFilter, '_')
|
|
257
|
+
.replaceAll(/[\x3D]/g, '~')
|
|
258
258
|
|
|
259
259
|
state.set(tagKey, tagValue)
|
|
260
260
|
}
|
|
@@ -508,7 +508,7 @@ class TextMapPropagator {
|
|
|
508
508
|
default: {
|
|
509
509
|
if (!key.startsWith('t.')) continue
|
|
510
510
|
const subKey = key.slice(2) // e.g. t.tid -> tid
|
|
511
|
-
const transformedValue = value.
|
|
511
|
+
const transformedValue = value.replaceAll(/[\x7E]/gm, '=')
|
|
512
512
|
|
|
513
513
|
// If subkey is tid then do nothing because trace header tid should always be preserved
|
|
514
514
|
if (subKey === 'tid') {
|
|
@@ -581,22 +581,21 @@ class TextMapPropagator {
|
|
|
581
581
|
return {
|
|
582
582
|
[b3SampledKey]: parts[0]
|
|
583
583
|
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
584
|
+
}
|
|
585
|
+
const b3 = {
|
|
586
|
+
[b3TraceKey]: parts[0],
|
|
587
|
+
[b3SpanKey]: parts[1]
|
|
588
|
+
}
|
|
589
589
|
|
|
590
|
-
|
|
591
|
-
|
|
590
|
+
if (parts[2]) {
|
|
591
|
+
b3[b3SampledKey] = parts[2] === '0' ? '0' : '1'
|
|
592
592
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
593
|
+
if (parts[2] === 'd') {
|
|
594
|
+
b3[b3FlagsKey] = '1'
|
|
596
595
|
}
|
|
597
|
-
|
|
598
|
-
return b3
|
|
599
596
|
}
|
|
597
|
+
|
|
598
|
+
return b3
|
|
600
599
|
}
|
|
601
600
|
|
|
602
601
|
_extractOrigin (carrier, spanContext) {
|
|
@@ -13,18 +13,17 @@ const { storage } = require('../../../datadog-core')
|
|
|
13
13
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
14
14
|
const { channel } = require('dc-polyfill')
|
|
15
15
|
const util = require('util')
|
|
16
|
+
const { getEnvironmentVariable } = require('../config-helper')
|
|
16
17
|
|
|
17
18
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
DD_TRACE_EXPERIMENTAL_SPAN_COUNTS
|
|
22
|
-
} = process.env
|
|
20
|
+
const DD_TRACE_EXPERIMENTAL_STATE_TRACKING = getEnvironmentVariable('DD_TRACE_EXPERIMENTAL_STATE_TRACKING')
|
|
21
|
+
const DD_TRACE_EXPERIMENTAL_SPAN_COUNTS = getEnvironmentVariable('DD_TRACE_EXPERIMENTAL_SPAN_COUNTS')
|
|
23
22
|
|
|
24
23
|
const unfinishedRegistry = createRegistry('unfinished')
|
|
25
24
|
const finishedRegistry = createRegistry('finished')
|
|
26
25
|
|
|
27
|
-
const OTEL_ENABLED = !!
|
|
26
|
+
const OTEL_ENABLED = !!getEnvironmentVariable('DD_TRACE_OTEL_ENABLED')
|
|
28
27
|
const ALLOWED = new Set(['string', 'number', 'boolean'])
|
|
29
28
|
|
|
30
29
|
const integrationCounters = {
|
|
@@ -56,6 +55,8 @@ class DatadogSpan {
|
|
|
56
55
|
constructor (tracer, processor, prioritySampler, fields, debug) {
|
|
57
56
|
const operationName = fields.operationName
|
|
58
57
|
const parent = fields.parent || null
|
|
58
|
+
// TODO(BridgeAR): Investigate why this is causing a performance regression
|
|
59
|
+
// eslint-disable-next-line prefer-object-spread
|
|
59
60
|
const tags = Object.assign({}, fields.tags)
|
|
60
61
|
const hostname = fields.hostname
|
|
61
62
|
|
|
@@ -333,7 +334,7 @@ class DatadogSpan {
|
|
|
333
334
|
spanId: id(),
|
|
334
335
|
parentId: parent._spanId,
|
|
335
336
|
sampling: parent._sampling,
|
|
336
|
-
baggageItems:
|
|
337
|
+
baggageItems: { ...parent._baggageItems },
|
|
337
338
|
trace: parent._trace,
|
|
338
339
|
tracestate: parent._tracestate
|
|
339
340
|
})
|
|
@@ -2,29 +2,25 @@ const aws = require('./aws.json')
|
|
|
2
2
|
const sdks = { aws }
|
|
3
3
|
|
|
4
4
|
function getSDKRules (sdk, requestInput, responseInput) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
)
|
|
5
|
+
const sdkServiceRules = {}
|
|
6
|
+
for (const [service, serviceRules] of Object.entries(sdk)) {
|
|
7
|
+
sdkServiceRules[service] = {
|
|
8
|
+
// Make a copy. Otherwise calling the function multiple times would append
|
|
9
|
+
// the rules to the same object.
|
|
10
|
+
request: [...serviceRules.request, ...requestInput],
|
|
11
|
+
response: [...serviceRules.response, ...responseInput],
|
|
12
|
+
expand: serviceRules.expand
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return sdkServiceRules
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
function appendRules (requestInput, responseInput) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
]
|
|
26
|
-
})
|
|
27
|
-
)
|
|
18
|
+
function appendRules (requestInput = [], responseInput = []) {
|
|
19
|
+
const sdkRules = {}
|
|
20
|
+
for (const [name, sdk] of Object.entries(sdks)) {
|
|
21
|
+
sdkRules[name] = getSDKRules(sdk, requestInput, responseInput)
|
|
22
|
+
}
|
|
23
|
+
return sdkRules
|
|
28
24
|
}
|
|
29
25
|
|
|
30
26
|
module.exports = { appendRules }
|
|
@@ -4,17 +4,18 @@ const { channel } = require('dc-polyfill')
|
|
|
4
4
|
const { isFalse } = require('./util')
|
|
5
5
|
const plugins = require('./plugins')
|
|
6
6
|
const log = require('./log')
|
|
7
|
+
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
|
|
7
8
|
|
|
8
9
|
const loadChannel = channel('dd-trace:instrumentation:load')
|
|
9
10
|
|
|
10
11
|
// instrument everything that needs Plugin System V2 instrumentation
|
|
11
12
|
require('../../datadog-instrumentations')
|
|
12
|
-
if (
|
|
13
|
+
if (getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined) {
|
|
13
14
|
// instrument lambda environment
|
|
14
15
|
require('./lambda')
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
+
const DD_TRACE_DISABLED_PLUGINS = getEnvironmentVariable('DD_TRACE_DISABLED_PLUGINS')
|
|
18
19
|
|
|
19
20
|
const disabledPlugins = new Set(
|
|
20
21
|
DD_TRACE_DISABLED_PLUGINS && DD_TRACE_DISABLED_PLUGINS.split(',').map(plugin => plugin.trim())
|
|
@@ -32,7 +33,7 @@ function maybeEnable (Plugin) {
|
|
|
32
33
|
if (!Plugin || typeof Plugin !== 'function') return
|
|
33
34
|
if (!pluginClasses[Plugin.id]) {
|
|
34
35
|
const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
|
|
35
|
-
const enabled =
|
|
36
|
+
const enabled = getEnvironmentVariable(envName.replaceAll(/[^a-z0-9_]/ig, '_'))
|
|
36
37
|
|
|
37
38
|
// TODO: remove the need to load the plugin class in order to disable the plugin
|
|
38
39
|
if (isFalse(enabled) || disabledPlugins.has(Plugin.id)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { storage } = require('../../../datadog-core')
|
|
1
2
|
const {
|
|
2
3
|
getTestEnvironmentMetadata,
|
|
3
4
|
getTestSessionName,
|
|
@@ -73,7 +74,10 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
73
74
|
this.fileLineToProbeId = new Map()
|
|
74
75
|
this.rootDir = process.cwd() // fallback in case :session:start events are not emitted
|
|
75
76
|
|
|
76
|
-
this.addSub(`ci:${this.constructor.id}:library-configuration`, (
|
|
77
|
+
this.addSub(`ci:${this.constructor.id}:library-configuration`, (ctx) => {
|
|
78
|
+
const { onDone, isParallel } = ctx
|
|
79
|
+
ctx.currentStore = storage('legacy').getStore()
|
|
80
|
+
|
|
77
81
|
if (!this.tracer._exporter || !this.tracer._exporter.getLibraryConfiguration) {
|
|
78
82
|
return onDone({ err: new Error('Test optimization was not initialized correctly') })
|
|
79
83
|
}
|
|
@@ -95,6 +99,10 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
95
99
|
})
|
|
96
100
|
})
|
|
97
101
|
|
|
102
|
+
this.addBind(`ci:${this.constructor.id}:test-suite:skippable`, (ctx) => {
|
|
103
|
+
return ctx.currentStore
|
|
104
|
+
})
|
|
105
|
+
|
|
98
106
|
this.addSub(`ci:${this.constructor.id}:test-suite:skippable`, ({ onDone }) => {
|
|
99
107
|
if (!this.tracer._exporter?.getSkippableSuites) {
|
|
100
108
|
return onDone({ err: new Error('Test optimization was not initialized correctly') })
|
|
@@ -158,8 +166,12 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
158
166
|
// only for vitest
|
|
159
167
|
// These are added for the worker threads to use
|
|
160
168
|
if (this.constructor.id === 'vitest') {
|
|
169
|
+
// TODO: Figure out alternative ways to pass this information to the worker threads
|
|
170
|
+
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
161
171
|
process.env.DD_CIVISIBILITY_TEST_SESSION_ID = this.testSessionSpan.context().toTraceId()
|
|
172
|
+
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
162
173
|
process.env.DD_CIVISIBILITY_TEST_MODULE_ID = this.testModuleSpan.context().toSpanId()
|
|
174
|
+
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
163
175
|
process.env.DD_CIVISIBILITY_TEST_COMMAND = this.command
|
|
164
176
|
}
|
|
165
177
|
|
|
@@ -188,6 +200,10 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
188
200
|
this.telemetry.count(TELEMETRY_ITR_SKIPPED, { testLevel: 'suite' }, skippedSuites.length)
|
|
189
201
|
})
|
|
190
202
|
|
|
203
|
+
this.addBind(`ci:${this.constructor.id}:known-tests`, (ctx) => {
|
|
204
|
+
return ctx.currentStore
|
|
205
|
+
})
|
|
206
|
+
|
|
191
207
|
this.addSub(`ci:${this.constructor.id}:known-tests`, ({ onDone }) => {
|
|
192
208
|
if (!this.tracer._exporter?.getKnownTests) {
|
|
193
209
|
return onDone({ err: new Error('Test optimization was not initialized correctly') })
|
|
@@ -202,6 +218,10 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
202
218
|
})
|
|
203
219
|
})
|
|
204
220
|
|
|
221
|
+
this.addBind(`ci:${this.constructor.id}:test-management-tests`, (ctx) => {
|
|
222
|
+
return ctx.currentStore
|
|
223
|
+
})
|
|
224
|
+
|
|
205
225
|
this.addSub(`ci:${this.constructor.id}:test-management-tests`, ({ onDone }) => {
|
|
206
226
|
if (!this.tracer._exporter?.getTestManagementTests) {
|
|
207
227
|
return onDone({ err: new Error('Test optimization was not initialized correctly') })
|
|
@@ -215,6 +235,10 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
215
235
|
})
|
|
216
236
|
})
|
|
217
237
|
|
|
238
|
+
this.addBind(`ci:${this.constructor.id}:modified-tests`, (ctx) => {
|
|
239
|
+
return ctx.currentStore
|
|
240
|
+
})
|
|
241
|
+
|
|
218
242
|
this.addSub(`ci:${this.constructor.id}:modified-tests`, ({ onDone }) => {
|
|
219
243
|
const {
|
|
220
244
|
[GIT_PULL_REQUEST_BASE_BRANCH]: pullRequestBaseBranch,
|
|
@@ -34,7 +34,7 @@ class StoreBinding {
|
|
|
34
34
|
this._transform = data => {
|
|
35
35
|
const store = storage('legacy').getStore()
|
|
36
36
|
|
|
37
|
-
return !store || !store.noop || data
|
|
37
|
+
return !store || !store.noop || (data && Object.hasOwn(data, 'currentStore'))
|
|
38
38
|
? transform(data)
|
|
39
39
|
: store
|
|
40
40
|
}
|
|
@@ -27,6 +27,7 @@ const {
|
|
|
27
27
|
CI_NODE_NAME
|
|
28
28
|
} = require('./tags')
|
|
29
29
|
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
30
|
+
const { getEnvironmentVariable } = require('../../config-helper')
|
|
30
31
|
|
|
31
32
|
// Receives a string with the form 'John Doe <john.doe@gmail.com>'
|
|
32
33
|
// and returns { name: 'John Doe', email: 'john.doe@gmail.com' }
|
|
@@ -67,7 +68,7 @@ function normalizeRef (ref) {
|
|
|
67
68
|
if (!ref) {
|
|
68
69
|
return ref
|
|
69
70
|
}
|
|
70
|
-
return ref.
|
|
71
|
+
return ref.replaceAll(/origin\/|refs\/heads\/|tags\//gm, '')
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
function resolveTilde (filePath) {
|
|
@@ -76,16 +77,16 @@ function resolveTilde (filePath) {
|
|
|
76
77
|
}
|
|
77
78
|
// '~/folder/path' or '~'
|
|
78
79
|
if (filePath[0] === '~' && (filePath[1] === '/' || filePath.length === 1)) {
|
|
79
|
-
return filePath.replace('~',
|
|
80
|
+
return filePath.replace('~', getEnvironmentVariable('HOME'))
|
|
80
81
|
}
|
|
81
82
|
return filePath
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
function getGitHubEventPayload () {
|
|
85
|
-
if (!
|
|
86
|
+
if (!getEnvironmentVariable('GITHUB_EVENT_PATH')) {
|
|
86
87
|
return
|
|
87
88
|
}
|
|
88
|
-
return JSON.parse(readFileSync(
|
|
89
|
+
return JSON.parse(readFileSync(getEnvironmentVariable('GITHUB_EVENT_PATH'), 'utf8'))
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
module.exports = {
|
|
@@ -139,11 +140,10 @@ module.exports = {
|
|
|
139
140
|
|
|
140
141
|
tags[refKey] = ref
|
|
141
142
|
|
|
142
|
-
let finalPipelineName = ''
|
|
143
143
|
if (JOB_NAME) {
|
|
144
144
|
// Job names can contain parameters, e.g. jobName/KEY1=VALUE1,KEY2=VALUE2/branchName
|
|
145
145
|
const jobNameAndParams = JOB_NAME.split('/')
|
|
146
|
-
finalPipelineName = jobNameAndParams.length > 1 && jobNameAndParams[1].includes('=')
|
|
146
|
+
const finalPipelineName = jobNameAndParams.length > 1 && jobNameAndParams[1].includes('=')
|
|
147
147
|
? jobNameAndParams[0]
|
|
148
148
|
: JOB_NAME.replace(`/${ref}`, '')
|
|
149
149
|
tags[CI_PIPELINE_NAME] = finalPipelineName
|
|
@@ -432,7 +432,7 @@ module.exports = {
|
|
|
432
432
|
[GIT_TAG]: BITBUCKET_TAG,
|
|
433
433
|
[GIT_REPOSITORY_URL]: BITBUCKET_GIT_SSH_ORIGIN || BITBUCKET_GIT_HTTP_ORIGIN,
|
|
434
434
|
[CI_WORKSPACE_PATH]: BITBUCKET_CLONE_DIR,
|
|
435
|
-
[CI_PIPELINE_ID]: BITBUCKET_PIPELINE_UUID && BITBUCKET_PIPELINE_UUID.
|
|
435
|
+
[CI_PIPELINE_ID]: BITBUCKET_PIPELINE_UUID && BITBUCKET_PIPELINE_UUID.replaceAll(/{|}/gm, ''),
|
|
436
436
|
[GIT_PULL_REQUEST_BASE_BRANCH]: BITBUCKET_PR_DESTINATION_BRANCH
|
|
437
437
|
}
|
|
438
438
|
}
|
|
@@ -51,7 +51,7 @@ function sanitizedExec (
|
|
|
51
51
|
try {
|
|
52
52
|
let result = cp.execFileSync(cmd, flags, { stdio: 'pipe' }).toString()
|
|
53
53
|
if (shouldTrim) {
|
|
54
|
-
result = result.
|
|
54
|
+
result = result.replaceAll(/(\r\n|\n|\r)/gm, '')
|
|
55
55
|
}
|
|
56
56
|
if (durationMetric) {
|
|
57
57
|
distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
|
|
@@ -11,8 +11,8 @@ function normalize (text, limit = 128) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
text = text
|
|
14
|
-
.
|
|
15
|
-
.
|
|
14
|
+
.replaceAll(RE_NEWLINE, String.raw`\n`)
|
|
15
|
+
.replaceAll(RE_TAB, String.raw`\t`)
|
|
16
16
|
|
|
17
17
|
// In case the replace above matched, more characters were added that must now be considered.
|
|
18
18
|
if (text.length > limit) {
|
|
@@ -34,7 +34,14 @@ function getCallSites (constructorOpt) {
|
|
|
34
34
|
*
|
|
35
35
|
* @param {Function} constructorOpt - Function to pass along to Error.captureStackTrace
|
|
36
36
|
* @param {number} [limit=Infinity] - The maximum number of frames to return
|
|
37
|
-
* @returns {
|
|
37
|
+
* @returns {StackFrame[]} - A list of stack frames from user-land code
|
|
38
|
+
*
|
|
39
|
+
* @typedef {Object} StackFrame
|
|
40
|
+
* @property {string} file - The file path of the frame
|
|
41
|
+
* @property {number} line - The line number in the file
|
|
42
|
+
* @property {number} column - The column number in the file
|
|
43
|
+
* @property {string} [method] - The function name, if available
|
|
44
|
+
* @property {string} [type] - The type name, if available
|
|
38
45
|
*/
|
|
39
46
|
function getUserLandFrames (constructorOpt, limit = Infinity) {
|
|
40
47
|
const callsites = getCallSites(constructorOpt)
|
|
@@ -2,6 +2,7 @@ const path = require('path')
|
|
|
2
2
|
const fs = require('fs')
|
|
3
3
|
const { URL } = require('url')
|
|
4
4
|
const log = require('../../log')
|
|
5
|
+
const { getEnvironmentVariable } = require('../../config-helper')
|
|
5
6
|
|
|
6
7
|
const istanbul = require('istanbul-lib-coverage')
|
|
7
8
|
const ignore = require('ignore')
|
|
@@ -284,7 +285,7 @@ module.exports = {
|
|
|
284
285
|
// Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
|
|
285
286
|
function getPkgManager () {
|
|
286
287
|
try {
|
|
287
|
-
return
|
|
288
|
+
return getEnvironmentVariable('npm_config_user_agent').split(' ')[0].replace('/', '-')
|
|
288
289
|
} catch {
|
|
289
290
|
return ''
|
|
290
291
|
}
|
|
@@ -789,11 +790,11 @@ function addAttemptToFixStringToTestName (testName, numAttempt) {
|
|
|
789
790
|
}
|
|
790
791
|
|
|
791
792
|
function removeEfdStringFromTestName (testName) {
|
|
792
|
-
return testName.
|
|
793
|
+
return testName.replaceAll(EFD_TEST_NAME_REGEX, '')
|
|
793
794
|
}
|
|
794
795
|
|
|
795
796
|
function removeAttemptToFixStringFromTestName (testName) {
|
|
796
|
-
return testName.
|
|
797
|
+
return testName.replaceAll(ATTEMPT_TEST_NAME_REGEX, '')
|
|
797
798
|
}
|
|
798
799
|
|
|
799
800
|
function getIsFaultyEarlyFlakeDetection (projectSuites, testsBySuiteName, faultyThresholdPercentage) {
|
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
|
|
18
18
|
const { normalizeRef } = require('./ci')
|
|
19
19
|
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
20
|
+
const { getEnvironmentVariables } = require('../../config-helper')
|
|
20
21
|
|
|
21
22
|
function removeEmptyValues (tags) {
|
|
22
23
|
return Object.keys(tags).reduce((filteredTags, tag) => {
|
|
@@ -59,7 +60,7 @@ function getUserProviderGitMetadata () {
|
|
|
59
60
|
DD_GIT_PULL_REQUEST_BASE_BRANCH,
|
|
60
61
|
DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA,
|
|
61
62
|
DD_GIT_COMMIT_HEAD_SHA
|
|
62
|
-
} =
|
|
63
|
+
} = getEnvironmentVariables()
|
|
63
64
|
|
|
64
65
|
const branch = normalizeRef(DD_GIT_BRANCH)
|
|
65
66
|
let tag = normalizeRef(DD_GIT_TAG)
|
|
@@ -421,7 +421,7 @@ function addAllowHeaders (req, res, headers) {
|
|
|
421
421
|
]
|
|
422
422
|
|
|
423
423
|
for (const header of contextHeaders) {
|
|
424
|
-
if (
|
|
424
|
+
if (requestHeaders.includes(header)) {
|
|
425
425
|
allowHeaders.push(header)
|
|
426
426
|
}
|
|
427
427
|
}
|
|
@@ -530,10 +530,9 @@ function extractURL (req) {
|
|
|
530
530
|
|
|
531
531
|
if (req.stream) {
|
|
532
532
|
return `${headers[HTTP2_HEADER_SCHEME]}://${headers[HTTP2_HEADER_AUTHORITY]}${headers[HTTP2_HEADER_PATH]}`
|
|
533
|
-
} else {
|
|
534
|
-
const protocol = getProtocol(req)
|
|
535
|
-
return `${protocol}://${req.headers.host}${req.originalUrl || req.url}`
|
|
536
533
|
}
|
|
534
|
+
const protocol = getProtocol(req)
|
|
535
|
+
return `${protocol}://${req.headers.host}${req.originalUrl || req.url}`
|
|
537
536
|
}
|
|
538
537
|
|
|
539
538
|
function getProtocol (req) {
|
|
@@ -5,7 +5,6 @@ const RateLimiter = require('./rate_limiter')
|
|
|
5
5
|
const Sampler = require('./sampler')
|
|
6
6
|
const { setSamplingRules } = require('./startup-log')
|
|
7
7
|
const SamplingRule = require('./sampling_rule')
|
|
8
|
-
const { hasOwn } = require('./util')
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
SAMPLING_MECHANISM_DEFAULT,
|
|
@@ -40,16 +39,28 @@ const DEFAULT_KEY = 'service:,env:'
|
|
|
40
39
|
const defaultSampler = new Sampler(AUTO_KEEP)
|
|
41
40
|
|
|
42
41
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
* PrioritySampler is responsible for determining whether a span should be sampled
|
|
43
|
+
* based on various rules, rate limits, and priorities. It supports manual and
|
|
44
|
+
* automatic sampling mechanisms and integrates with Datadog's tracing system.
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
* @typedef {
|
|
46
|
+
* @class PrioritySampler
|
|
47
|
+
* @typedef {import('./opentracing/span')} DatadogSpan
|
|
48
|
+
* @typedef {import('./opentracing/span_context')} DatadogSpanContext
|
|
49
|
+
* @typedef {import('./standalone/product')} PRODUCTS
|
|
50
|
+
* @typedef {2|-1|1|0} SamplingPriority Empirically defined sampling priorities.
|
|
48
51
|
*/
|
|
49
52
|
class PrioritySampler {
|
|
50
53
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
54
|
+
* Creates an instance of PrioritySampler.
|
|
55
|
+
*
|
|
56
|
+
* @typedef {Object} SamplingConfig
|
|
57
|
+
* @property {number} [sampleRate] - The default sample rate for traces.
|
|
58
|
+
* @property {string} [provenance] - The provenance of the sampling rule (e.g., "customer", "dynamic").
|
|
59
|
+
* @property {number} [rateLimit=100] - The maximum number of traces to sample per second.
|
|
60
|
+
* @property {Array<SamplingRule>} [rules=[]] - An array of sampling rules to apply.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} env - The environment name (e.g., "production", "staging").
|
|
63
|
+
* @param {SamplingConfig} config - The configuration object for sampling.
|
|
53
64
|
*/
|
|
54
65
|
constructor (env, config) {
|
|
55
66
|
this.configure(env, config)
|
|
@@ -62,9 +73,9 @@ class PrioritySampler {
|
|
|
62
73
|
* @param opts {SamplingConfig}
|
|
63
74
|
*/
|
|
64
75
|
configure (env, opts = {}) {
|
|
65
|
-
const { sampleRate, provenance, rateLimit = 100, rules
|
|
76
|
+
const { sampleRate, provenance, rateLimit = 100, rules } = opts
|
|
66
77
|
this._env = env
|
|
67
|
-
this._rules = this.#normalizeRules(rules, sampleRate, rateLimit, provenance)
|
|
78
|
+
this._rules = this.#normalizeRules(rules || [], sampleRate, rateLimit, provenance)
|
|
68
79
|
this._limiter = new RateLimiter(rateLimit)
|
|
69
80
|
|
|
70
81
|
log.trace(env, opts)
|
|
@@ -154,7 +165,7 @@ class PrioritySampler {
|
|
|
154
165
|
*
|
|
155
166
|
* @param span {DatadogSpan}
|
|
156
167
|
* @param samplingPriority {SamplingPriority}
|
|
157
|
-
* @param product {import('./standalone/product')
|
|
168
|
+
* @param product {import('./standalone/product')}
|
|
158
169
|
*/
|
|
159
170
|
setPriority (span, samplingPriority, product) {
|
|
160
171
|
if (!span || !this.validate(samplingPriority)) return
|
|
@@ -208,18 +219,17 @@ class PrioritySampler {
|
|
|
208
219
|
* @returns {SamplingPriority}
|
|
209
220
|
*/
|
|
210
221
|
_getPriorityFromTags (tags, _context) {
|
|
211
|
-
if (hasOwn(tags, MANUAL_KEEP) && tags[MANUAL_KEEP] !== false) {
|
|
222
|
+
if (Object.hasOwn(tags, MANUAL_KEEP) && tags[MANUAL_KEEP] !== false) {
|
|
212
223
|
return USER_KEEP
|
|
213
|
-
} else if (hasOwn(tags, MANUAL_DROP) && tags[MANUAL_DROP] !== false) {
|
|
224
|
+
} else if (Object.hasOwn(tags, MANUAL_DROP) && tags[MANUAL_DROP] !== false) {
|
|
214
225
|
return USER_REJECT
|
|
215
|
-
}
|
|
216
|
-
|
|
226
|
+
}
|
|
227
|
+
const priority = Number.parseInt(tags[SAMPLING_PRIORITY], 10)
|
|
217
228
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
229
|
+
if (priority === 1 || priority === 2) {
|
|
230
|
+
return USER_KEEP
|
|
231
|
+
} else if (priority === 0 || priority === -1) {
|
|
232
|
+
return USER_REJECT
|
|
223
233
|
}
|
|
224
234
|
}
|
|
225
235
|
|
|
@@ -258,7 +268,6 @@ class PrioritySampler {
|
|
|
258
268
|
*
|
|
259
269
|
* @param context {DatadogSpanContext}
|
|
260
270
|
* @returns {SamplingPriority}
|
|
261
|
-
* @private
|
|
262
271
|
*/
|
|
263
272
|
#getPriorityByAgent (context) {
|
|
264
273
|
const key = `service:${context._tags[SERVICE_NAME]},env:${this._env}`
|
|
@@ -274,7 +283,6 @@ class PrioritySampler {
|
|
|
274
283
|
/**
|
|
275
284
|
*
|
|
276
285
|
* @param span {DatadogSpan}
|
|
277
|
-
* @private
|
|
278
286
|
* @returns {void}
|
|
279
287
|
*/
|
|
280
288
|
#addDecisionMaker (span) {
|
|
@@ -293,30 +301,33 @@ class PrioritySampler {
|
|
|
293
301
|
}
|
|
294
302
|
|
|
295
303
|
/**
|
|
296
|
-
*
|
|
297
|
-
* @param
|
|
298
|
-
* @param
|
|
299
|
-
* @param
|
|
300
|
-
* @param provenance {string}
|
|
304
|
+
* @param {Record<string, unknown>[] | Record<string, unknown>} rules - The sampling rules to normalize.
|
|
305
|
+
* @param {number} sampleRate
|
|
306
|
+
* @param {number} rateLimit
|
|
307
|
+
* @param {string} provenance
|
|
301
308
|
* @returns {SamplingRule[]}
|
|
302
|
-
* @private
|
|
303
309
|
*/
|
|
304
310
|
#normalizeRules (rules, sampleRate, rateLimit, provenance) {
|
|
305
|
-
rules =
|
|
311
|
+
rules = Array.isArray(rules) ? rules.flat() : [rules]
|
|
306
312
|
|
|
307
313
|
rules.push({ sampleRate, maxPerSecond: rateLimit, provenance })
|
|
308
314
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
315
|
+
const result = []
|
|
316
|
+
for (const rule of rules) {
|
|
317
|
+
const sampleRate = Number.parseFloat(rule.sampleRate)
|
|
318
|
+
// TODO(BridgeAR): Debug logging invalid rules fails our tests.
|
|
319
|
+
// Should we definitely not know about these?
|
|
320
|
+
if (!Number.isNaN(sampleRate)) {
|
|
321
|
+
result.push(SamplingRule.from({ ...rule, sampleRate }))
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return result
|
|
313
325
|
}
|
|
314
326
|
|
|
315
327
|
/**
|
|
316
328
|
*
|
|
317
329
|
* @param span {DatadogSpan}
|
|
318
|
-
* @returns {SamplingRule}
|
|
319
|
-
* @private
|
|
330
|
+
* @returns {SamplingRule|undefined}
|
|
320
331
|
*/
|
|
321
332
|
#findRule (span) {
|
|
322
333
|
for (const rule of this._rules) {
|
|
@@ -330,7 +341,7 @@ class PrioritySampler {
|
|
|
330
341
|
/**
|
|
331
342
|
*
|
|
332
343
|
* @param span {DatadogSpan}
|
|
333
|
-
* @param product {import('./standalone/product')
|
|
344
|
+
* @param product {import('./standalone/product')}
|
|
334
345
|
*/
|
|
335
346
|
static keepTrace (span, product) {
|
|
336
347
|
span?._prioritySampler?.setPriority(span, USER_KEEP, product)
|