dd-trace 5.103.0 → 5.105.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/LICENSE-3rdparty.csv +90 -102
- package/index.d.ts +107 -6
- package/package.json +18 -17
- package/packages/datadog-core/src/storage.js +1 -1
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/ai.js +8 -7
- package/packages/datadog-instrumentations/src/aws-sdk.js +15 -2
- package/packages/datadog-instrumentations/src/azure-cosmos.js +7 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +3 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -2
- package/packages/datadog-instrumentations/src/cucumber.js +181 -35
- package/packages/datadog-instrumentations/src/dns.js +54 -18
- package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
- package/packages/datadog-instrumentations/src/fastify.js +142 -82
- package/packages/datadog-instrumentations/src/graphql.js +188 -67
- package/packages/datadog-instrumentations/src/grpc/client.js +48 -32
- package/packages/datadog-instrumentations/src/helpers/ai-messages.js +322 -14
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/kafka.js +17 -0
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +269 -0
- package/packages/datadog-instrumentations/src/helpers/promise-instrumentor.js +42 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +3 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +19 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-cosmos.js +50 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +85 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +31 -229
- package/packages/datadog-instrumentations/src/hono.js +54 -3
- package/packages/datadog-instrumentations/src/http/client.js +2 -2
- package/packages/datadog-instrumentations/src/http/server.js +9 -4
- package/packages/datadog-instrumentations/src/ioredis.js +3 -3
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +163 -0
- package/packages/datadog-instrumentations/src/jest.js +390 -183
- package/packages/datadog-instrumentations/src/kafkajs.js +140 -17
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/memcached.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +399 -107
- package/packages/datadog-instrumentations/src/mocha/utils.js +48 -8
- package/packages/datadog-instrumentations/src/mongodb-core.js +1 -1
- package/packages/datadog-instrumentations/src/mongoose.js +10 -12
- package/packages/datadog-instrumentations/src/mysql.js +2 -2
- package/packages/datadog-instrumentations/src/mysql2.js +1 -1
- package/packages/datadog-instrumentations/src/nats.js +182 -0
- package/packages/datadog-instrumentations/src/nyc.js +38 -1
- package/packages/datadog-instrumentations/src/openai.js +33 -18
- package/packages/datadog-instrumentations/src/oracledb.js +6 -1
- package/packages/datadog-instrumentations/src/pg.js +1 -1
- package/packages/datadog-instrumentations/src/pino.js +17 -5
- package/packages/datadog-instrumentations/src/playwright.js +537 -297
- package/packages/datadog-instrumentations/src/router.js +80 -34
- package/packages/datadog-instrumentations/src/stripe.js +1 -1
- package/packages/datadog-instrumentations/src/vitest.js +246 -149
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-azure-cosmos/src/index.js +144 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +1 -1
- package/packages/datadog-plugin-bunyan/src/index.js +28 -0
- package/packages/datadog-plugin-cucumber/src/index.js +17 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +223 -45
- package/packages/datadog-plugin-cypress/src/support.js +69 -1
- package/packages/datadog-plugin-dns/src/lookup.js +8 -6
- package/packages/datadog-plugin-elasticsearch/src/index.js +28 -8
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +2 -0
- package/packages/datadog-plugin-graphql/src/resolve.js +64 -67
- package/packages/datadog-plugin-graphql/src/utils.js +4 -1
- package/packages/datadog-plugin-http/src/server.js +40 -15
- package/packages/datadog-plugin-jest/src/index.js +11 -3
- package/packages/datadog-plugin-jest/src/util.js +15 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +35 -0
- package/packages/datadog-plugin-langgraph/src/stream.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +19 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +311 -35
- package/packages/datadog-plugin-nats/src/consumer.js +43 -0
- package/packages/datadog-plugin-nats/src/index.js +20 -0
- package/packages/datadog-plugin-nats/src/producer.js +62 -0
- package/packages/datadog-plugin-nats/src/util.js +33 -0
- package/packages/datadog-plugin-next/src/index.js +5 -3
- package/packages/datadog-plugin-openai/src/tracing.js +15 -2
- package/packages/datadog-plugin-oracledb/src/index.js +13 -2
- package/packages/datadog-plugin-pino/src/index.js +42 -0
- package/packages/datadog-plugin-playwright/src/index.js +4 -4
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-redis/src/index.js +37 -2
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +33 -44
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-undici/src/index.js +19 -0
- package/packages/datadog-plugin-vitest/src/index.js +24 -20
- package/packages/datadog-plugin-winston/src/index.js +30 -0
- package/packages/datadog-shimmer/src/shimmer.js +49 -21
- package/packages/dd-trace/src/aiguard/index.js +1 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/blocking.js +2 -2
- package/packages/dd-trace/src/appsec/index.js +11 -4
- package/packages/dd-trace/src/appsec/reporter.js +24 -11
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/utils.js +1 -1
- package/packages/dd-trace/src/appsec/user_tracking.js +5 -4
- package/packages/dd-trace/src/baggage.js +7 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +0 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +25 -13
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +5 -3
- package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +70 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +7 -2
- package/packages/dd-trace/src/config/supported-configurations.json +36 -8
- package/packages/dd-trace/src/crashtracking/crashtracker.js +15 -3
- package/packages/dd-trace/src/datastreams/context.js +4 -2
- package/packages/dd-trace/src/datastreams/writer.js +2 -4
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -8
- package/packages/dd-trace/src/encode/0.4.js +124 -108
- package/packages/dd-trace/src/encode/0.5.js +114 -26
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +57 -42
- package/packages/dd-trace/src/encode/agentless-json.js +4 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +32 -13
- package/packages/dd-trace/src/encode/span-stats.js +16 -16
- package/packages/dd-trace/src/encode/tags-processors.js +16 -0
- package/packages/dd-trace/src/exporters/common/agents.js +3 -1
- package/packages/dd-trace/src/exporters/common/request.js +3 -1
- package/packages/dd-trace/src/id.js +17 -4
- package/packages/dd-trace/src/lambda/handler.js +2 -4
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +9 -7
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +10 -16
- package/packages/dd-trace/src/llmobs/span_processor.js +3 -3
- package/packages/dd-trace/src/llmobs/tagger.js +9 -1
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/util.js +66 -3
- package/packages/dd-trace/src/log/index.js +1 -1
- package/packages/dd-trace/src/log/writer.js +3 -1
- package/packages/dd-trace/src/msgpack/chunk.js +394 -10
- package/packages/dd-trace/src/msgpack/index.js +96 -2
- package/packages/dd-trace/src/noop/span.js +3 -1
- package/packages/dd-trace/src/openfeature/encoding.js +70 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +20 -0
- package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +143 -0
- package/packages/dd-trace/src/openfeature/span-enrichment.js +149 -0
- package/packages/dd-trace/src/openfeature/writers/exposures.js +51 -20
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +4 -3
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +18 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +62 -67
- package/packages/dd-trace/src/opentracing/span.js +59 -19
- package/packages/dd-trace/src/opentracing/span_context.js +49 -0
- package/packages/dd-trace/src/plugins/apollo.js +3 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +23 -33
- package/packages/dd-trace/src/plugins/database.js +7 -6
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_injection.js +56 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -46
- package/packages/dd-trace/src/plugins/outbound.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +15 -17
- package/packages/dd-trace/src/plugins/tracing.js +48 -8
- package/packages/dd-trace/src/plugins/util/git.js +3 -1
- package/packages/dd-trace/src/plugins/util/test.js +318 -13
- package/packages/dd-trace/src/plugins/util/web.js +89 -64
- package/packages/dd-trace/src/priority_sampler.js +2 -2
- package/packages/dd-trace/src/profiling/profiler.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +10 -4
- package/packages/dd-trace/src/sampling_rule.js +7 -7
- package/packages/dd-trace/src/scope.js +7 -5
- package/packages/dd-trace/src/service-naming/extra-services.js +14 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +10 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/source-resolver.js +46 -0
- package/packages/dd-trace/src/span_format.js +190 -58
- package/packages/dd-trace/src/spanleak.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -3
- package/packages/dd-trace/src/tagger.js +0 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +70 -39
- package/vendor/dist/@datadog/sketches-js/LICENSE +10 -36
- 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/packages/dd-trace/src/msgpack/encoder.js +0 -308
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +0 -9
- package/vendor/dist/opentracing/LICENSE +0 -201
- package/vendor/dist/opentracing/binary_carrier.d.ts +0 -11
- package/vendor/dist/opentracing/constants.d.ts +0 -61
- package/vendor/dist/opentracing/examples/demo/demo.d.ts +0 -2
- package/vendor/dist/opentracing/ext/tags.d.ts +0 -90
- package/vendor/dist/opentracing/functions.d.ts +0 -20
- package/vendor/dist/opentracing/global_tracer.d.ts +0 -14
- package/vendor/dist/opentracing/index.d.ts +0 -12
- package/vendor/dist/opentracing/index.js +0 -1
- package/vendor/dist/opentracing/mock_tracer/index.d.ts +0 -5
- package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +0 -13
- package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +0 -16
- package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +0 -50
- package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +0 -26
- package/vendor/dist/opentracing/noop.d.ts +0 -8
- package/vendor/dist/opentracing/reference.d.ts +0 -33
- package/vendor/dist/opentracing/span.d.ts +0 -147
- package/vendor/dist/opentracing/span_context.d.ts +0 -26
- package/vendor/dist/opentracing/test/api_compatibility.d.ts +0 -16
- package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +0 -3
- package/vendor/dist/opentracing/test/noop_implementation.d.ts +0 -4
- package/vendor/dist/opentracing/test/opentracing_api.d.ts +0 -3
- package/vendor/dist/opentracing/test/unittest.d.ts +0 -2
- package/vendor/dist/opentracing/tracer.d.ts +0 -127
|
@@ -13,12 +13,12 @@ const tracers = new WeakSet()
|
|
|
13
13
|
const wrappedModels = new WeakSet()
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Publishes already-converted AI
|
|
16
|
+
* Publishes already-converted AI-style messages to the AI Guard evaluation channel.
|
|
17
17
|
*
|
|
18
|
-
* @param {Array<object>} messages - AI
|
|
18
|
+
* @param {Array<object>} messages - AI-style messages to evaluate.
|
|
19
19
|
* @returns {Promise<void>}
|
|
20
20
|
*/
|
|
21
|
-
function
|
|
21
|
+
function publishEvaluation (messages) {
|
|
22
22
|
return new Promise((resolve, reject) => {
|
|
23
23
|
aiguardChannel.publish({ messages, integration: 'ai', resolve, reject })
|
|
24
24
|
})
|
|
@@ -47,10 +47,11 @@ function wrapModelWithAIGuard (model) {
|
|
|
47
47
|
|
|
48
48
|
// Run AI Guard input evaluation and LLM call in parallel.
|
|
49
49
|
// The LLM has no side effects so it is safe to discard its result if AI Guard blocks.
|
|
50
|
-
return Promise.all([
|
|
50
|
+
return Promise.all([publishEvaluation(inputMessages), originalResult])
|
|
51
51
|
.then(([, result]) => {
|
|
52
52
|
if (!result.content?.length) return result
|
|
53
|
-
|
|
53
|
+
const outputMessages = buildOutputMessages(inputMessages, result.content)
|
|
54
|
+
return publishEvaluation(outputMessages)
|
|
54
55
|
.then(() => result)
|
|
55
56
|
})
|
|
56
57
|
}
|
|
@@ -70,7 +71,7 @@ function wrapModelWithAIGuard (model) {
|
|
|
70
71
|
|
|
71
72
|
// Run AI Guard input evaluation and LLM call in parallel.
|
|
72
73
|
// The LLM has no side effects so it is safe to discard its result if AI Guard blocks.
|
|
73
|
-
return Promise.all([
|
|
74
|
+
return Promise.all([publishEvaluation(inputMessages), originalResult])
|
|
74
75
|
.then(([, result]) => {
|
|
75
76
|
const chunks = []
|
|
76
77
|
const reader = result.stream.getReader()
|
|
@@ -89,7 +90,7 @@ function wrapModelWithAIGuard (model) {
|
|
|
89
90
|
const content = toolCalls.length ? toolCalls : text ? [{ type: 'text', text }] : []
|
|
90
91
|
|
|
91
92
|
const evaluate = content.length
|
|
92
|
-
?
|
|
93
|
+
? publishEvaluation(buildOutputMessages(inputMessages, content))
|
|
93
94
|
: Promise.resolve()
|
|
94
95
|
|
|
95
96
|
return evaluate.then(() => {
|
|
@@ -198,7 +198,7 @@ function wrapSmithySend (send) {
|
|
|
198
198
|
})
|
|
199
199
|
|
|
200
200
|
if (typeof cb === 'function') {
|
|
201
|
-
args[args.length - 1] = shimmer.
|
|
201
|
+
args[args.length - 1] = shimmer.wrapCallback(cb, cb => function (err, result) {
|
|
202
202
|
addResponse(ctx, err, result)
|
|
203
203
|
|
|
204
204
|
handleCompletion(result, ctx, channels)
|
|
@@ -270,7 +270,7 @@ function handleCompletion (result, ctx, channels) {
|
|
|
270
270
|
|
|
271
271
|
function wrapCb (cb, channels, ctx) {
|
|
272
272
|
// eslint-disable-next-line n/handle-callback-err
|
|
273
|
-
return shimmer.
|
|
273
|
+
return shimmer.wrapCallback(cb, cb => function wrappedCb (err, response) {
|
|
274
274
|
ctx = { request: ctx.request, response }
|
|
275
275
|
return channels.responseStart.runStores(ctx, () => {
|
|
276
276
|
try {
|
|
@@ -324,6 +324,19 @@ addHook({ name: '@aws-sdk/smithy-client', versions: ['>=3'] }, smithy => {
|
|
|
324
324
|
return smithy
|
|
325
325
|
})
|
|
326
326
|
|
|
327
|
+
// `@aws-sdk/client-*` >= 3.1046.0 dropped `@smithy/smithy-client` and now
|
|
328
|
+
// extends from `@smithy/core/client` directly. The `Client.send` contract is
|
|
329
|
+
// unchanged, but the host module moved -- patch the new home so the v3 hooks
|
|
330
|
+
// keep firing.
|
|
331
|
+
addHook({
|
|
332
|
+
name: '@smithy/core',
|
|
333
|
+
file: 'dist-cjs/submodules/client/index.js',
|
|
334
|
+
versions: ['>=3.24.0'],
|
|
335
|
+
}, smithyCoreClient => {
|
|
336
|
+
shimmer.wrap(smithyCoreClient.Client.prototype, 'send', wrapSmithySend)
|
|
337
|
+
return smithyCoreClient
|
|
338
|
+
})
|
|
339
|
+
|
|
327
340
|
addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
|
|
328
341
|
shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
|
|
329
342
|
return function wrappedSetPromisesDependency (dep) {
|
|
@@ -26,6 +26,9 @@ addHook({ name: '@azure/functions', versions: ['>=4'], patchDefault: false }, (a
|
|
|
26
26
|
// Event Hub triggers
|
|
27
27
|
shimmer.wrap(app, 'eventHub', wrapHandler)
|
|
28
28
|
|
|
29
|
+
// CosmosDB triggers
|
|
30
|
+
shimmer.wrap(app, 'cosmosDB', wrapHandler)
|
|
31
|
+
|
|
29
32
|
return azureFunction
|
|
30
33
|
})
|
|
31
34
|
|
|
@@ -29,9 +29,12 @@ addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
|
|
|
29
29
|
|
|
30
30
|
try {
|
|
31
31
|
const res = batch.apply(this, arguments)
|
|
32
|
-
if (typeof res === 'function'
|
|
32
|
+
if (typeof res === 'function') {
|
|
33
33
|
return wrapCallback(finishCh, errorCh, startCtx, res)
|
|
34
34
|
}
|
|
35
|
+
if (!res) {
|
|
36
|
+
return res
|
|
37
|
+
}
|
|
35
38
|
return res.then(
|
|
36
39
|
() => finish(finishCh, errorCh, startCtx),
|
|
37
40
|
err => finish(finishCh, errorCh, startCtx, err)
|
|
@@ -162,7 +165,7 @@ function finish (finishCh, errorCh, ctx, error) {
|
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
function wrapCallback (finishCh, errorCh, ctx, callback) {
|
|
165
|
-
return shimmer.
|
|
168
|
+
return shimmer.wrapCallback(callback, callback => function (err) {
|
|
166
169
|
if (err) {
|
|
167
170
|
ctx.error = err
|
|
168
171
|
errorCh.publish(ctx)
|
|
@@ -7,19 +7,26 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
7
7
|
const log = require('../../dd-trace/src/log')
|
|
8
8
|
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
9
9
|
const {
|
|
10
|
-
|
|
10
|
+
getCoveredFilesFromCoverage,
|
|
11
|
+
getExecutableFilesFromCoverage,
|
|
11
12
|
resetCoverage,
|
|
12
13
|
mergeCoverage,
|
|
13
14
|
fromCoverageMapToCoverage,
|
|
14
15
|
getTestSuitePath,
|
|
16
|
+
getRelativeCoverageFiles,
|
|
15
17
|
CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
|
|
16
18
|
getIsFaultyEarlyFlakeDetection,
|
|
17
19
|
getEfdRetryCount,
|
|
20
|
+
getMaxEfdRetryCount,
|
|
21
|
+
applySkippedCoverageToCoverage,
|
|
22
|
+
getTestCoverageLinesPercentage,
|
|
18
23
|
recordAttemptToFixExecution,
|
|
19
24
|
collectAttemptToFixExecutionsFromTraces,
|
|
20
25
|
logAttemptToFixTestExecution,
|
|
21
26
|
logTestOptimizationSummary,
|
|
27
|
+
getTestOptimizationRequestResults,
|
|
22
28
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
29
|
+
const { writeCoverageBackfillToCache } = require('../../dd-trace/src/ci-visibility/test-optimization-cache')
|
|
23
30
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
24
31
|
const { addHook, channel } = require('./helpers/instrument')
|
|
25
32
|
|
|
@@ -51,6 +58,8 @@ const itrSkippedSuitesCh = channel('ci:cucumber:itr:skipped-suites')
|
|
|
51
58
|
|
|
52
59
|
const getCodeCoverageCh = channel('ci:nyc:get-coverage')
|
|
53
60
|
|
|
61
|
+
const DD_EFD_RETRY_COUNT_MESSAGE = '_ddEfdRetryCount'
|
|
62
|
+
|
|
54
63
|
const isMarkedAsUnskippable = (pickle) => {
|
|
55
64
|
return pickle.tags.some(tag => tag.name === '@datadog:unskippable')
|
|
56
65
|
}
|
|
@@ -67,7 +76,7 @@ const atrStatusesByScenarioKey = new Map()
|
|
|
67
76
|
const numRetriesByPickleId = new Map()
|
|
68
77
|
const efdRetryCountByPickleId = new Map()
|
|
69
78
|
const efdSlowAbortedPickleIds = new Set()
|
|
70
|
-
const
|
|
79
|
+
const finishedParallelSuites = new Set()
|
|
71
80
|
const numAttemptToCtx = new Map()
|
|
72
81
|
const newTestsByTestFullname = new Map()
|
|
73
82
|
const attemptToFixTestsByTestFullname = new Map()
|
|
@@ -82,10 +91,14 @@ let pickleByFile = {}
|
|
|
82
91
|
const pickleResultByFile = {}
|
|
83
92
|
|
|
84
93
|
let skippableSuites = []
|
|
94
|
+
let skippableSuitesCoverage = {}
|
|
95
|
+
let skippedSuitesCoverage = {}
|
|
85
96
|
let itrCorrelationId = ''
|
|
86
97
|
let isForcedToRun = false
|
|
87
98
|
let isUnskippable = false
|
|
99
|
+
let isItrEnabled = false
|
|
88
100
|
let isSuitesSkippingEnabled = false
|
|
101
|
+
let isCoverageReportUploadEnabled = false
|
|
89
102
|
let isEarlyFlakeDetectionEnabled = false
|
|
90
103
|
let earlyFlakeDetectionNumRetries = 0
|
|
91
104
|
let earlyFlakeDetectionSlowTestRetries = {}
|
|
@@ -102,11 +115,55 @@ let numTestRetries = 0
|
|
|
102
115
|
let knownTests = {}
|
|
103
116
|
let skippedSuites = []
|
|
104
117
|
let isSuitesSkipped = false
|
|
118
|
+
let repositoryRoot
|
|
105
119
|
|
|
106
120
|
function isValidKnownTests (receivedKnownTests) {
|
|
107
121
|
return !!receivedKnownTests.cucumber
|
|
108
122
|
}
|
|
109
123
|
|
|
124
|
+
function hasSkippableSuitesCoverage () {
|
|
125
|
+
return skippableSuitesCoverage &&
|
|
126
|
+
typeof skippableSuitesCoverage === 'object' &&
|
|
127
|
+
Object.keys(skippableSuitesCoverage).length > 0
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function isTiaCoverageBackfillEnabled () {
|
|
131
|
+
return isItrEnabled && isCoverageReportUploadEnabled
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getCoverageRootDir () {
|
|
135
|
+
return repositoryRoot || process.cwd()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function shouldReportCodeCoverageLinesPct (hasBackfilledCoverage) {
|
|
139
|
+
return !isSuitesSkipped || hasBackfilledCoverage
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function getSkippedSuitesCoverageForRun () {
|
|
143
|
+
return isSuitesSkipped && isTiaCoverageBackfillEnabled() && hasSkippableSuitesCoverage()
|
|
144
|
+
? skippableSuitesCoverage
|
|
145
|
+
: {}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function applySkippedCoverageToCucumberCoverageMap () {
|
|
149
|
+
if (!isTiaCoverageBackfillEnabled()) return false
|
|
150
|
+
return applySkippedCoverageToCoverage(originalCoverageMap, skippedSuitesCoverage, getCoverageRootDir())
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function getCucumberTestSessionCoverageFiles () {
|
|
154
|
+
return getRelativeCoverageFiles(getExecutableFilesFromCoverage(originalCoverageMap), getCoverageRootDir())
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function resetSuiteSkippingRunState () {
|
|
158
|
+
skippableSuites = []
|
|
159
|
+
skippableSuitesCoverage = {}
|
|
160
|
+
skippedSuitesCoverage = {}
|
|
161
|
+
skippedSuites = []
|
|
162
|
+
isSuitesSkipped = false
|
|
163
|
+
repositoryRoot = undefined
|
|
164
|
+
writeCoverageBackfillToCache({})
|
|
165
|
+
}
|
|
166
|
+
|
|
110
167
|
function getSuiteStatusFromTestStatuses (testStatuses) {
|
|
111
168
|
if (testStatuses.includes('fail')) {
|
|
112
169
|
return 'fail'
|
|
@@ -117,6 +174,68 @@ function getSuiteStatusFromTestStatuses (testStatuses) {
|
|
|
117
174
|
return 'pass'
|
|
118
175
|
}
|
|
119
176
|
|
|
177
|
+
function getConfiguredEfdRetryCount () {
|
|
178
|
+
const maxSlowTestRetryCount = getMaxEfdRetryCount(earlyFlakeDetectionSlowTestRetries)
|
|
179
|
+
return maxSlowTestRetryCount || earlyFlakeDetectionNumRetries
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function publishWorkerEfdRetryCount (pickle, retryCount) {
|
|
183
|
+
if (typeof process.send !== 'function') return
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
process.send({
|
|
187
|
+
[DD_EFD_RETRY_COUNT_MESSAGE]: {
|
|
188
|
+
pickleId: pickle.id,
|
|
189
|
+
retryCount,
|
|
190
|
+
testFileAbsolutePath: pickle.uri,
|
|
191
|
+
testName: pickle.name,
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
} catch {
|
|
195
|
+
// ignore IPC errors
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function finishParallelSuiteIfDone (testFileAbsolutePath) {
|
|
200
|
+
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
201
|
+
const expectedPickles = pickleByFile[testFileAbsolutePath]
|
|
202
|
+
|
|
203
|
+
if (!finished || !expectedPickles || finished.length !== expectedPickles.length) return
|
|
204
|
+
if (finishedParallelSuites.has(testFileAbsolutePath)) return
|
|
205
|
+
|
|
206
|
+
finishedParallelSuites.add(testFileAbsolutePath)
|
|
207
|
+
testSuiteFinishCh.publish({
|
|
208
|
+
status: getSuiteStatusFromTestStatuses(finished),
|
|
209
|
+
testSuitePath: getTestSuitePath(testFileAbsolutePath, process.cwd()),
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function maybeRecordFinalParallelEfdStatus ({ pickleId, testFileAbsolutePath, testFullname }) {
|
|
214
|
+
const efdRetryCount = efdRetryCountByPickleId.get(pickleId)
|
|
215
|
+
const testStatuses = newTestsByTestFullname.get(testFullname)
|
|
216
|
+
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
217
|
+
|
|
218
|
+
if (efdRetryCount === undefined || !testStatuses || !finished) return
|
|
219
|
+
if (testStatuses.length !== efdRetryCount + 1) return
|
|
220
|
+
|
|
221
|
+
finished.push(getTestStatusFromRetries(testStatuses))
|
|
222
|
+
newTestsByTestFullname.delete(testFullname)
|
|
223
|
+
finishParallelSuiteIfDone(testFileAbsolutePath)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function handleEfdRetryCountMessage (message) {
|
|
227
|
+
const { pickleId, retryCount, testFileAbsolutePath, testName } = message
|
|
228
|
+
|
|
229
|
+
if (!pickleId || typeof retryCount !== 'number' || !testFileAbsolutePath || !testName) return
|
|
230
|
+
|
|
231
|
+
efdRetryCountByPickleId.set(pickleId, retryCount)
|
|
232
|
+
maybeRecordFinalParallelEfdStatus({
|
|
233
|
+
pickleId,
|
|
234
|
+
testFileAbsolutePath,
|
|
235
|
+
testFullname: `${testFileAbsolutePath}:${testName}`,
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
|
|
120
239
|
function getStatusFromResult (result) {
|
|
121
240
|
if (result.status === 1) {
|
|
122
241
|
return { status: 'pass' }
|
|
@@ -617,6 +736,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
617
736
|
if (!libraryConfigurationCh.hasSubscribers) {
|
|
618
737
|
return start.apply(this, arguments)
|
|
619
738
|
}
|
|
739
|
+
resetSuiteSkippingRunState()
|
|
620
740
|
const options = getCucumberOptions(this)
|
|
621
741
|
|
|
622
742
|
if (!isParallel && this.adapter?.options) {
|
|
@@ -626,11 +746,14 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
626
746
|
|
|
627
747
|
const configurationResponse = await getChannelPromise(libraryConfigurationCh, frameworkVersion)
|
|
628
748
|
|
|
749
|
+
repositoryRoot = configurationResponse.repositoryRoot
|
|
750
|
+
isItrEnabled = configurationResponse.libraryConfig?.isItrEnabled
|
|
629
751
|
isEarlyFlakeDetectionEnabled = configurationResponse.libraryConfig?.isEarlyFlakeDetectionEnabled
|
|
630
752
|
earlyFlakeDetectionNumRetries = configurationResponse.libraryConfig?.earlyFlakeDetectionNumRetries
|
|
631
753
|
earlyFlakeDetectionSlowTestRetries = configurationResponse.libraryConfig?.earlyFlakeDetectionSlowTestRetries ?? {}
|
|
632
754
|
earlyFlakeDetectionFaultyThreshold = configurationResponse.libraryConfig?.earlyFlakeDetectionFaultyThreshold
|
|
633
|
-
isSuitesSkippingEnabled = configurationResponse.libraryConfig?.isSuitesSkippingEnabled
|
|
755
|
+
isSuitesSkippingEnabled = isItrEnabled && configurationResponse.libraryConfig?.isSuitesSkippingEnabled
|
|
756
|
+
isCoverageReportUploadEnabled = configurationResponse.libraryConfig?.isCoverageReportUploadEnabled
|
|
634
757
|
isFlakyTestRetriesEnabled = configurationResponse.libraryConfig?.isFlakyTestRetriesEnabled
|
|
635
758
|
const configRetryCount = configurationResponse.libraryConfig?.flakyTestRetriesCount
|
|
636
759
|
numTestRetries = (typeof configRetryCount === 'number' && configRetryCount > 0) ? configRetryCount : 0
|
|
@@ -639,21 +762,35 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
639
762
|
testManagementAttemptToFixRetries = configurationResponse.libraryConfig?.testManagementAttemptToFixRetries
|
|
640
763
|
isImpactedTestsEnabled = configurationResponse.libraryConfig?.isImpactedTestsEnabled
|
|
641
764
|
|
|
765
|
+
const {
|
|
766
|
+
knownTestsResponse,
|
|
767
|
+
testManagementTestsResponse,
|
|
768
|
+
skippableSuitesResponse,
|
|
769
|
+
} = await getTestOptimizationRequestResults({
|
|
770
|
+
isKnownTestsEnabled,
|
|
771
|
+
isTestManagementTestsEnabled,
|
|
772
|
+
isSuitesSkippingEnabled,
|
|
773
|
+
getKnownTests: () => getChannelPromise(knownTestsCh),
|
|
774
|
+
getTestManagementTests: () => getChannelPromise(testManagementTestsCh),
|
|
775
|
+
getSkippableSuites: () => getChannelPromise(skippableSuitesCh),
|
|
776
|
+
})
|
|
777
|
+
|
|
642
778
|
if (isKnownTestsEnabled) {
|
|
643
|
-
const
|
|
644
|
-
if (
|
|
779
|
+
const currentKnownTestsResponse = knownTestsResponse || await getChannelPromise(knownTestsCh)
|
|
780
|
+
if (currentKnownTestsResponse.err) {
|
|
645
781
|
isEarlyFlakeDetectionEnabled = false
|
|
646
782
|
isKnownTestsEnabled = false
|
|
647
783
|
} else {
|
|
648
|
-
knownTests =
|
|
784
|
+
knownTests = currentKnownTestsResponse.knownTests
|
|
649
785
|
}
|
|
650
786
|
}
|
|
651
787
|
|
|
652
788
|
if (isSuitesSkippingEnabled) {
|
|
653
|
-
const skippableResponse = await getChannelPromise(skippableSuitesCh)
|
|
789
|
+
const skippableResponse = skippableSuitesResponse || await getChannelPromise(skippableSuitesCh)
|
|
654
790
|
|
|
655
791
|
errorSkippableRequest = skippableResponse.err
|
|
656
792
|
skippableSuites = skippableResponse.skippableSuites ?? []
|
|
793
|
+
skippableSuitesCoverage = skippableResponse.skippableSuitesCoverage ?? {}
|
|
657
794
|
|
|
658
795
|
if (!errorSkippableRequest) {
|
|
659
796
|
const filteredPickles = isCoordinator
|
|
@@ -674,6 +811,8 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
674
811
|
}
|
|
675
812
|
|
|
676
813
|
skippedSuites = [...filteredPickles.skippedSuites]
|
|
814
|
+
skippedSuitesCoverage = getSkippedSuitesCoverageForRun()
|
|
815
|
+
writeCoverageBackfillToCache(skippedSuitesCoverage, getCoverageRootDir())
|
|
677
816
|
itrCorrelationId = skippableResponse.itrCorrelationId
|
|
678
817
|
}
|
|
679
818
|
}
|
|
@@ -694,11 +833,12 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
694
833
|
}
|
|
695
834
|
|
|
696
835
|
if (isTestManagementTestsEnabled) {
|
|
697
|
-
const
|
|
698
|
-
|
|
836
|
+
const currentTestManagementTestsResponse =
|
|
837
|
+
testManagementTestsResponse || await getChannelPromise(testManagementTestsCh)
|
|
838
|
+
if (currentTestManagementTestsResponse.err) {
|
|
699
839
|
isTestManagementTestsEnabled = false
|
|
700
840
|
} else {
|
|
701
|
-
testManagementTests =
|
|
841
|
+
testManagementTests = currentTestManagementTestsResponse.testManagementTests
|
|
702
842
|
}
|
|
703
843
|
}
|
|
704
844
|
|
|
@@ -720,7 +860,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
720
860
|
attemptToFixTestsByTestFullname.clear()
|
|
721
861
|
efdRetryCountByPickleId.clear()
|
|
722
862
|
efdSlowAbortedPickleIds.clear()
|
|
723
|
-
|
|
863
|
+
finishedParallelSuites.clear()
|
|
724
864
|
newTestsByTestFullname.clear()
|
|
725
865
|
sessionStartCh.publish({ command, frameworkVersion })
|
|
726
866
|
|
|
@@ -736,13 +876,25 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
736
876
|
}
|
|
737
877
|
|
|
738
878
|
let testCodeCoverageLinesTotal
|
|
879
|
+
let testSessionCoverageFiles
|
|
739
880
|
|
|
740
|
-
if (global.__coverage__) {
|
|
881
|
+
if (global.__coverage__ || untestedCoverage) {
|
|
741
882
|
try {
|
|
883
|
+
let hasBackfilledCoverage = false
|
|
742
884
|
if (untestedCoverage) {
|
|
743
885
|
originalCoverageMap.merge(fromCoverageMapToCoverage(untestedCoverage))
|
|
744
886
|
}
|
|
745
|
-
|
|
887
|
+
hasBackfilledCoverage = applySkippedCoverageToCucumberCoverageMap()
|
|
888
|
+
if (shouldReportCodeCoverageLinesPct(hasBackfilledCoverage)) {
|
|
889
|
+
testCodeCoverageLinesTotal = getTestCoverageLinesPercentage(
|
|
890
|
+
originalCoverageMap,
|
|
891
|
+
undefined,
|
|
892
|
+
getCoverageRootDir()
|
|
893
|
+
)
|
|
894
|
+
}
|
|
895
|
+
if (isTiaCoverageBackfillEnabled()) {
|
|
896
|
+
testSessionCoverageFiles = getCucumberTestSessionCoverageFiles()
|
|
897
|
+
}
|
|
746
898
|
} catch {
|
|
747
899
|
// ignore errors
|
|
748
900
|
}
|
|
@@ -754,6 +906,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
754
906
|
status: success ? 'pass' : 'fail',
|
|
755
907
|
isSuitesSkipped,
|
|
756
908
|
testCodeCoverageLinesTotal,
|
|
909
|
+
testSessionCoverageFiles,
|
|
757
910
|
numSkippedSuites: skippedSuites.length,
|
|
758
911
|
hasUnskippableSuites: isUnskippable,
|
|
759
912
|
hasForcedToRunSuites: isForcedToRun,
|
|
@@ -875,6 +1028,9 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
875
1028
|
efdSlowAbortedPickleIds.add(pickle.id)
|
|
876
1029
|
}
|
|
877
1030
|
}
|
|
1031
|
+
if (isWorker) {
|
|
1032
|
+
publishWorkerEfdRetryCount(pickle, efdRetryCount)
|
|
1033
|
+
}
|
|
878
1034
|
for (let retryIndex = 0; retryIndex < efdRetryCount; retryIndex++) {
|
|
879
1035
|
numRetriesByPickleId.set(pickle.id, retryIndex + 1)
|
|
880
1036
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -925,7 +1081,7 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
925
1081
|
// last test in suite
|
|
926
1082
|
const testSuiteStatus = getSuiteStatusFromTestStatuses(pickleResultByFile[testFileAbsolutePath])
|
|
927
1083
|
if (global.__coverage__) {
|
|
928
|
-
const coverageFiles =
|
|
1084
|
+
const coverageFiles = getCoveredFilesFromCoverage(global.__coverage__)
|
|
929
1085
|
|
|
930
1086
|
testSuiteCodeCoverageCh.publish({
|
|
931
1087
|
coverageFiles,
|
|
@@ -973,6 +1129,10 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
973
1129
|
return
|
|
974
1130
|
}
|
|
975
1131
|
}
|
|
1132
|
+
if (message[DD_EFD_RETRY_COUNT_MESSAGE]) {
|
|
1133
|
+
handleEfdRetryCountMessage(message[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
1134
|
+
return
|
|
1135
|
+
}
|
|
976
1136
|
|
|
977
1137
|
const envelope = isNewVersion ? message.envelope : message.jsonEnvelope
|
|
978
1138
|
|
|
@@ -989,12 +1149,13 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
989
1149
|
return parseWorkerMessageFunction.apply(this, arguments)
|
|
990
1150
|
}
|
|
991
1151
|
}
|
|
1152
|
+
if (parsed[DD_EFD_RETRY_COUNT_MESSAGE]) {
|
|
1153
|
+
handleEfdRetryCountMessage(parsed[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
1154
|
+
return
|
|
1155
|
+
}
|
|
992
1156
|
let pickle
|
|
993
1157
|
|
|
994
1158
|
if (parsed.testCaseStarted) {
|
|
995
|
-
if (parsed.testCaseStarted.id) {
|
|
996
|
-
testCaseStartedTimesById.set(parsed.testCaseStarted.id, performance.now())
|
|
997
|
-
}
|
|
998
1159
|
if (isNewVersion) {
|
|
999
1160
|
pickle = this.inProgress[worker.id].pickle
|
|
1000
1161
|
} else {
|
|
@@ -1016,10 +1177,6 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1016
1177
|
|
|
1017
1178
|
// after calling `parseWorkerMessageFunction`, the test status can already be read
|
|
1018
1179
|
if (parsed.testCaseFinished) {
|
|
1019
|
-
const testCaseStartedId = parsed.testCaseFinished.testCaseStartedId
|
|
1020
|
-
const testCaseStartedAt = testCaseStartedTimesById.get(testCaseStartedId)
|
|
1021
|
-
testCaseStartedTimesById.delete(testCaseStartedId)
|
|
1022
|
-
|
|
1023
1180
|
let worstTestStepResult
|
|
1024
1181
|
if (isNewVersion && eventDataCollector) {
|
|
1025
1182
|
pickle = this.inProgress[worker.id].pickle
|
|
@@ -1052,21 +1209,15 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1052
1209
|
}
|
|
1053
1210
|
let efdRetryCount = efdRetryCountByPickleId.get(pickle.id)
|
|
1054
1211
|
if (efdRetryCount === undefined) {
|
|
1055
|
-
const firstExecutionDurationMs = testCaseStartedAt === undefined ? 0 : performance.now() - testCaseStartedAt
|
|
1056
1212
|
efdRetryCount = status === 'skip'
|
|
1057
1213
|
? 0
|
|
1058
|
-
:
|
|
1214
|
+
: getConfiguredEfdRetryCount()
|
|
1059
1215
|
efdRetryCountByPickleId.set(pickle.id, efdRetryCount)
|
|
1060
1216
|
if (efdRetryCount === 0 && status !== 'skip') {
|
|
1061
1217
|
efdSlowAbortedPickleIds.add(pickle.id)
|
|
1062
1218
|
}
|
|
1063
1219
|
}
|
|
1064
|
-
|
|
1065
|
-
if (testStatuses.length === efdRetryCount + 1) {
|
|
1066
|
-
const newTestFinalStatus = getTestStatusFromRetries(testStatuses)
|
|
1067
|
-
// we only push to `finished` if the retries have finished
|
|
1068
|
-
finished.push(newTestFinalStatus)
|
|
1069
|
-
}
|
|
1220
|
+
maybeRecordFinalParallelEfdStatus({ pickleId: pickle.id, testFileAbsolutePath, testFullname })
|
|
1070
1221
|
} else if (
|
|
1071
1222
|
isTestManagementTestsEnabled &&
|
|
1072
1223
|
getTestProperties(getTestSuitePath(testFileAbsolutePath, process.cwd()), pickle.name).attemptToFix
|
|
@@ -1090,12 +1241,7 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1090
1241
|
finished.push(status)
|
|
1091
1242
|
}
|
|
1092
1243
|
|
|
1093
|
-
|
|
1094
|
-
testSuiteFinishCh.publish({
|
|
1095
|
-
status: getSuiteStatusFromTestStatuses(finished),
|
|
1096
|
-
testSuitePath: getTestSuitePath(testFileAbsolutePath, process.cwd()),
|
|
1097
|
-
})
|
|
1098
|
-
}
|
|
1244
|
+
finishParallelSuiteIfDone(testFileAbsolutePath)
|
|
1099
1245
|
}
|
|
1100
1246
|
|
|
1101
1247
|
return parseWorkerResponse
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const shimmer = require('../../datadog-shimmer')
|
|
4
4
|
const { addHook } = require('./helpers/instrument')
|
|
5
5
|
const { createCallbackInstrumentor } = require('./helpers/callback-instrumentor')
|
|
6
|
+
const { createPromiseInstrumentor } = require('./helpers/promise-instrumentor')
|
|
6
7
|
|
|
7
8
|
const rrtypes = {
|
|
8
9
|
resolveAny: 'ANY',
|
|
@@ -18,30 +19,55 @@ const rrtypes = {
|
|
|
18
19
|
resolveSoa: 'SOA',
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
shimmer.wrap(dns, 'lookup', lookup(buildArgsContext()))
|
|
28
|
-
shimmer.wrap(dns, 'lookupService', lookupService(buildArgsContext()))
|
|
29
|
-
shimmer.wrap(dns, 'resolve', resolve(buildArgsContext()))
|
|
30
|
-
shimmer.wrap(dns, 'reverse', reverse(buildArgsContext()))
|
|
31
|
-
|
|
32
|
-
patchResolveShorthands(dns, resolve)
|
|
22
|
+
// `dns.promises` and `require('dns/promises')` resolve to the same exports object. Both
|
|
23
|
+
// access paths register a hook, so without a guard the second hook to fire would stack a
|
|
24
|
+
// second wrap layer on top and publish every `apm:dns:*` event twice per call. The WeakSet
|
|
25
|
+
// collapses the two hooks to one wrap regardless of which one runs first.
|
|
26
|
+
const wrappedPromiseApis = new WeakSet()
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
shimmer.wrap(dns.Resolver.prototype, 'reverse', reverse(buildArgsContext()))
|
|
28
|
+
addHook({ name: 'dns' }, dns => {
|
|
29
|
+
patchApi(dns, createCallbackInstrumentor, buildCallbackArgsContext)
|
|
37
30
|
|
|
38
|
-
|
|
31
|
+
if (dns.promises) {
|
|
32
|
+
patchPromiseApi(dns.promises)
|
|
39
33
|
}
|
|
40
34
|
|
|
41
35
|
return dns
|
|
42
36
|
})
|
|
43
37
|
|
|
44
|
-
|
|
38
|
+
addHook({ name: 'dns/promises' }, dnsPromises => {
|
|
39
|
+
patchPromiseApi(dnsPromises)
|
|
40
|
+
return dnsPromises
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
function patchPromiseApi (api) {
|
|
44
|
+
if (wrappedPromiseApis.has(api)) return
|
|
45
|
+
wrappedPromiseApis.add(api)
|
|
46
|
+
patchApi(api, createPromiseInstrumentor, buildPromiseArgsContext)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function patchApi (api, instrumentorFactory, buildArgsContext) {
|
|
50
|
+
const lookup = instrumentorFactory('apm:dns:lookup', { captureResult: true })
|
|
51
|
+
const lookupService = instrumentorFactory('apm:dns:lookup_service', { captureResult: true })
|
|
52
|
+
const resolve = instrumentorFactory('apm:dns:resolve', { captureResult: true })
|
|
53
|
+
const reverse = instrumentorFactory('apm:dns:reverse', { captureResult: true })
|
|
54
|
+
|
|
55
|
+
shimmer.wrap(api, 'lookup', lookup(buildArgsContext()))
|
|
56
|
+
shimmer.wrap(api, 'lookupService', lookupService(buildArgsContext()))
|
|
57
|
+
shimmer.wrap(api, 'resolve', resolve(buildArgsContext()))
|
|
58
|
+
shimmer.wrap(api, 'reverse', reverse(buildArgsContext()))
|
|
59
|
+
|
|
60
|
+
patchResolveShorthands(api, resolve, buildArgsContext)
|
|
61
|
+
|
|
62
|
+
if (api.Resolver) {
|
|
63
|
+
shimmer.wrap(api.Resolver.prototype, 'resolve', resolve(buildArgsContext()))
|
|
64
|
+
shimmer.wrap(api.Resolver.prototype, 'reverse', reverse(buildArgsContext()))
|
|
65
|
+
|
|
66
|
+
patchResolveShorthands(api.Resolver.prototype, resolve, buildArgsContext)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function patchResolveShorthands (prototype, resolve, buildArgsContext) {
|
|
45
71
|
for (const method of Object.keys(rrtypes)) {
|
|
46
72
|
if (prototype[method]) {
|
|
47
73
|
shimmer.wrap(prototype, method, resolve(buildArgsContext(rrtypes[method])))
|
|
@@ -49,7 +75,7 @@ function patchResolveShorthands (prototype, resolve) {
|
|
|
49
75
|
}
|
|
50
76
|
}
|
|
51
77
|
|
|
52
|
-
function
|
|
78
|
+
function buildCallbackArgsContext (rrtype) {
|
|
53
79
|
return function (_, args) {
|
|
54
80
|
if (args.length < 2) return
|
|
55
81
|
const captured = [...args]
|
|
@@ -60,3 +86,13 @@ function buildArgsContext (rrtype) {
|
|
|
60
86
|
return { args: captured }
|
|
61
87
|
}
|
|
62
88
|
}
|
|
89
|
+
|
|
90
|
+
function buildPromiseArgsContext (rrtype) {
|
|
91
|
+
return function (_, args) {
|
|
92
|
+
const captured = [...args]
|
|
93
|
+
if (rrtype) {
|
|
94
|
+
captured.push(rrtype)
|
|
95
|
+
}
|
|
96
|
+
return { args: captured }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -51,9 +51,9 @@ function createWrapSelect () {
|
|
|
51
51
|
const connectCh = channel('apm:elasticsearch:query:connect')
|
|
52
52
|
return function wrapRequest (request) {
|
|
53
53
|
return function (...args) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
args[0] = shimmer.
|
|
54
|
+
const cb = args[0]
|
|
55
|
+
if (args.length === 1 && typeof cb === 'function') {
|
|
56
|
+
args[0] = shimmer.wrapCallback(cb, cb => function (err, connection) {
|
|
57
57
|
if (connectCh.hasSubscribers && connection && connection.host) {
|
|
58
58
|
connectCh.publish({ hostname: connection.host.host, port: connection.host.port })
|
|
59
59
|
}
|
|
@@ -85,7 +85,7 @@ function createWrapRequest (name) {
|
|
|
85
85
|
cb = arguments[lastIndex]
|
|
86
86
|
|
|
87
87
|
if (typeof cb === 'function') {
|
|
88
|
-
arguments[lastIndex] = shimmer.
|
|
88
|
+
arguments[lastIndex] = shimmer.wrapCallback(cb, cb => function (error) {
|
|
89
89
|
if (error) {
|
|
90
90
|
ctx.error = error
|
|
91
91
|
errorCh.publish(ctx)
|