dd-trace 5.96.0 → 5.98.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/index.d.ts +60 -2
- package/package.json +9 -7
- package/packages/datadog-esbuild/index.js +20 -9
- package/packages/datadog-instrumentations/src/child_process.js +7 -17
- package/packages/datadog-instrumentations/src/crypto.js +1 -2
- package/packages/datadog-instrumentations/src/cucumber.js +69 -4
- package/packages/datadog-instrumentations/src/cypress-config.js +318 -0
- package/packages/datadog-instrumentations/src/cypress.js +86 -4
- package/packages/datadog-instrumentations/src/dns.js +1 -2
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fs.js +27 -29
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
- package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
- package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
- package/packages/datadog-instrumentations/src/http/client.js +2 -3
- package/packages/datadog-instrumentations/src/http/server.js +2 -5
- package/packages/datadog-instrumentations/src/http2/client.js +1 -3
- package/packages/datadog-instrumentations/src/http2/server.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +117 -16
- package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +12 -1
- package/packages/datadog-instrumentations/src/net.js +2 -8
- package/packages/datadog-instrumentations/src/pino.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +1 -2
- package/packages/datadog-instrumentations/src/redis.js +12 -6
- package/packages/datadog-instrumentations/src/selenium.js +4 -1
- package/packages/datadog-instrumentations/src/sequelize.js +1 -1
- package/packages/datadog-instrumentations/src/url.js +1 -3
- package/packages/datadog-instrumentations/src/vitest.js +5 -1
- package/packages/datadog-instrumentations/src/vm.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -4
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-cucumber/src/index.js +13 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +166 -6
- package/packages/datadog-plugin-cypress/src/index.js +59 -2
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +10 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +10 -2
- package/packages/datadog-plugin-jest/src/index.js +4 -2
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +3 -3
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +10 -16
- package/packages/datadog-plugin-openai/src/services.js +1 -0
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/src/index.js +1 -1
- package/packages/datadog-plugin-ws/src/close.js +1 -1
- package/packages/datadog-plugin-ws/src/receiver.js +1 -1
- package/packages/datadog-webpack/index.js +3 -3
- package/packages/dd-trace/index.js +12 -10
- package/packages/dd-trace/src/agent/url.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +26 -22
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
- package/packages/dd-trace/src/appsec/blocking.js +64 -33
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
- package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/config/defaults.js +315 -146
- package/packages/dd-trace/src/config/generated-config-types.d.ts +9 -1
- package/packages/dd-trace/src/config/helper.js +59 -10
- package/packages/dd-trace/src/config/index.js +587 -1496
- package/packages/dd-trace/src/config/parsers.js +256 -0
- package/packages/dd-trace/src/config/remote_config.js +59 -2
- package/packages/dd-trace/src/config/supported-configurations.json +406 -432
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
- package/packages/dd-trace/src/crashtracking/index.js +1 -7
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
- package/packages/dd-trace/src/debugger/index.js +1 -1
- package/packages/dd-trace/src/dogstatsd.js +12 -9
- package/packages/dd-trace/src/encode/0.4.js +8 -7
- package/packages/dd-trace/src/encode/span-stats.js +4 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
- package/packages/dd-trace/src/exporters/common/request.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +12 -2
- package/packages/dd-trace/src/heap_snapshots.js +3 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
- package/packages/dd-trace/src/llmobs/index.js +4 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
- package/packages/dd-trace/src/llmobs/sdk.js +12 -8
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +9 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
- package/packages/dd-trace/src/log/index.js +20 -59
- package/packages/dd-trace/src/log/writer.js +7 -19
- package/packages/dd-trace/src/noop/proxy.js +8 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +17 -2
- package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
- package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
- package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +75 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +66 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +332 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
- package/packages/dd-trace/src/opentracing/tracer.js +9 -4
- package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
- package/packages/dd-trace/src/plugins/plugin.js +11 -13
- package/packages/dd-trace/src/plugins/storage.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +22 -5
- package/packages/dd-trace/src/plugins/util/test.js +2 -0
- package/packages/dd-trace/src/plugins/util/web.js +6 -88
- package/packages/dd-trace/src/process-tags/index.js +3 -0
- package/packages/dd-trace/src/profiler.js +27 -2
- package/packages/dd-trace/src/profiling/config.js +73 -241
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
- package/packages/dd-trace/src/profiling/profiler.js +78 -109
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
- package/packages/dd-trace/src/propagation-hash/index.js +2 -1
- package/packages/dd-trace/src/proxy.js +40 -6
- package/packages/dd-trace/src/remote_config/index.js +3 -0
- package/packages/dd-trace/src/require-package-json.js +8 -4
- package/packages/dd-trace/src/ritm.js +58 -26
- package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +18 -11
- package/packages/dd-trace/src/sampler.js +1 -1
- package/packages/dd-trace/src/service-naming/index.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
- package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +17 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +11 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
- package/packages/dd-trace/src/span_stats.js +5 -1
- package/packages/dd-trace/src/standalone/index.js +3 -0
- package/packages/dd-trace/src/telemetry/index.js +2 -3
- package/packages/dd-trace/src/telemetry/send-data.js +5 -19
- package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
- package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
- package/packages/dd-trace/src/tracer.js +2 -2
- package/packages/dd-trace/src/util.js +0 -9
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
- package/vendor/dist/protobufjs/index.js +1 -1
- package/packages/dd-trace/src/log/utils.js +0 -16
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real timers at module load, before any test can install fake timers.
|
|
4
|
+
const { performance } = require('perf_hooks')
|
|
5
|
+
const dateNow = Date.now
|
|
6
|
+
|
|
3
7
|
const {
|
|
4
8
|
TEST_STATUS,
|
|
5
9
|
TEST_IS_RUM_ACTIVE,
|
|
@@ -53,6 +57,7 @@ const {
|
|
|
53
57
|
DYNAMIC_NAME_RE,
|
|
54
58
|
logDynamicNamesWarning,
|
|
55
59
|
getPullRequestBaseBranch,
|
|
60
|
+
TEST_FINAL_STATUS,
|
|
56
61
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
57
62
|
const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
|
|
58
63
|
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
@@ -240,6 +245,58 @@ function getSuiteStatus (suiteStats) {
|
|
|
240
245
|
return 'pass'
|
|
241
246
|
}
|
|
242
247
|
|
|
248
|
+
const FINAL_STATUS_RETRY_KIND = {
|
|
249
|
+
none: 'none',
|
|
250
|
+
atr: 'atr',
|
|
251
|
+
efd: 'efd',
|
|
252
|
+
atf: 'atf',
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function getFinalStatusRetryKind ({ finishedTest, finishedTestAttempts, flakyTestRetriesCount }) {
|
|
256
|
+
// Infer retry kind from the executions we actually saw so ATR enabled with
|
|
257
|
+
// a retry count of 0 is still treated as a single final execution.
|
|
258
|
+
if (finishedTest.isAttemptToFix) {
|
|
259
|
+
return FINAL_STATUS_RETRY_KIND.atf
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (finishedTestAttempts.some(testAttempt => testAttempt.isEfdRetry)) {
|
|
263
|
+
return FINAL_STATUS_RETRY_KIND.efd
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (finishedTestAttempts.length > 1 && flakyTestRetriesCount > 0) {
|
|
267
|
+
return FINAL_STATUS_RETRY_KIND.atr
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return FINAL_STATUS_RETRY_KIND.none
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function getFinalStatus ({
|
|
274
|
+
status,
|
|
275
|
+
retryKind,
|
|
276
|
+
hasFailedAllRetries,
|
|
277
|
+
hasPassedAllAtfRetries,
|
|
278
|
+
isQuarantined,
|
|
279
|
+
isDisabled,
|
|
280
|
+
}) {
|
|
281
|
+
// If the test is quarantined or disabled, regardless of its actual execution result or active retry features,
|
|
282
|
+
// the final status of its last execution should be reported as 'skip'.
|
|
283
|
+
if (isQuarantined || isDisabled || status === 'skip') {
|
|
284
|
+
return 'skip'
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
switch (retryKind) {
|
|
288
|
+
case FINAL_STATUS_RETRY_KIND.atr:
|
|
289
|
+
case FINAL_STATUS_RETRY_KIND.efd:
|
|
290
|
+
// These modes report the aggregate result across attempts.
|
|
291
|
+
return hasFailedAllRetries ? 'fail' : 'pass'
|
|
292
|
+
case FINAL_STATUS_RETRY_KIND.atf:
|
|
293
|
+
// Attempt-to-fix only passes if every execution passed.
|
|
294
|
+
return hasPassedAllAtfRetries ? 'pass' : 'fail'
|
|
295
|
+
default:
|
|
296
|
+
return status
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
243
300
|
class CypressPlugin {
|
|
244
301
|
_isInit = false
|
|
245
302
|
testEnvironmentMetadata = getTestEnvironmentMetadata(TEST_FRAMEWORK_NAME)
|
|
@@ -307,10 +364,68 @@ class CypressPlugin {
|
|
|
307
364
|
}
|
|
308
365
|
}
|
|
309
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Resets state that is scoped to a single Cypress run so the singleton plugin
|
|
369
|
+
* can be reused safely across multiple programmatic cypress.run() calls.
|
|
370
|
+
*
|
|
371
|
+
* @returns {void}
|
|
372
|
+
*/
|
|
373
|
+
resetRunState () {
|
|
374
|
+
this._isInit = false
|
|
375
|
+
this.finishedTestsByFile = {}
|
|
376
|
+
this.testStatuses = {}
|
|
377
|
+
this.isTestsSkipped = false
|
|
378
|
+
this.isSuitesSkippingEnabled = false
|
|
379
|
+
this.isCodeCoverageEnabled = false
|
|
380
|
+
this.isFlakyTestRetriesEnabled = false
|
|
381
|
+
this.flakyTestRetriesCount = 0
|
|
382
|
+
this.isEarlyFlakeDetectionEnabled = false
|
|
383
|
+
this.isKnownTestsEnabled = false
|
|
384
|
+
this.earlyFlakeDetectionNumRetries = 0
|
|
385
|
+
this.testsToSkip = []
|
|
386
|
+
this.skippedTests = []
|
|
387
|
+
this.hasForcedToRunSuites = false
|
|
388
|
+
this.hasUnskippableSuites = false
|
|
389
|
+
this.unskippableSuites = []
|
|
390
|
+
this.knownTests = []
|
|
391
|
+
this.knownTestsByTestSuite = undefined
|
|
392
|
+
this.isTestManagementTestsEnabled = false
|
|
393
|
+
this.testManagementAttemptToFixRetries = 0
|
|
394
|
+
this.testManagementTests = undefined
|
|
395
|
+
this.isImpactedTestsEnabled = false
|
|
396
|
+
this.modifiedFiles = []
|
|
397
|
+
this.activeTestSpan = null
|
|
398
|
+
this.testSuiteSpan = null
|
|
399
|
+
this.testModuleSpan = null
|
|
400
|
+
this.testSessionSpan = null
|
|
401
|
+
this.command = undefined
|
|
402
|
+
this.frameworkVersion = undefined
|
|
403
|
+
this.rootDir = undefined
|
|
404
|
+
this.itrCorrelationId = undefined
|
|
405
|
+
this.isTestIsolationEnabled = undefined
|
|
406
|
+
this.rumFlushWaitMillis = undefined
|
|
407
|
+
this._pendingRequestErrorTags = []
|
|
408
|
+
this.libraryConfigurationPromise = undefined
|
|
409
|
+
this._timeOrigin = 0
|
|
410
|
+
this._perfOrigin = 0
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Returns the current time in the same coordinate system used by span
|
|
415
|
+
* start/finish. Captured at session span creation so it shares the same
|
|
416
|
+
* epoch as the trace without reaching into span internals.
|
|
417
|
+
*
|
|
418
|
+
* @returns {number}
|
|
419
|
+
*/
|
|
420
|
+
_now () {
|
|
421
|
+
return this._timeOrigin + performance.now() - this._perfOrigin
|
|
422
|
+
}
|
|
423
|
+
|
|
310
424
|
// Init function returns a promise that resolves with the Cypress configuration
|
|
311
425
|
// Depending on the received configuration, the Cypress configuration can be modified:
|
|
312
426
|
// for example, to enable retries for failed tests.
|
|
313
427
|
init (tracer, cypressConfig) {
|
|
428
|
+
this.resetRunState()
|
|
314
429
|
this._isInit = true
|
|
315
430
|
this.tracer = tracer
|
|
316
431
|
this.cypressConfig = cypressConfig
|
|
@@ -620,6 +735,13 @@ class CypressPlugin {
|
|
|
620
735
|
this.tracer._tracer._exporter.addMetadataTags(metadataTags)
|
|
621
736
|
}
|
|
622
737
|
|
|
738
|
+
// Capture time references that match what startSpan records internally
|
|
739
|
+
// (trace.startTime = Date.now(), trace.ticks = performance.now()).
|
|
740
|
+
// This lets _now() produce values in the same coordinate system as
|
|
741
|
+
// span._startTime without accessing span internals.
|
|
742
|
+
this._timeOrigin = dateNow()
|
|
743
|
+
this._perfOrigin = performance.now()
|
|
744
|
+
|
|
623
745
|
this.testSessionSpan = this.tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_session`, {
|
|
624
746
|
childOf,
|
|
625
747
|
tags: {
|
|
@@ -694,20 +816,27 @@ class CypressPlugin {
|
|
|
694
816
|
}
|
|
695
817
|
|
|
696
818
|
return new Promise(resolve => {
|
|
819
|
+
const finishAfterRun = () => {
|
|
820
|
+
this._isInit = false
|
|
821
|
+
appClosingTelemetry()
|
|
822
|
+
resolve(null)
|
|
823
|
+
}
|
|
824
|
+
|
|
697
825
|
const exporter = this.tracer._tracer._exporter
|
|
698
826
|
if (!exporter) {
|
|
699
|
-
|
|
827
|
+
finishAfterRun()
|
|
828
|
+
return
|
|
700
829
|
}
|
|
701
830
|
if (exporter.flush) {
|
|
702
831
|
exporter.flush(() => {
|
|
703
|
-
|
|
704
|
-
resolve(null)
|
|
832
|
+
finishAfterRun()
|
|
705
833
|
})
|
|
706
834
|
} else if (exporter._writer) {
|
|
707
835
|
exporter._writer.flush(() => {
|
|
708
|
-
|
|
709
|
-
resolve(null)
|
|
836
|
+
finishAfterRun()
|
|
710
837
|
})
|
|
838
|
+
} else {
|
|
839
|
+
finishAfterRun()
|
|
711
840
|
}
|
|
712
841
|
})
|
|
713
842
|
}
|
|
@@ -745,6 +874,7 @@ class CypressPlugin {
|
|
|
745
874
|
: spec.relative
|
|
746
875
|
|
|
747
876
|
const skippedTestSpan = this.getTestSpan({ testName: cypressTestName, testSuite: spec.relative, testSourceFile })
|
|
877
|
+
skippedTestSpan.setTag(TEST_FINAL_STATUS, 'skip')
|
|
748
878
|
|
|
749
879
|
skippedTestSpan.setTag(TEST_STATUS, 'skip')
|
|
750
880
|
if (isSkippedByItr) {
|
|
@@ -834,6 +964,36 @@ class CypressPlugin {
|
|
|
834
964
|
finishedTest.testSpan.setTag(TEST_CODE_OWNERS, codeOwners)
|
|
835
965
|
}
|
|
836
966
|
|
|
967
|
+
// We can check if this is the last attempt regardless of the retry mechanism
|
|
968
|
+
const isLastAttempt = attemptIndex === finishedTestAttempts.length - 1
|
|
969
|
+
if (isLastAttempt) {
|
|
970
|
+
const testSpanTags = finishedTest.testSpan.context()._tags
|
|
971
|
+
const retryKind = getFinalStatusRetryKind({
|
|
972
|
+
finishedTest,
|
|
973
|
+
finishedTestAttempts,
|
|
974
|
+
flakyTestRetriesCount: this.flakyTestRetriesCount,
|
|
975
|
+
})
|
|
976
|
+
|
|
977
|
+
const hasFailedAllRetries = testSpanTags[TEST_HAS_FAILED_ALL_RETRIES] === 'true'
|
|
978
|
+
const hasPassedAllAtfRetries =
|
|
979
|
+
testSpanTags[TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED] === 'true'
|
|
980
|
+
const isQuarantined = testSpanTags[TEST_MANAGEMENT_IS_QUARANTINED] === 'true'
|
|
981
|
+
const isDisabled = testSpanTags[TEST_MANAGEMENT_IS_DISABLED] === 'true'
|
|
982
|
+
|
|
983
|
+
const finalStatus = getFinalStatus({
|
|
984
|
+
status: cypressTestStatus,
|
|
985
|
+
retryKind,
|
|
986
|
+
hasFailedAllRetries,
|
|
987
|
+
hasPassedAllAtfRetries,
|
|
988
|
+
isQuarantined,
|
|
989
|
+
isDisabled,
|
|
990
|
+
})
|
|
991
|
+
|
|
992
|
+
if (finalStatus) {
|
|
993
|
+
finishedTest.testSpan.setTag(TEST_FINAL_STATUS, finalStatus)
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
837
997
|
finishedTest.testSpan.finish(finishedTest.finishTime)
|
|
838
998
|
}
|
|
839
999
|
}
|
|
@@ -1051,7 +1211,7 @@ class CypressPlugin {
|
|
|
1051
1211
|
const finishedTest = {
|
|
1052
1212
|
testName,
|
|
1053
1213
|
testStatus,
|
|
1054
|
-
finishTime: this.
|
|
1214
|
+
finishTime: this._now(),
|
|
1055
1215
|
testSpan: this.activeTestSpan,
|
|
1056
1216
|
isEfdRetry,
|
|
1057
1217
|
isAttemptToFix,
|
|
@@ -1,11 +1,68 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const NoopTracer = require('../../dd-trace/src/noop/tracer')
|
|
3
4
|
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Cypress plugin handles setup-node-events from the instrumentation layer
|
|
8
|
+
* via a diagnostic channel, keeping the instrumentation free of tracer references.
|
|
9
|
+
*/
|
|
7
10
|
class CypressPlugin extends Plugin {
|
|
8
11
|
static id = 'cypress'
|
|
12
|
+
|
|
13
|
+
constructor (...args) {
|
|
14
|
+
super(...args)
|
|
15
|
+
|
|
16
|
+
this.addSub('ci:cypress:setup-node-events', (payload) => {
|
|
17
|
+
// Bail out if the tracer failed to init (e.g. invalid DD_SITE).
|
|
18
|
+
// Mirrors the guard in the manual plugin entrypoint (plugin.js).
|
|
19
|
+
if (this._tracer._tracer instanceof NoopTracer) return
|
|
20
|
+
|
|
21
|
+
const { on, config, userAfterSpecHandlers, userAfterRunHandlers, cleanupWrapper } = payload
|
|
22
|
+
|
|
23
|
+
const registerAfterRunWithCleanup = (afterRunHandler) => {
|
|
24
|
+
on('after:run', (results) => {
|
|
25
|
+
const chain = userAfterRunHandlers.reduce(
|
|
26
|
+
(p, h) => p.then(() => h(results)),
|
|
27
|
+
Promise.resolve()
|
|
28
|
+
)
|
|
29
|
+
if (afterRunHandler) {
|
|
30
|
+
return chain.then(() => afterRunHandler(results)).finally(cleanupWrapper)
|
|
31
|
+
}
|
|
32
|
+
return chain.finally(cleanupWrapper)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const cypressPlugin = require('./cypress-plugin')
|
|
37
|
+
|
|
38
|
+
if (cypressPlugin._isInit) {
|
|
39
|
+
// Already initialized by manual plugin call — just chain user handlers
|
|
40
|
+
for (const h of userAfterSpecHandlers) on('after:spec', h)
|
|
41
|
+
registerAfterRunWithCleanup()
|
|
42
|
+
payload.registered = true
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
on('before:run', cypressPlugin.beforeRun.bind(cypressPlugin))
|
|
47
|
+
|
|
48
|
+
on('after:spec', (spec, results) => {
|
|
49
|
+
const chain = userAfterSpecHandlers.reduce(
|
|
50
|
+
(p, h) => p.then(() => h(spec, results)),
|
|
51
|
+
Promise.resolve()
|
|
52
|
+
)
|
|
53
|
+
return chain.then(() => cypressPlugin.afterSpec(spec, results))
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
registerAfterRunWithCleanup((results) => cypressPlugin.afterRun(results))
|
|
57
|
+
|
|
58
|
+
on('task', cypressPlugin.getTasks())
|
|
59
|
+
|
|
60
|
+
payload.registered = true
|
|
61
|
+
// cypressPlugin.init expects the proxy tracer (with ._tracer._exporter),
|
|
62
|
+
// not the unwrapped internal tracer that this.tracer returns.
|
|
63
|
+
payload.configPromise = Promise.resolve(cypressPlugin.init(this._tracer, config)).then(() => config)
|
|
64
|
+
})
|
|
65
|
+
}
|
|
9
66
|
}
|
|
10
67
|
|
|
11
68
|
module.exports = CypressPlugin
|
|
@@ -123,7 +123,8 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
|
|
|
123
123
|
const topicName = topic?.slice(topic.lastIndexOf('/') + 1) ??
|
|
124
124
|
subscription.name.slice(subscription.name.lastIndexOf('/') + 1)
|
|
125
125
|
const baseService = this.tracer._service || 'unknown'
|
|
126
|
-
const serviceName = this.config.service || `${baseService}-pubsub
|
|
126
|
+
const serviceName = this.config.service || { name: `${baseService}-pubsub`, source: baseService }
|
|
127
|
+
|
|
127
128
|
const meta = {
|
|
128
129
|
'gcloud.project_id': subscription.pubsub.projectId,
|
|
129
130
|
'pubsub.topic': topic,
|
|
@@ -145,17 +145,12 @@ class GoogleCloudPubsubPushSubscriptionPlugin extends TracingPlugin {
|
|
|
145
145
|
const subscriptionName = subscription?.slice(subscription.lastIndexOf('/') + 1) ?? subscription
|
|
146
146
|
const publishStartTime = attrs['x-dd-publish-start-time']
|
|
147
147
|
const startTime = publishStartTime ? Number.parseInt(publishStartTime, 10) : undefined
|
|
148
|
-
|
|
149
|
-
// Get the base service name and construct the pubsub service override
|
|
150
|
-
const baseService = this.tracer._service
|
|
151
|
-
const serviceOverride = this.config.service ?? `${baseService}-pubsub`
|
|
152
|
-
|
|
153
148
|
// Use this.startSpan() which automatically activates the span
|
|
154
149
|
const span = this.startSpan('pubsub.push.receive', {
|
|
155
150
|
childOf: parentContext,
|
|
156
151
|
startTime,
|
|
157
152
|
kind: 'consumer',
|
|
158
|
-
service:
|
|
153
|
+
service: this.config.service || { name: `${this.tracer._service}-pubsub`, source: this.tracer._service },
|
|
159
154
|
meta: {
|
|
160
155
|
component: 'google-cloud-pubsub',
|
|
161
156
|
'pubsub.method': 'receive',
|
|
@@ -163,7 +158,7 @@ class GoogleCloudPubsubPushSubscriptionPlugin extends TracingPlugin {
|
|
|
163
158
|
'pubsub.message_id': message.messageId,
|
|
164
159
|
'pubsub.subscription_type': 'push',
|
|
165
160
|
'pubsub.topic': topicName,
|
|
166
|
-
'_dd.base_service':
|
|
161
|
+
'_dd.base_service': this.tracer._service,
|
|
167
162
|
'_dd.serviceoverride.type': 'integration',
|
|
168
163
|
'resource.name': `Push Subscription ${subscriptionName}`,
|
|
169
164
|
},
|
|
@@ -28,7 +28,7 @@ class GraphQLResolvePlugin extends TracingPlugin {
|
|
|
28
28
|
if (rootCtx.fields[computedPathString]) return
|
|
29
29
|
|
|
30
30
|
if (!rootCtx[collapsedPathSym]) {
|
|
31
|
-
rootCtx[collapsedPathSym] =
|
|
31
|
+
rootCtx[collapsedPathSym] = Object.create(null)
|
|
32
32
|
} else if (rootCtx[collapsedPathSym][computedPathString]) {
|
|
33
33
|
return
|
|
34
34
|
}
|
|
@@ -40,10 +40,10 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
40
40
|
const span = this.startSpan(this.operationName(), {
|
|
41
41
|
childOf,
|
|
42
42
|
integrationName: this.constructor.id,
|
|
43
|
+
service: this.serviceName({ pluginConfig: this.config, sessionDetails: extractSessionDetails(options) }),
|
|
43
44
|
meta: {
|
|
44
45
|
[COMPONENT]: this.constructor.id,
|
|
45
46
|
'span.kind': 'client',
|
|
46
|
-
'service.name': this.serviceName({ pluginConfig: this.config, sessionDetails: extractSessionDetails(options) }),
|
|
47
47
|
'resource.name': method,
|
|
48
48
|
'span.type': 'http',
|
|
49
49
|
'http.method': method,
|
|
@@ -4,7 +4,7 @@ const ServerPlugin = require('../../dd-trace/src/plugins/server')
|
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
5
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
6
6
|
const { incomingHttpRequestStart, incomingHttpRequestEnd } = require('../../dd-trace/src/appsec/channels')
|
|
7
|
-
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
7
|
+
const { COMPONENT, SVC_SRC_KEY } = require('../../dd-trace/src/constants')
|
|
8
8
|
|
|
9
9
|
class HttpServerPlugin extends ServerPlugin {
|
|
10
10
|
static id = 'http'
|
|
@@ -18,16 +18,24 @@ class HttpServerPlugin extends ServerPlugin {
|
|
|
18
18
|
|
|
19
19
|
start ({ req, res, abortController }) {
|
|
20
20
|
let store = storage('legacy').getStore()
|
|
21
|
+
const { name: schemaServiceName, source: schemaServiceSource } = this.serviceName()
|
|
22
|
+
const service = this.config.service || schemaServiceName
|
|
23
|
+
const serviceSource = (this.config.service && service !== this.tracer._service)
|
|
24
|
+
? 'opt.plugin'
|
|
25
|
+
: (service === this.tracer._service ? undefined : schemaServiceSource)
|
|
21
26
|
const span = web.startSpan(
|
|
22
27
|
this.tracer,
|
|
23
28
|
{
|
|
24
29
|
...this.config,
|
|
25
|
-
service
|
|
30
|
+
service,
|
|
26
31
|
},
|
|
27
32
|
req,
|
|
28
33
|
res,
|
|
29
34
|
this.operationName()
|
|
30
35
|
)
|
|
36
|
+
if (serviceSource !== undefined) {
|
|
37
|
+
span.setTag(SVC_SRC_KEY, serviceSource)
|
|
38
|
+
}
|
|
31
39
|
span.setTag(COMPONENT, this.constructor.id)
|
|
32
40
|
span._integrationName = this.constructor.id
|
|
33
41
|
|
|
@@ -41,10 +41,10 @@ class Http2ClientPlugin extends ClientPlugin {
|
|
|
41
41
|
const span = this.startSpan(this.operationName(), {
|
|
42
42
|
childOf,
|
|
43
43
|
integrationName: this.constructor.id,
|
|
44
|
+
service: this.serviceName({ pluginConfig: this.config, sessionDetails }),
|
|
44
45
|
meta: {
|
|
45
46
|
[COMPONENT]: this.constructor.id,
|
|
46
47
|
[SPAN_KIND]: CLIENT,
|
|
47
|
-
'service.name': this.serviceName({ pluginConfig: this.config, sessionDetails }),
|
|
48
48
|
'resource.name': method,
|
|
49
49
|
'span.type': 'http',
|
|
50
50
|
'http.method': method,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const ServerPlugin = require('../../dd-trace/src/plugins/server')
|
|
6
6
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
7
|
-
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
7
|
+
const { COMPONENT, SVC_SRC_KEY } = require('../../dd-trace/src/constants')
|
|
8
8
|
|
|
9
9
|
class Http2ServerPlugin extends ServerPlugin {
|
|
10
10
|
constructor (tracer, config) {
|
|
@@ -19,17 +19,25 @@ class Http2ServerPlugin extends ServerPlugin {
|
|
|
19
19
|
bindStart (ctx) {
|
|
20
20
|
const { req, res } = ctx
|
|
21
21
|
|
|
22
|
+
const { name: schemaServiceName, source: schemaServiceSource } = this.serviceName()
|
|
23
|
+
const service = this.config.service || schemaServiceName
|
|
24
|
+
const serviceSource = (this.config.service && service !== this.tracer._service)
|
|
25
|
+
? 'opt.plugin'
|
|
26
|
+
: (service === this.tracer._service ? undefined : schemaServiceSource)
|
|
22
27
|
const span = web.startSpan(
|
|
23
28
|
this.tracer,
|
|
24
29
|
{
|
|
25
30
|
...this.config,
|
|
26
|
-
service
|
|
31
|
+
service,
|
|
27
32
|
},
|
|
28
33
|
req,
|
|
29
34
|
res,
|
|
30
35
|
this.operationName(),
|
|
31
36
|
ctx
|
|
32
37
|
)
|
|
38
|
+
if (serviceSource !== undefined) {
|
|
39
|
+
span.setTag(SVC_SRC_KEY, serviceSource)
|
|
40
|
+
}
|
|
33
41
|
|
|
34
42
|
span.setTag(COMPONENT, this.constructor.id)
|
|
35
43
|
span._integrationName = this.constructor.id
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real timers at module load time, before any test can install fake timers.
|
|
4
|
+
const realSetTimeout = setTimeout
|
|
5
|
+
|
|
3
6
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
4
7
|
const { storage } = require('../../datadog-core')
|
|
5
8
|
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
@@ -60,8 +63,7 @@ const CHILD_MESSAGE_END = 2
|
|
|
60
63
|
|
|
61
64
|
function withTimeout (promise, timeoutMs) {
|
|
62
65
|
return new Promise(resolve => {
|
|
63
|
-
|
|
64
|
-
setTimeout(resolve, timeoutMs)
|
|
66
|
+
realSetTimeout(resolve, timeoutMs)
|
|
65
67
|
|
|
66
68
|
// Also resolve if the original promise resolves
|
|
67
69
|
promise.then(resolve)
|
|
@@ -8,20 +8,47 @@ class KafkajsBatchConsumerPlugin extends ConsumerPlugin {
|
|
|
8
8
|
static id = 'kafkajs'
|
|
9
9
|
static operation = 'consume-batch'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
const { topic, messages, groupId, clusterId } = ctx.extractedArgs || ctx
|
|
11
|
+
bindStart (ctx) {
|
|
12
|
+
const { topic, partition, messages, groupId, clusterId } = ctx.extractedArgs || ctx
|
|
13
|
+
|
|
14
|
+
const span = this.startSpan({
|
|
15
|
+
resource: topic,
|
|
16
|
+
type: 'worker',
|
|
17
|
+
meta: {
|
|
18
|
+
component: this.constructor.id,
|
|
19
|
+
'kafka.topic': topic,
|
|
20
|
+
'kafka.cluster_id': clusterId,
|
|
21
|
+
'messaging.destination.name': topic,
|
|
22
|
+
'messaging.system': 'kafka',
|
|
23
|
+
},
|
|
24
|
+
metrics: {
|
|
25
|
+
'kafka.partition': partition,
|
|
26
|
+
'messaging.batch.message_count': messages.length,
|
|
27
|
+
},
|
|
28
|
+
}, ctx)
|
|
13
29
|
|
|
14
|
-
if (!this.config.dsmEnabled) return
|
|
15
30
|
for (const message of messages) {
|
|
16
31
|
if (!message || !message.headers) continue
|
|
32
|
+
|
|
33
|
+
const headers = convertToTextMap(message.headers)
|
|
34
|
+
if (headers) {
|
|
35
|
+
const childOf = this.tracer.extract('text_map', headers)
|
|
36
|
+
if (childOf) {
|
|
37
|
+
span.addLink(childOf)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!this.config.dsmEnabled) continue
|
|
17
42
|
const payloadSize = getMessageSize(message)
|
|
18
|
-
this.tracer.decodeDataStreamsContext(
|
|
43
|
+
this.tracer.decodeDataStreamsContext(headers)
|
|
19
44
|
const edgeTags = ['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka']
|
|
20
45
|
if (clusterId) {
|
|
21
46
|
edgeTags.push(`kafka_cluster_id:${clusterId}`)
|
|
22
47
|
}
|
|
23
48
|
this.tracer.setCheckpoint(edgeTags, null, payloadSize)
|
|
24
49
|
}
|
|
50
|
+
|
|
51
|
+
return ctx.currentStore
|
|
25
52
|
}
|
|
26
53
|
}
|
|
27
54
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real Date.now at module load time, before any test can install fake timers.
|
|
4
|
+
const realDateNow = Date.now.bind(Date)
|
|
5
|
+
|
|
3
6
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
4
7
|
const { storage } = require('../../datadog-core')
|
|
5
8
|
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
@@ -323,8 +326,8 @@ class MochaPlugin extends CiPlugin {
|
|
|
323
326
|
this.runningTestProbe = { file, line }
|
|
324
327
|
this.testErrorStackIndex = stackIndex
|
|
325
328
|
test._ddShouldWaitForHitProbe = true
|
|
326
|
-
const waitUntil =
|
|
327
|
-
while (
|
|
329
|
+
const waitUntil = realDateNow() + BREAKPOINT_SET_GRACE_PERIOD_MS
|
|
330
|
+
while (realDateNow() < waitUntil) {
|
|
328
331
|
// TODO: To avoid a race condition, we should wait until `probeInformation.setProbePromise` has resolved.
|
|
329
332
|
// However, Mocha doesn't have a mechanism for waiting asyncrounously here, so for now, we'll have to
|
|
330
333
|
// fall back to a fixed syncronous delay.
|
|
@@ -35,9 +35,9 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
35
35
|
}
|
|
36
36
|
const query = getQuery(ops)
|
|
37
37
|
const resource = truncate(getResource(this, ns, query, name))
|
|
38
|
-
const
|
|
38
|
+
const serviceResult = this.serviceName({ pluginConfig: this.config })
|
|
39
39
|
const span = this.startSpan(this.operationName(), {
|
|
40
|
-
service,
|
|
40
|
+
service: serviceResult,
|
|
41
41
|
resource,
|
|
42
42
|
type: 'mongodb',
|
|
43
43
|
kind: 'client',
|
|
@@ -49,7 +49,7 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
49
49
|
'out.port': options.port,
|
|
50
50
|
},
|
|
51
51
|
}, ctx)
|
|
52
|
-
const comment = this.injectDbmComment(span, ops.comment,
|
|
52
|
+
const comment = this.injectDbmComment(span, ops.comment, serviceResult.name)
|
|
53
53
|
if (comment) {
|
|
54
54
|
ops.comment = comment
|
|
55
55
|
}
|
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
const ServerPlugin = require('../../dd-trace/src/plugins/server')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
6
|
-
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
6
|
+
const { COMPONENT, SVC_SRC_KEY } = require('../../dd-trace/src/constants')
|
|
7
7
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
8
8
|
|
|
9
9
|
const errorPages = new Set(['/404', '/500', '/_error', '/_not-found', '/_not-found/page'])
|
|
10
10
|
|
|
11
11
|
class NextPlugin extends ServerPlugin {
|
|
12
12
|
static id = 'next'
|
|
13
|
-
#requestsBySpanId = new WeakMap()
|
|
14
13
|
|
|
15
14
|
constructor (...args) {
|
|
16
15
|
super(...args)
|
|
@@ -20,26 +19,28 @@ class NextPlugin extends ServerPlugin {
|
|
|
20
19
|
bindStart ({ req, res }) {
|
|
21
20
|
const store = storage('legacy').getStore()
|
|
22
21
|
const childOf = store ? store.span : store
|
|
22
|
+
const { name: schemaServiceName, source: schemaServiceSource } = this.serviceName()
|
|
23
|
+
const serviceName = this.config.service || schemaServiceName
|
|
24
|
+
let serviceSource = this.config.service ? 'opt.plugin' : schemaServiceSource
|
|
25
|
+
if (!serviceName || serviceName === this.tracer._service) serviceSource = undefined
|
|
26
|
+
|
|
23
27
|
const span = this.tracer.startSpan(this.operationName(), {
|
|
24
28
|
childOf,
|
|
25
29
|
tags: {
|
|
26
30
|
[COMPONENT]: this.constructor.id,
|
|
27
|
-
'service.name':
|
|
31
|
+
'service.name': serviceName,
|
|
28
32
|
'resource.name': req.method,
|
|
29
33
|
'span.type': 'web',
|
|
30
34
|
'span.kind': 'server',
|
|
31
35
|
'http.method': req.method,
|
|
36
|
+
...(serviceSource === undefined ? {} : { [SVC_SRC_KEY]: serviceSource }),
|
|
32
37
|
},
|
|
33
38
|
integrationName: this.constructor.id,
|
|
34
39
|
})
|
|
35
40
|
|
|
36
41
|
analyticsSampler.sample(span, this.config.measured, true)
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
const spanId = span.context()._spanId
|
|
40
|
-
this.#requestsBySpanId.set(spanId, req)
|
|
41
|
-
|
|
42
|
-
return { ...store, span }
|
|
43
|
+
return { ...store, span, req }
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
error ({ span, error }) {
|
|
@@ -90,14 +91,7 @@ class NextPlugin extends ServerPlugin {
|
|
|
90
91
|
|
|
91
92
|
if (!store) return
|
|
92
93
|
|
|
93
|
-
const span = store
|
|
94
|
-
|
|
95
|
-
const spanId = span.context()._spanId
|
|
96
|
-
const parentSpanId = span.context()._parentId
|
|
97
|
-
|
|
98
|
-
// Try current span first, then parent span.
|
|
99
|
-
// This handles cases where pageLoad runs in a child span context
|
|
100
|
-
const req = this.#requestsBySpanId.get(spanId) ?? this.#requestsBySpanId.get(parentSpanId)
|
|
94
|
+
const { span, req } = store
|
|
101
95
|
|
|
102
96
|
// safeguard against missing req in complicated timeout scenarios
|
|
103
97
|
if (!req) return
|