dd-trace 5.132.0 → 5.134.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/diagnose.js +9 -14
- package/ci/init.js +1 -2
- package/ci/test-optimization-validation/ci-discovery.js +9 -4
- package/ci/test-optimization-validation/executable.js +1 -5
- package/ci/test-optimization-validation/framework-adapters/cypress.js +1 -4
- package/ci/test-optimization-validation/framework-adapters/vitest.js +1 -1
- package/ci/test-optimization-validation/generated-files.js +6 -4
- package/ci/test-optimization-validation/generated-test-contract.js +7 -3
- package/ci/test-optimization-validation/manifest-scaffold.js +7 -2
- package/ci/test-optimization-validation/manifest-schema.js +6 -7
- package/ci/test-optimization-validation/report-writer.js +6 -2
- package/ci/test-optimization-validation/runner-command.js +2 -4
- package/ci/test-optimization-validation/runner-contract.js +1 -2
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +1 -15
- package/ci/vitest-no-worker-init-runner-setup.mjs +27 -0
- package/ci/vitest-no-worker-init-setup.mjs +10 -7
- package/index.d.ts +41 -19
- package/initialize.mjs +1 -3
- package/openfeature/rules-based.d.ts +11 -0
- package/openfeature/rules-based.js +7 -0
- package/package.json +25 -22
- package/packages/datadog-core/src/storage.js +16 -0
- package/packages/datadog-esbuild/index.js +18 -12
- package/packages/datadog-instrumentations/index.js +2 -1
- package/packages/datadog-instrumentations/src/aerospike.js +3 -3
- package/packages/datadog-instrumentations/src/ai.js +3 -3
- package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
- package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
- package/packages/datadog-instrumentations/src/cucumber.js +65 -41
- package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
- package/packages/datadog-instrumentations/src/electron.js +6 -6
- package/packages/datadog-instrumentations/src/fastify.js +13 -4
- package/packages/datadog-instrumentations/src/fs.js +2 -2
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
- package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +28 -9
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +45 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +89 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/jest.js +12 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/vitest.js +8 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +7 -7
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +5 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
- package/packages/datadog-instrumentations/src/ioredis.js +7 -5
- package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
- package/packages/datadog-instrumentations/src/jest.js +72 -67
- package/packages/datadog-instrumentations/src/knex.js +9 -5
- package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
- package/packages/datadog-instrumentations/src/mocha/utils.js +38 -4
- package/packages/datadog-instrumentations/src/mocha/worker.js +1 -2
- package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
- package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
- package/packages/datadog-instrumentations/src/nova-sonic/session.js +492 -0
- package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
- package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
- package/packages/datadog-instrumentations/src/openai.js +7 -0
- package/packages/datadog-instrumentations/src/pino.js +5 -6
- package/packages/datadog-instrumentations/src/playwright.js +2 -0
- package/packages/datadog-instrumentations/src/redis.js +27 -13
- package/packages/datadog-instrumentations/src/router.js +30 -0
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
- package/packages/datadog-instrumentations/src/stripe.js +23 -12
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +8 -5
- package/packages/datadog-instrumentations/src/vitest-main.js +16 -18
- package/packages/datadog-instrumentations/src/vitest-util.js +7 -4
- package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
- package/packages/datadog-instrumentations/src/vitest.js +9 -1
- package/packages/datadog-instrumentations/src/webdriverio.js +5 -8
- package/packages/datadog-instrumentations/src/ws.js +1 -4
- package/packages/datadog-plugin-amqplib/src/client.js +1 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
- package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
- package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +4 -5
- package/packages/datadog-plugin-cypress/src/index.js +6 -6
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
- package/packages/datadog-plugin-cypress/src/support.js +3 -4
- package/packages/datadog-plugin-express/src/code_origin.js +1 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
- package/packages/datadog-plugin-graphql/src/execute.js +5 -5
- package/packages/datadog-plugin-grpc/src/util.js +1 -2
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +7 -10
- package/packages/datadog-plugin-mocha/src/webdriverio-video.js +8 -4
- package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
- package/packages/datadog-plugin-next/src/index.js +1 -2
- package/packages/datadog-plugin-openai/src/tracing.js +5 -2
- package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
- package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
- package/packages/datadog-plugin-postgres/src/index.js +24 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
- package/packages/datadog-plugin-vitest/src/index.js +5 -2
- package/packages/datadog-shimmer/src/shimmer.js +5 -4
- package/packages/datadog-webpack/index.js +55 -43
- package/packages/datadog-webpack/src/loader.js +56 -8
- package/packages/dd-trace/src/aiguard/evaluation.js +143 -1
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
- package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
- package/packages/dd-trace/src/aiguard/redaction.js +8 -2
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
- package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
- package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
- package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
- package/packages/dd-trace/src/appsec/iast/path-line.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
- package/packages/dd-trace/src/appsec/lambda.js +1 -3
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
- package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
- package/packages/dd-trace/src/appsec/reporter.js +21 -1
- package/packages/dd-trace/src/appsec/stack_trace.js +4 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
- package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
- package/packages/dd-trace/src/config/config-types.d.ts +2 -2
- package/packages/dd-trace/src/config/defaults.js +5 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +10 -0
- package/packages/dd-trace/src/config/helper.js +34 -3
- package/packages/dd-trace/src/config/index.js +55 -9
- package/packages/dd-trace/src/config/normalize-service.js +1 -1
- package/packages/dd-trace/src/config/parsers.js +2 -2
- package/packages/dd-trace/src/config/supported-configurations.json +44 -0
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -5
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -5
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +4 -6
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
- package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
- package/packages/dd-trace/src/debugger/unsupported-runtime.js +16 -0
- package/packages/dd-trace/src/dogstatsd.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/request.js +1 -5
- package/packages/dd-trace/src/id.js +14 -1
- package/packages/dd-trace/src/lambda/handler.js +179 -19
- package/packages/dd-trace/src/lambda/index.js +15 -1
- package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
- package/packages/dd-trace/src/llmobs/agent-manifest.js +19 -2
- package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +15 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +5 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +64 -2
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
- package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
- package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +15 -4
- package/packages/dd-trace/src/llmobs/span_processor.js +13 -2
- package/packages/dd-trace/src/llmobs/tagger.js +20 -10
- package/packages/dd-trace/src/llmobs/util.js +11 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +4 -5
- package/packages/dd-trace/src/log/log.js +1 -5
- package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +48 -21
- package/packages/dd-trace/src/openfeature/index.js +6 -0
- package/packages/dd-trace/src/openfeature/writers/util.js +4 -4
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
- package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +24 -24
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
- package/packages/dd-trace/src/otel-sampling.js +4 -5
- package/packages/dd-trace/src/otel-thread-ctx.js +79 -13
- package/packages/dd-trace/src/plugin_manager.js +1 -2
- package/packages/dd-trace/src/plugins/database.js +7 -16
- package/packages/dd-trace/src/plugins/tracing.js +0 -1
- package/packages/dd-trace/src/plugins/util/git.js +99 -59
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
- package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -1
- package/packages/dd-trace/src/plugins/util/test.js +50 -4
- package/packages/dd-trace/src/plugins/util/web.js +90 -20
- package/packages/dd-trace/src/priority_sampler.js +1 -2
- package/packages/dd-trace/src/profiling/profiler.js +4 -6
- package/packages/dd-trace/src/proxy.js +1 -2
- package/packages/dd-trace/src/ritm.js +4 -2
- package/packages/dd-trace/src/serverless.js +5 -0
- package/packages/dd-trace/src/span_processor.js +13 -17
- package/packages/dd-trace/src/span_stats.js +4 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +1 -1
- package/packages/dd-trace/src/util.js +37 -4
- package/packages/dd-trace/src/web-tags-cache.js +6 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +8 -8
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
- 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
|
@@ -1,16 +1,38 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
// Activated rewrites publish their module name to the plugin manager after evaluation.
|
|
4
|
-
//
|
|
4
|
+
// Integrations can also provide synchronous runtime setup before plugin activation.
|
|
5
|
+
// Setup must not load rewrite targets: re-entrant activations of the same group are dropped.
|
|
6
|
+
// activate: true covers every rewrite target in the entry; activate.modules narrows it to the packages
|
|
7
|
+
// that should trigger activation, leaving the rest of the entry rewrite-only.
|
|
5
8
|
// Other entries use hooks or another activation path, or do not need activation from a rewrite.
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {object} Activation
|
|
11
|
+
* @property {string} moduleName
|
|
12
|
+
* @property {string} [version]
|
|
13
|
+
*
|
|
14
|
+
* @typedef {object} ActivationConfig
|
|
15
|
+
* @property {string[]} [modules]
|
|
16
|
+
* @property {((activation: Activation) => void)} [setup]
|
|
17
|
+
*
|
|
18
|
+
* @typedef {object} InstrumentationRegistryEntry
|
|
19
|
+
* @property {true|ActivationConfig} [activate]
|
|
20
|
+
* @property {Array<{ module: { name: string } }>} instrumentations
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** @satisfies {InstrumentationRegistryEntry[]} */
|
|
6
24
|
const registry = [
|
|
7
25
|
{ instrumentations: require('./instrumentations/ai') },
|
|
8
26
|
{ activate: true, instrumentations: require('./instrumentations/azure-cosmos') },
|
|
9
27
|
{ instrumentations: require('./instrumentations/azure-durable-functions') },
|
|
10
28
|
{ activate: true, instrumentations: require('./instrumentations/bullmq') },
|
|
11
|
-
{
|
|
29
|
+
{
|
|
30
|
+
activate: { setup: () => require('../../claude-agent-sdk') },
|
|
31
|
+
instrumentations: require('./instrumentations/claude-agent-sdk'),
|
|
32
|
+
},
|
|
12
33
|
{ instrumentations: require('./instrumentations/graphql') },
|
|
13
34
|
{ instrumentations: require('./instrumentations/graphql-jit') },
|
|
35
|
+
{ instrumentations: require('./instrumentations/jest') },
|
|
14
36
|
{ activate: true, instrumentations: require('./instrumentations/langchain') },
|
|
15
37
|
{ activate: true, instrumentations: require('./instrumentations/langgraph') },
|
|
16
38
|
{ activate: true, instrumentations: require('./instrumentations/mercurius') },
|
|
@@ -18,15 +40,68 @@ const registry = [
|
|
|
18
40
|
{ instrumentations: require('./instrumentations/openai-agents') },
|
|
19
41
|
{ instrumentations: require('./instrumentations/playwright') },
|
|
20
42
|
{ activate: true, instrumentations: require('./instrumentations/postgres') },
|
|
43
|
+
{ instrumentations: require('./instrumentations/vitest') },
|
|
21
44
|
{ instrumentations: require('./instrumentations/webdriverio') },
|
|
22
|
-
{
|
|
45
|
+
{
|
|
46
|
+
activate: { setup: () => require('../../aws-durable-execution-sdk-js') },
|
|
47
|
+
instrumentations: require('./instrumentations/aws-durable-execution-sdk-js'),
|
|
48
|
+
},
|
|
23
49
|
{ activate: true, instrumentations: require('./instrumentations/supabase') },
|
|
24
50
|
]
|
|
25
51
|
|
|
26
52
|
const activatedModules = new Set()
|
|
53
|
+
/** @type {Map<string, (activation: Activation) => void>} */
|
|
54
|
+
const activationSetups = new Map()
|
|
27
55
|
for (const { activate, instrumentations } of registry) {
|
|
28
|
-
if (
|
|
29
|
-
|
|
56
|
+
if (activate === undefined) continue
|
|
57
|
+
if (activate !== true && (typeof activate !== 'object' || activate === null || Array.isArray(activate))) {
|
|
58
|
+
throw new TypeError('Instrumentation registry activate must be true or an activation config object')
|
|
59
|
+
}
|
|
60
|
+
const config = activate === true ? undefined : activate
|
|
61
|
+
const setup = config?.setup
|
|
62
|
+
if (setup !== undefined && typeof setup !== 'function') {
|
|
63
|
+
throw new TypeError('Instrumentation registry activate.setup must be a function')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const rewriteModules = new Set(instrumentations.map(({ module }) => module.name))
|
|
67
|
+
for (const moduleName of resolveActivationModules(config?.modules, rewriteModules)) {
|
|
68
|
+
if (activatedModules.has(moduleName) && activationSetups.get(moduleName) !== setup) {
|
|
69
|
+
throw new TypeError(`Instrumentation registry activation module "${moduleName}" has conflicting setup functions`)
|
|
70
|
+
}
|
|
71
|
+
activatedModules.add(moduleName)
|
|
72
|
+
if (setup) activationSetups.set(moduleName, setup)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Activation covers every rewrite target in the entry unless it names the packages to activate. An explicit
|
|
78
|
+
* list keeps helper packages that share the entry rewrite-only.
|
|
79
|
+
* @param {string[]|undefined} modules
|
|
80
|
+
* @param {Set<string>} rewriteModules
|
|
81
|
+
* @returns {Set<string>}
|
|
82
|
+
*/
|
|
83
|
+
function resolveActivationModules (modules, rewriteModules) {
|
|
84
|
+
if (modules === undefined) return rewriteModules
|
|
85
|
+
if (!Array.isArray(modules) || modules.length === 0) {
|
|
86
|
+
throw new TypeError('Instrumentation registry activate.modules must be a non-empty array')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const entryModules = new Set()
|
|
90
|
+
for (const moduleName of modules) {
|
|
91
|
+
if (typeof moduleName !== 'string' || moduleName.length === 0) {
|
|
92
|
+
throw new TypeError('Instrumentation registry activate.modules must contain non-empty strings')
|
|
93
|
+
}
|
|
94
|
+
if (!rewriteModules.has(moduleName)) {
|
|
95
|
+
throw new TypeError(
|
|
96
|
+
`Instrumentation registry activation module "${moduleName}" is not a rewrite target in its entry`
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
if (entryModules.has(moduleName)) {
|
|
100
|
+
throw new TypeError(`Instrumentation registry activation module "${moduleName}" is duplicated in its entry`)
|
|
101
|
+
}
|
|
102
|
+
entryModules.add(moduleName)
|
|
103
|
+
}
|
|
104
|
+
return entryModules
|
|
30
105
|
}
|
|
31
106
|
|
|
32
107
|
const instrumentations = registry.flatMap(entry => entry.instrumentations)
|
|
@@ -38,4 +113,12 @@ function isRewriteActivationEnabled (moduleName) {
|
|
|
38
113
|
return activatedModules.has(moduleName)
|
|
39
114
|
}
|
|
40
115
|
|
|
41
|
-
|
|
116
|
+
/**
|
|
117
|
+
* @param {string} moduleName
|
|
118
|
+
* @returns {((activation: Activation) => void)|undefined}
|
|
119
|
+
*/
|
|
120
|
+
function getActivationSetup (moduleName) {
|
|
121
|
+
return activationSetups.get(moduleName)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = { getActivationSetup, isRewriteActivationEnabled, instrumentations, registry }
|
package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js
CHANGED
|
@@ -26,11 +26,10 @@ const COMPILE_DEFERRED_FIELD = 'FunctionDeclaration[id.name="compileDeferredFiel
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* @param {GraphqlJitInstrumentation[]} instrumentations
|
|
30
29
|
* @param {string} versionRange
|
|
31
30
|
* @param {string} filePath
|
|
32
31
|
*/
|
|
33
|
-
function addInstrumentations (
|
|
32
|
+
function addInstrumentations (versionRange, filePath) {
|
|
34
33
|
const moduleDefinition = { name: 'graphql-jit', versionRange, filePath }
|
|
35
34
|
instrumentations.push(
|
|
36
35
|
{
|
|
@@ -75,9 +74,9 @@ function addInstrumentations (instrumentations, versionRange, filePath) {
|
|
|
75
74
|
const instrumentations = []
|
|
76
75
|
// graphql-jit 0.7 and 0.8.0 use this layout and remain compatible with GraphQL 15 and 16.
|
|
77
76
|
// GraphQL 17 compatibility starts at 0.8.1.
|
|
78
|
-
addInstrumentations(
|
|
79
|
-
addInstrumentations(
|
|
80
|
-
addInstrumentations(
|
|
81
|
-
addInstrumentations(
|
|
77
|
+
addInstrumentations('>=0.7.0 <0.8.5 || >=0.8.7 <0.9.0', 'dist/execution.js')
|
|
78
|
+
addInstrumentations('>=0.8.5 <0.8.7', 'dist/cjs/execution.js')
|
|
79
|
+
addInstrumentations('>=0.8.5 <0.8.7', 'dist/esm/execution.js')
|
|
80
|
+
addInstrumentations('>=0.8.7 <0.9.0', 'dist/execution.mjs')
|
|
82
81
|
|
|
83
82
|
module.exports = instrumentations
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = [
|
|
4
|
+
['>=24.8.0 <30.0.0', 'build/runTest.js'],
|
|
5
|
+
['>=30.0.0', 'build/index.js'],
|
|
6
|
+
['>=30.0.0', 'build/testWorker.js'],
|
|
7
|
+
].map(([versionRange, filePath]) => ({
|
|
8
|
+
module: { name: 'jest-runner', versionRange, filePath },
|
|
9
|
+
// Wrap the returned promise so completion covers both successful and failed teardown.
|
|
10
|
+
functionQuery: { functionName: 'runTestInternal', kind: 'Sync' },
|
|
11
|
+
channelName: 'runTestInternal',
|
|
12
|
+
}))
|
|
@@ -1,36 +1,53 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
module: {
|
|
5
|
-
name: 'postgres',
|
|
6
|
-
versionRange: '>=3.0.0',
|
|
7
|
-
filePath,
|
|
8
|
-
},
|
|
9
|
-
astQuery: 'Program',
|
|
10
|
-
transform: 'postgresQueryHandlers',
|
|
11
|
-
channelName: 'query',
|
|
12
|
-
}))
|
|
3
|
+
const instrumentations = []
|
|
13
4
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
for (const filePath of ['src/index.js', 'cjs/src/index.js']) {
|
|
6
|
+
instrumentations.push({
|
|
7
|
+
module: {
|
|
8
|
+
name: 'postgres',
|
|
9
|
+
versionRange: '>=3.0.0',
|
|
10
|
+
filePath,
|
|
11
|
+
},
|
|
12
|
+
astQuery: 'Program',
|
|
13
|
+
transform: 'postgresQueryHandlers',
|
|
14
|
+
channelName: 'query',
|
|
15
|
+
})
|
|
16
|
+
}
|
|
24
17
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
for (const filePath of ['src/connection.js', 'cjs/src/connection.js']) {
|
|
19
|
+
instrumentations.push({
|
|
20
|
+
module: {
|
|
21
|
+
name: 'postgres',
|
|
22
|
+
versionRange: '>=3.0.0',
|
|
23
|
+
filePath,
|
|
24
|
+
},
|
|
25
|
+
astQuery: 'Program',
|
|
26
|
+
transform: 'postgresQueryAcquire',
|
|
27
|
+
channelName: 'query:acquire',
|
|
28
|
+
}, {
|
|
29
|
+
module: {
|
|
30
|
+
name: 'postgres',
|
|
31
|
+
versionRange: '>=3.0.0',
|
|
32
|
+
filePath,
|
|
33
|
+
},
|
|
34
|
+
astQuery: 'Program',
|
|
35
|
+
transform: 'postgresQueryPreparation',
|
|
36
|
+
channelName: 'query:prepare',
|
|
37
|
+
})
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
for (const filePath of ['src/query.js', 'cjs/src/query.js']) {
|
|
41
|
+
instrumentations.push({
|
|
42
|
+
module: {
|
|
43
|
+
name: 'postgres',
|
|
44
|
+
versionRange: '>=3.0.0',
|
|
45
|
+
filePath,
|
|
46
|
+
},
|
|
47
|
+
astQuery: 'Program',
|
|
48
|
+
transform: 'postgresQueryLifecycle',
|
|
49
|
+
channelName: 'query',
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = instrumentations
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = ['dist/index.js', 'dist/chunk-hooks.js'].map(filePath => ({
|
|
4
|
+
module: { name: '@vitest/runner', versionRange: '>=1.6.0 <4.1.0', filePath },
|
|
5
|
+
astQuery: 'FunctionDeclaration[id.name="createSuiteCollector"] ' +
|
|
6
|
+
'VariableDeclarator[id.name="task"] > FunctionExpression',
|
|
7
|
+
channelName: 'createTestTask',
|
|
8
|
+
}))
|
package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js
CHANGED
|
@@ -506,9 +506,8 @@ module.exports = [
|
|
|
506
506
|
versionRange: '>=9.0.0',
|
|
507
507
|
filePath: 'build/index.js',
|
|
508
508
|
},
|
|
509
|
-
astQuery: 'TryStatement:has(CatchClause
|
|
510
|
-
'[
|
|
511
|
-
'[test.right.object.name="retries"][test.right.property.name="attempts"]) > BlockStatement',
|
|
509
|
+
astQuery: 'FunctionDeclaration[id.name="executeAsync"] TryStatement:has(CatchClause ' +
|
|
510
|
+
'CallExpression[callee.object.name="executeAsync"][callee.property.name="call"]) > BlockStatement',
|
|
512
511
|
channelName: 'executeAsync',
|
|
513
512
|
transform: 'awaitContextCallback',
|
|
514
513
|
transformOptions: {
|
|
@@ -521,10 +520,8 @@ module.exports = [
|
|
|
521
520
|
versionRange: '>=9.0.0',
|
|
522
521
|
filePath: 'build/index.js',
|
|
523
522
|
},
|
|
524
|
-
astQuery: 'FunctionDeclaration[id.name="executeAsync"] CatchClause ' +
|
|
525
|
-
'IfStatement[
|
|
526
|
-
'[test.left.property.name="limit"][test.right.object.name="retries"]' +
|
|
527
|
-
'[test.right.property.name="attempts"]',
|
|
523
|
+
astQuery: 'FunctionDeclaration[id.name="executeAsync"] CatchClause > BlockStatement > ' +
|
|
524
|
+
'IfStatement:has(CallExpression[callee.object.name="executeAsync"][callee.property.name="call"])',
|
|
528
525
|
channelName: 'executeAsync',
|
|
529
526
|
transform: 'awaitContextCallback',
|
|
530
527
|
transformOptions: {
|
|
@@ -540,7 +537,10 @@ module.exports = [
|
|
|
540
537
|
},
|
|
541
538
|
astQuery: 'AssignmentExpression[left.object.object.name="Spec"]' +
|
|
542
539
|
'[left.object.property.name="prototype"][left.property.name="execute"] > FunctionExpression',
|
|
540
|
+
// A method name keeps the original function expression, so the start context
|
|
541
|
+
// carries `self` (the legacy Spec) that the WebdriverIO Jasmine lifecycle reads.
|
|
543
542
|
functionQuery: {
|
|
543
|
+
methodName: 'execute',
|
|
544
544
|
kind: 'Sync',
|
|
545
545
|
},
|
|
546
546
|
channelName: 'Spec_execute',
|
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
"@supabase/realtime-js/dist/module/RealtimeChannel.js": "@supabase/realtime-js",
|
|
42
42
|
"@supabase/storage-js/dist/index.cjs": "@supabase/storage-js",
|
|
43
43
|
"@supabase/storage-js/dist/index.mjs": "@supabase/storage-js",
|
|
44
|
+
"@vitest/runner/dist/chunk-hooks.js": "@vitest/runner",
|
|
45
|
+
"@vitest/runner/dist/index.js": "@vitest/runner",
|
|
44
46
|
"@wdio/cli/build/index.js": "@wdio/cli",
|
|
45
47
|
"@wdio/config/build/node/index.js": "@wdio/config",
|
|
46
48
|
"@wdio/jasmine-framework/build/index.js": "@wdio/jasmine-framework",
|
|
@@ -76,6 +78,9 @@
|
|
|
76
78
|
"graphql/validation/validate.js": "graphql",
|
|
77
79
|
"graphql/validation/validate.mjs": "graphql",
|
|
78
80
|
"jasmine-core/lib/jasmine-core/jasmine.js": "jasmine-core",
|
|
81
|
+
"jest-runner/build/index.js": "jest-runner",
|
|
82
|
+
"jest-runner/build/runTest.js": "jest-runner",
|
|
83
|
+
"jest-runner/build/testWorker.js": "jest-runner",
|
|
79
84
|
"mercurius/index.js": "mercurius",
|
|
80
85
|
"playwright-core/lib/coreBundle.js": "playwright-core",
|
|
81
86
|
"playwright/lib/common/config.js": "playwright",
|
|
@@ -12,11 +12,37 @@ const POSTGRES_SIMPLE_DBM_QUERIES = '__ddTracePostgresSimpleDbmQueries'
|
|
|
12
12
|
const POSTGRES_STATEMENT = 'this.string ?? (this.tagged && this.strings?.length !== 1 ? undefined : this.strings?.[0])'
|
|
13
13
|
|
|
14
14
|
module.exports = {
|
|
15
|
+
postgresQueryAcquire,
|
|
15
16
|
postgresQueryHandlers,
|
|
16
17
|
postgresQueryLifecycle,
|
|
17
18
|
postgresQueryPreparation,
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @param {object} state
|
|
23
|
+
* @param {import('estree').Program} program
|
|
24
|
+
*/
|
|
25
|
+
function postgresQueryAcquire (state, program) {
|
|
26
|
+
const channelVariable = injectPostgresTracingChannel(state, program)
|
|
27
|
+
const executeFunctions = query(program, 'FunctionDeclaration[id.name="execute"]')
|
|
28
|
+
assert(executeFunctions.length === 1, 'postgresQueryAcquire: unexpected execute function count')
|
|
29
|
+
|
|
30
|
+
const execute = executeFunctions[0]
|
|
31
|
+
const queryParameter = execute.params[0]
|
|
32
|
+
assert(queryParameter?.type === 'Identifier', 'postgresQueryAcquire: execute query parameter changed')
|
|
33
|
+
assert(execute.body.type === 'BlockStatement', 'postgresQueryAcquire: execute body changed')
|
|
34
|
+
|
|
35
|
+
const body = execute.body.body
|
|
36
|
+
const executeIndex = body.findIndex(statement => statement.type === 'TryStatement')
|
|
37
|
+
assert(executeIndex !== -1, 'postgresQueryAcquire: execute try block changed')
|
|
38
|
+
|
|
39
|
+
body.splice(executeIndex, 0, ...parse(`
|
|
40
|
+
if (${channelVariable}.start.hasSubscribers) {
|
|
41
|
+
${channelVariable}.start.publish({ query: ${queryParameter.name} });
|
|
42
|
+
}
|
|
43
|
+
`).body)
|
|
44
|
+
}
|
|
45
|
+
|
|
20
46
|
/**
|
|
21
47
|
* Starts a Postgres.js query at the pool handler that owns its connection options.
|
|
22
48
|
*
|
|
@@ -154,6 +180,7 @@ function wrapPostgresHandler (handler, queryParameter, channelVariable) {
|
|
|
154
180
|
assert(handler.body.type === 'BlockStatement', 'postgresQueryHandlers: handler body changed')
|
|
155
181
|
assert(!handler.async && !handler.generator, 'postgresQueryHandlers: unsupported handler kind')
|
|
156
182
|
|
|
183
|
+
// Direct handoffs publish before the handler returns, so they record zero pool wait.
|
|
157
184
|
const originalBody = handler.body.body
|
|
158
185
|
const wrapperBody = parse(`
|
|
159
186
|
function wrapper () {
|
|
@@ -167,12 +194,18 @@ function wrapPostgresHandler (handler, queryParameter, channelVariable) {
|
|
|
167
194
|
__ddTraceContext.host = ${POSTGRES_OPTIONS}.host[0];
|
|
168
195
|
__ddTraceContext.port = ${POSTGRES_OPTIONS}.port[0];
|
|
169
196
|
}
|
|
170
|
-
|
|
197
|
+
const __ddTraceResult = ${channelVariable}.start.runStores(__ddTraceContext, () => {});
|
|
198
|
+
if (!__ddTraceContext.poolWaitFinished) {
|
|
199
|
+
__ddTraceContext.poolWaitStartMs = performance.now();
|
|
200
|
+
}
|
|
201
|
+
return __ddTraceResult;
|
|
171
202
|
}
|
|
172
203
|
}
|
|
173
204
|
`).body[0].body.body
|
|
174
205
|
|
|
175
|
-
wrapperBody[0]
|
|
206
|
+
const tracingCalls = query(wrapperBody[0], 'CallExpression[callee.property.name="runStores"]')
|
|
207
|
+
assert(tracingCalls.length === 1, 'postgresQueryHandlers: runStores call changed')
|
|
208
|
+
tracingCalls[0].arguments[1].body.body = originalBody
|
|
176
209
|
handler.body.body = [...wrapperBody, ...originalBody]
|
|
177
210
|
}
|
|
178
211
|
|
|
@@ -272,8 +305,13 @@ function findPostgresQueryIdentifier (program) {
|
|
|
272
305
|
|
|
273
306
|
const declarations = query(program, 'VariableDeclarator[id.type="ObjectPattern"]')
|
|
274
307
|
for (const declaration of declarations) {
|
|
275
|
-
if (
|
|
276
|
-
|
|
308
|
+
if (
|
|
309
|
+
declaration.init?.type !== 'CallExpression' ||
|
|
310
|
+
declaration.init.callee.name !== 'require' ||
|
|
311
|
+
declaration.init.arguments[0]?.value !== './query.js'
|
|
312
|
+
) {
|
|
313
|
+
continue
|
|
314
|
+
}
|
|
277
315
|
|
|
278
316
|
for (const property of declaration.id.properties) {
|
|
279
317
|
if (property.type === 'Property' && property.key.name === 'Query' && property.value.type === 'Identifier') {
|
|
@@ -140,8 +140,7 @@ function awaitContextCallback (state, node, _parent, ancestry) {
|
|
|
140
140
|
const generatedCallback = createAwaitedContextCallback(
|
|
141
141
|
state,
|
|
142
142
|
insertionTarget,
|
|
143
|
-
callbackAncestry
|
|
144
|
-
'awaitContextCallback'
|
|
143
|
+
callbackAncestry
|
|
145
144
|
)
|
|
146
145
|
if (!generatedCallback) return
|
|
147
146
|
|
|
@@ -158,8 +157,7 @@ function awaitContextCallback (state, node, _parent, ancestry) {
|
|
|
158
157
|
const generatedCallback = createAwaitedContextCallback(
|
|
159
158
|
state,
|
|
160
159
|
node.consequent,
|
|
161
|
-
ancestry
|
|
162
|
-
'awaitContextCallback'
|
|
160
|
+
ancestry
|
|
163
161
|
)
|
|
164
162
|
if (!generatedCallback) return
|
|
165
163
|
|
|
@@ -181,18 +179,17 @@ function awaitContextCallback (state, node, _parent, ancestry) {
|
|
|
181
179
|
* @param {Parameters<typeof awaitContextCallback>[0]} state
|
|
182
180
|
* @param {import('estree').BlockStatement} insertionTarget
|
|
183
181
|
* @param {import('estree').Node[]} ancestry
|
|
184
|
-
* @param {string} transformName
|
|
185
182
|
* @returns {{
|
|
186
183
|
* callbackStatements: import('estree').Statement[],
|
|
187
184
|
* callbackVariable: string
|
|
188
185
|
* }|undefined}
|
|
189
186
|
*/
|
|
190
|
-
function createAwaitedContextCallback (state, insertionTarget, ancestry
|
|
187
|
+
function createAwaitedContextCallback (state, insertionTarget, ancestry) {
|
|
191
188
|
const { callbackArgumentNames = [], callbackName, callbackThis = false } = state.transformOptions ?? {}
|
|
192
189
|
|
|
193
|
-
assert(identifierPattern.test(callbackName),
|
|
190
|
+
assert(identifierPattern.test(callbackName), 'awaitContextCallback: callbackName must be an identifier')
|
|
194
191
|
assert(Array.isArray(callbackArgumentNames) && callbackArgumentNames.every(name => identifierPattern.test(name)),
|
|
195
|
-
|
|
192
|
+
'awaitContextCallback: callbackArgumentNames must be identifiers')
|
|
196
193
|
|
|
197
194
|
let enclosingFunction
|
|
198
195
|
let hasTraceWrapper = false
|
|
@@ -215,8 +212,8 @@ function createAwaitedContextCallback (state, insertionTarget, ancestry, transfo
|
|
|
215
212
|
hasTraceWrapper ||= hasContextBinding && hasTracedBinding
|
|
216
213
|
}
|
|
217
214
|
|
|
218
|
-
assert(enclosingFunction?.async,
|
|
219
|
-
assert(hasTraceWrapper,
|
|
215
|
+
assert(enclosingFunction?.async, 'awaitContextCallback: expected an enclosing async function')
|
|
216
|
+
assert(hasTraceWrapper, 'awaitContextCallback: expected an enclosing trace wrapper')
|
|
220
217
|
|
|
221
218
|
const callbackVariable = `__apm$${callbackName}`
|
|
222
219
|
if (query(insertionTarget, `[id.name="${callbackVariable}"]`).length > 0) return
|
|
@@ -14,9 +14,7 @@ const connectionOptionsCache = new WeakMap()
|
|
|
14
14
|
|
|
15
15
|
function wrapRedis (Redis) {
|
|
16
16
|
shimmer.wrap(Redis.prototype, 'sendCommand', sendCommand => function (command, stream) {
|
|
17
|
-
if (!startCh.hasSubscribers) return sendCommand.call(this, command, stream)
|
|
18
|
-
|
|
19
|
-
if (!command?.promise) return sendCommand.call(this, command, stream)
|
|
17
|
+
if (!startCh.hasSubscribers || !command?.promise) return sendCommand.call(this, command, stream)
|
|
20
18
|
|
|
21
19
|
const options = this.options || {}
|
|
22
20
|
let connectionOptions = connectionOptionsCache.get(this)
|
|
@@ -32,7 +30,7 @@ function wrapRedis (Redis) {
|
|
|
32
30
|
connectionName: options.connectionName,
|
|
33
31
|
}
|
|
34
32
|
return startCh.runStores(ctx, () => {
|
|
35
|
-
command.promise.then(() => finish(
|
|
33
|
+
command.promise.then(() => finish(ctx), err => finish(ctx, err))
|
|
36
34
|
|
|
37
35
|
return sendCommand.call(this, command, stream)
|
|
38
36
|
})
|
|
@@ -51,7 +49,11 @@ addHook({ name: 'ioredis', versions: ['>=4.11.0 <5'], file: 'built/redis/index.j
|
|
|
51
49
|
|
|
52
50
|
addHook({ name: 'ioredis', versions: ['>=5'] }, wrapRedis)
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
/**
|
|
53
|
+
* @param {Record<string, unknown> & { error?: Error }} ctx
|
|
54
|
+
* @param {Error} [error]
|
|
55
|
+
*/
|
|
56
|
+
function finish (ctx, error) {
|
|
55
57
|
if (error) {
|
|
56
58
|
ctx.error = error
|
|
57
59
|
errorCh.publish(ctx)
|
|
@@ -12,9 +12,7 @@ const errorCh = channel('apm:iovalkey:command:error')
|
|
|
12
12
|
|
|
13
13
|
addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
14
14
|
shimmer.wrap(Valkey.prototype, 'sendCommand', sendCommand => function (command, stream) {
|
|
15
|
-
if (!startCh.hasSubscribers) return sendCommand.apply(this, arguments)
|
|
16
|
-
|
|
17
|
-
if (!command?.promise) return sendCommand.apply(this, arguments)
|
|
15
|
+
if (!startCh.hasSubscribers || !command?.promise) return sendCommand.apply(this, arguments)
|
|
18
16
|
|
|
19
17
|
const options = this.options || {}
|
|
20
18
|
const connectionName = options.connectionName
|
|
@@ -22,7 +20,7 @@ addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
|
22
20
|
|
|
23
21
|
const ctx = { command: command.name, args: command.args, connectionOptions, connectionName }
|
|
24
22
|
return startCh.runStores(ctx, () => {
|
|
25
|
-
command.promise.then(() => finish(
|
|
23
|
+
command.promise.then(() => finish(ctx), err => finish(ctx, err))
|
|
26
24
|
|
|
27
25
|
try {
|
|
28
26
|
return sendCommand.apply(this, arguments)
|
|
@@ -37,7 +35,11 @@ addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
|
37
35
|
return Valkey
|
|
38
36
|
})
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
/**
|
|
39
|
+
* @param {Record<string, unknown> & { error?: Error }} ctx
|
|
40
|
+
* @param {Error} [error]
|
|
41
|
+
*/
|
|
42
|
+
function finish (ctx, error) {
|
|
41
43
|
if (error) {
|
|
42
44
|
ctx.error = error
|
|
43
45
|
errorCh.publish(ctx)
|