dd-trace 5.24.0 → 5.26.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.
Files changed (138) hide show
  1. package/LICENSE-3rdparty.csv +3 -0
  2. package/index.d.ts +345 -8
  3. package/init.js +60 -47
  4. package/package.json +16 -7
  5. package/packages/datadog-code-origin/index.js +4 -4
  6. package/packages/datadog-core/index.js +1 -3
  7. package/packages/datadog-core/src/storage.js +21 -0
  8. package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
  9. package/packages/datadog-esbuild/index.js +4 -2
  10. package/packages/datadog-instrumentations/src/amqplib.js +65 -5
  11. package/packages/datadog-instrumentations/src/child_process.js +135 -27
  12. package/packages/datadog-instrumentations/src/express.js +1 -1
  13. package/packages/datadog-instrumentations/src/handlebars.js +40 -0
  14. package/packages/datadog-instrumentations/src/helpers/hooks.js +5 -0
  15. package/packages/datadog-instrumentations/src/helpers/register.js +9 -0
  16. package/packages/datadog-instrumentations/src/jest.js +6 -2
  17. package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
  18. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
  19. package/packages/datadog-instrumentations/src/multer.js +37 -0
  20. package/packages/datadog-instrumentations/src/openai.js +2 -2
  21. package/packages/datadog-instrumentations/src/pug.js +23 -0
  22. package/packages/datadog-instrumentations/src/router.js +2 -3
  23. package/packages/datadog-instrumentations/src/url.js +84 -0
  24. package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
  25. package/packages/datadog-plugin-amqplib/src/consumer.js +6 -5
  26. package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
  27. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  28. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +10 -7
  29. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +35 -0
  30. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +11 -9
  31. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +59 -45
  32. package/packages/datadog-plugin-cypress/src/support.js +1 -0
  33. package/packages/datadog-plugin-fastify/src/code_origin.js +2 -2
  34. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +10 -2
  35. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
  36. package/packages/datadog-plugin-grpc/src/client.js +3 -0
  37. package/packages/datadog-plugin-grpc/src/server.js +5 -1
  38. package/packages/datadog-plugin-http/src/client.js +42 -1
  39. package/packages/datadog-plugin-http2/src/client.js +26 -1
  40. package/packages/datadog-plugin-jest/src/index.js +2 -1
  41. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
  42. package/packages/datadog-plugin-kafkajs/src/consumer.js +10 -5
  43. package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
  44. package/packages/datadog-plugin-mocha/src/index.js +5 -2
  45. package/packages/datadog-plugin-moleculer/src/server.js +2 -2
  46. package/packages/datadog-plugin-openai/src/index.js +9 -1015
  47. package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
  48. package/packages/datadog-plugin-rhea/src/consumer.js +2 -1
  49. package/packages/datadog-plugin-vitest/src/index.js +2 -1
  50. package/packages/dd-trace/src/appsec/addresses.js +2 -0
  51. package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
  52. package/packages/dd-trace/src/appsec/channels.js +3 -1
  53. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
  54. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +33 -16
  55. package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +18 -0
  56. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +55 -7
  57. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -2
  58. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
  59. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -2
  60. package/packages/dd-trace/src/appsec/index.js +9 -6
  61. package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
  62. package/packages/dd-trace/src/appsec/rasp/index.js +3 -0
  63. package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
  64. package/packages/dd-trace/src/appsec/rasp/utils.js +3 -2
  65. package/packages/dd-trace/src/appsec/recommended.json +354 -158
  66. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
  67. package/packages/dd-trace/src/appsec/remote_config/index.js +2 -7
  68. package/packages/dd-trace/src/appsec/reporter.js +6 -4
  69. package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -3
  70. package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
  71. package/packages/dd-trace/src/azure_metadata.js +120 -0
  72. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
  73. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
  74. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
  75. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
  76. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
  77. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
  78. package/packages/dd-trace/src/config.js +88 -10
  79. package/packages/dd-trace/src/constants.js +8 -1
  80. package/packages/dd-trace/src/crashtracking/crashtracker.js +98 -0
  81. package/packages/dd-trace/src/crashtracking/index.js +15 -0
  82. package/packages/dd-trace/src/crashtracking/noop.js +8 -0
  83. package/packages/dd-trace/src/datastreams/pathway.js +1 -0
  84. package/packages/dd-trace/src/debugger/devtools_client/index.js +9 -13
  85. package/packages/dd-trace/src/debugger/devtools_client/send.js +15 -1
  86. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +57 -23
  87. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +12 -2
  88. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +31 -20
  89. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
  90. package/packages/dd-trace/src/debugger/devtools_client/state.js +11 -2
  91. package/packages/dd-trace/src/debugger/index.js +10 -3
  92. package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
  93. package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
  94. package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
  95. package/packages/dd-trace/src/llmobs/index.js +103 -0
  96. package/packages/dd-trace/src/llmobs/noop.js +82 -0
  97. package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
  98. package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
  99. package/packages/dd-trace/src/llmobs/sdk.js +377 -0
  100. package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
  101. package/packages/dd-trace/src/llmobs/storage.js +7 -0
  102. package/packages/dd-trace/src/llmobs/tagger.js +322 -0
  103. package/packages/dd-trace/src/llmobs/util.js +176 -0
  104. package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
  105. package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
  106. package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
  107. package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
  108. package/packages/dd-trace/src/llmobs/writers/spans/base.js +52 -0
  109. package/packages/dd-trace/src/log/index.js +10 -13
  110. package/packages/dd-trace/src/log/log.js +52 -0
  111. package/packages/dd-trace/src/log/writer.js +50 -19
  112. package/packages/dd-trace/src/noop/proxy.js +3 -0
  113. package/packages/dd-trace/src/noop/span.js +4 -0
  114. package/packages/dd-trace/src/opentelemetry/span.js +16 -1
  115. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
  116. package/packages/dd-trace/src/opentracing/propagation/text_map.js +106 -32
  117. package/packages/dd-trace/src/opentracing/span.js +26 -0
  118. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  119. package/packages/dd-trace/src/opentracing/tracer.js +8 -1
  120. package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
  121. package/packages/dd-trace/src/plugins/outbound.js +9 -0
  122. package/packages/dd-trace/src/plugins/tracing.js +3 -3
  123. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +121 -0
  124. package/packages/dd-trace/src/plugins/util/ip_extractor.js +0 -1
  125. package/packages/dd-trace/src/plugins/util/web.js +39 -11
  126. package/packages/dd-trace/src/priority_sampler.js +16 -0
  127. package/packages/dd-trace/src/profiling/config.js +3 -1
  128. package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
  129. package/packages/dd-trace/src/profiling/profilers/wall.js +2 -1
  130. package/packages/dd-trace/src/proxy.js +13 -1
  131. package/packages/dd-trace/src/span_processor.js +5 -0
  132. package/packages/dd-trace/src/telemetry/index.js +11 -1
  133. package/packages/dd-trace/src/telemetry/logs/index.js +16 -11
  134. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -8
  135. package/packages/dd-trace/src/telemetry/metrics.js +6 -1
  136. package/packages/dd-trace/src/util.js +16 -1
  137. package/version.js +4 -2
  138. /package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/{code-injection-sensitive-analyzer.js → tainted-range-based-sensitive-analyzer.js} +0 -0
@@ -654,55 +654,69 @@ class CypressPlugin {
654
654
  return this.activeTestSpan ? { traceId: this.activeTestSpan.context().toTraceId() } : {}
655
655
  },
656
656
  'dd:afterEach': ({ test, coverage }) => {
657
- const { state, error, isRUMActive, testSourceLine, testSuite, testName, isNew, isEfdRetry } = test
658
- if (this.activeTestSpan) {
659
- if (coverage && this.isCodeCoverageEnabled && this.tracer._tracer._exporter?.exportCoverage) {
660
- const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
661
- const relativeCoverageFiles = coverageFiles.map(file => getTestSuitePath(file, this.rootDir))
662
- if (!relativeCoverageFiles.length) {
663
- incrementCountMetric(TELEMETRY_CODE_COVERAGE_EMPTY)
664
- }
665
- distributionMetric(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
666
- const { _traceId, _spanId } = this.testSuiteSpan.context()
667
- const formattedCoverage = {
668
- sessionId: _traceId,
669
- suiteId: _spanId,
670
- testId: this.activeTestSpan.context()._spanId,
671
- files: relativeCoverageFiles
672
- }
673
- this.tracer._tracer._exporter.exportCoverage(formattedCoverage)
674
- }
675
- const testStatus = CYPRESS_STATUS_TO_TEST_STATUS[state]
676
- this.activeTestSpan.setTag(TEST_STATUS, testStatus)
677
-
678
- if (error) {
679
- this.activeTestSpan.setTag('error', error)
680
- }
681
- if (isRUMActive) {
682
- this.activeTestSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
683
- }
684
- if (testSourceLine) {
685
- this.activeTestSpan.setTag(TEST_SOURCE_START, testSourceLine)
686
- }
687
- if (isNew) {
688
- this.activeTestSpan.setTag(TEST_IS_NEW, 'true')
689
- if (isEfdRetry) {
690
- this.activeTestSpan.setTag(TEST_IS_RETRY, 'true')
691
- }
657
+ if (!this.activeTestSpan) {
658
+ log.warn('There is no active test span in dd:afterEach handler')
659
+ return null
660
+ }
661
+ const {
662
+ state,
663
+ error,
664
+ isRUMActive,
665
+ testSourceLine,
666
+ testSuite,
667
+ testSuiteAbsolutePath,
668
+ testName,
669
+ isNew,
670
+ isEfdRetry
671
+ } = test
672
+ if (coverage && this.isCodeCoverageEnabled && this.tracer._tracer._exporter?.exportCoverage) {
673
+ const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
674
+ const relativeCoverageFiles = [...coverageFiles, testSuiteAbsolutePath].map(
675
+ file => getTestSuitePath(file, this.repositoryRoot || this.rootDir)
676
+ )
677
+ if (!relativeCoverageFiles.length) {
678
+ incrementCountMetric(TELEMETRY_CODE_COVERAGE_EMPTY)
692
679
  }
693
- const finishedTest = {
694
- testName,
695
- testStatus,
696
- finishTime: this.activeTestSpan._getTime(), // we store the finish time here
697
- testSpan: this.activeTestSpan
680
+ distributionMetric(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
681
+ const { _traceId, _spanId } = this.testSuiteSpan.context()
682
+ const formattedCoverage = {
683
+ sessionId: _traceId,
684
+ suiteId: _spanId,
685
+ testId: this.activeTestSpan.context()._spanId,
686
+ files: relativeCoverageFiles
698
687
  }
699
- if (this.finishedTestsByFile[testSuite]) {
700
- this.finishedTestsByFile[testSuite].push(finishedTest)
701
- } else {
702
- this.finishedTestsByFile[testSuite] = [finishedTest]
688
+ this.tracer._tracer._exporter.exportCoverage(formattedCoverage)
689
+ }
690
+ const testStatus = CYPRESS_STATUS_TO_TEST_STATUS[state]
691
+ this.activeTestSpan.setTag(TEST_STATUS, testStatus)
692
+
693
+ if (error) {
694
+ this.activeTestSpan.setTag('error', error)
695
+ }
696
+ if (isRUMActive) {
697
+ this.activeTestSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
698
+ }
699
+ if (testSourceLine) {
700
+ this.activeTestSpan.setTag(TEST_SOURCE_START, testSourceLine)
701
+ }
702
+ if (isNew) {
703
+ this.activeTestSpan.setTag(TEST_IS_NEW, 'true')
704
+ if (isEfdRetry) {
705
+ this.activeTestSpan.setTag(TEST_IS_RETRY, 'true')
703
706
  }
704
- // test spans are finished at after:spec
705
707
  }
708
+ const finishedTest = {
709
+ testName,
710
+ testStatus,
711
+ finishTime: this.activeTestSpan._getTime(), // we store the finish time here
712
+ testSpan: this.activeTestSpan
713
+ }
714
+ if (this.finishedTestsByFile[testSuite]) {
715
+ this.finishedTestsByFile[testSuite].push(finishedTest)
716
+ } else {
717
+ this.finishedTestsByFile[testSuite] = [finishedTest]
718
+ }
719
+ // test spans are finished at after:spec
706
720
  this.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test', {
707
721
  hasCodeOwners: !!this.activeTestSpan.context()._tags[TEST_CODE_OWNERS],
708
722
  isNew,
@@ -88,6 +88,7 @@ afterEach(function () {
88
88
  const testInfo = {
89
89
  testName: currentTest.fullTitle(),
90
90
  testSuite: Cypress.mocha.getRootSuite().file,
91
+ testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute,
91
92
  state: currentTest.state,
92
93
  error: currentTest.err,
93
94
  isNew: currentTest._ddIsNew,
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { entryTag } = require('../../datadog-code-origin')
3
+ const { entryTags } = require('../../datadog-code-origin')
4
4
  const Plugin = require('../../dd-trace/src/plugins/plugin')
5
5
  const web = require('../../dd-trace/src/plugins/util/web')
6
6
 
@@ -23,7 +23,7 @@ class FastifyCodeOriginForSpansPlugin extends Plugin {
23
23
 
24
24
  this.addSub('apm:fastify:route:added', ({ routeOptions, onRoute }) => {
25
25
  if (!routeOptions.config) routeOptions.config = {}
26
- routeOptions.config[kCodeOriginForSpansTagsSym] = entryTag(onRoute)
26
+ routeOptions.config[kCodeOriginForSpansTagsSym] = entryTags(onRoute)
27
27
  })
28
28
  }
29
29
  }
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { getMessageSize } = require('../../dd-trace/src/datastreams/processor')
3
4
  const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
4
5
 
5
6
  class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
@@ -11,7 +12,7 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
11
12
  const topic = subscription.metadata && subscription.metadata.topic
12
13
  const childOf = this.tracer.extract('text_map', message.attributes) || null
13
14
 
14
- this.startSpan({
15
+ const span = this.startSpan({
15
16
  childOf,
16
17
  resource: topic,
17
18
  type: 'worker',
@@ -21,8 +22,15 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
21
22
  },
22
23
  metrics: {
23
24
  'pubsub.ack': 0
24
- }
25
+ },
26
+ extractedLinks: childOf?._links
25
27
  })
28
+ if (this.config.dsmEnabled && message?.attributes) {
29
+ const payloadSize = getMessageSize(message)
30
+ this.tracer.decodeDataStreamsContext(message.attributes)
31
+ this.tracer
32
+ .setCheckpoint(['direction:in', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
33
+ }
26
34
  }
27
35
 
28
36
  finish (message) {
@@ -1,6 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
+ const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
5
+ const { getHeadersSize } = require('../../dd-trace/src/datastreams/processor')
4
6
 
5
7
  class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
6
8
  static get id () { return 'google-cloud-pubsub' }
@@ -25,6 +27,12 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
25
27
  msg.attributes = {}
26
28
  }
27
29
  this.tracer.inject(span, 'text_map', msg.attributes)
30
+ if (this.config.dsmEnabled) {
31
+ const payloadSize = getHeadersSize(msg)
32
+ const dataStreamsContext = this.tracer
33
+ .setCheckpoint(['direction:out', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
34
+ DsmPathwayCodec.encode(dataStreamsContext, msg.attributes)
35
+ }
28
36
  }
29
37
  }
30
38
  }
@@ -64,6 +64,9 @@ class GrpcClientPlugin extends ClientPlugin {
64
64
 
65
65
  error ({ span, error }) {
66
66
  this.addCode(span, error.code)
67
+ if (error.code && !this._tracerConfig.grpc.client.error.statuses.includes(error.code)) {
68
+ return
69
+ }
67
70
  this.addError(error, span)
68
71
  }
69
72
 
@@ -48,7 +48,8 @@ class GrpcServerPlugin extends ServerPlugin {
48
48
  },
49
49
  metrics: {
50
50
  'grpc.status.code': 0
51
- }
51
+ },
52
+ extractedLinks: childOf?._links
52
53
  })
53
54
 
54
55
  addMetadataTags(span, metadata, metadataFilter, 'request')
@@ -70,6 +71,9 @@ class GrpcServerPlugin extends ServerPlugin {
70
71
  if (!span) return
71
72
 
72
73
  this.addCode(span, error.code)
74
+ if (error.code && !this._tracerConfig.grpc.server.error.statuses.includes(error.code)) {
75
+ return
76
+ }
73
77
  this.addError(error)
74
78
  }
75
79
 
@@ -58,7 +58,7 @@ class HttpClientPlugin extends ClientPlugin {
58
58
  span._spanContext._trace.record = false
59
59
  }
60
60
 
61
- if (this.config.propagationFilter(uri)) {
61
+ if (this.shouldInjectTraceHeaders(options, uri)) {
62
62
  this.tracer.inject(span, HTTP_HEADERS, options.headers)
63
63
  }
64
64
 
@@ -71,6 +71,18 @@ class HttpClientPlugin extends ClientPlugin {
71
71
  return message.currentStore
72
72
  }
73
73
 
74
+ shouldInjectTraceHeaders (options, uri) {
75
+ if (hasAmazonSignature(options) && !this.config.enablePropagationWithAmazonHeaders) {
76
+ return false
77
+ }
78
+
79
+ if (!this.config.propagationFilter(uri)) {
80
+ return false
81
+ }
82
+
83
+ return true
84
+ }
85
+
74
86
  bindAsyncStart ({ parentStore }) {
75
87
  return parentStore
76
88
  }
@@ -200,6 +212,31 @@ function getHooks (config) {
200
212
  return { request }
201
213
  }
202
214
 
215
+ function hasAmazonSignature (options) {
216
+ if (!options) {
217
+ return false
218
+ }
219
+
220
+ if (options.headers) {
221
+ const headers = Object.keys(options.headers)
222
+ .reduce((prev, next) => Object.assign(prev, {
223
+ [next.toLowerCase()]: options.headers[next]
224
+ }), {})
225
+
226
+ if (headers['x-amz-signature']) {
227
+ return true
228
+ }
229
+
230
+ if ([].concat(headers.authorization).some(startsWith('AWS4-HMAC-SHA256'))) {
231
+ return true
232
+ }
233
+ }
234
+
235
+ const search = options.search || options.path
236
+
237
+ return search && search.toLowerCase().indexOf('x-amz-signature=') !== -1
238
+ }
239
+
203
240
  function extractSessionDetails (options) {
204
241
  if (typeof options === 'string') {
205
242
  return new URL(options).host
@@ -211,4 +248,8 @@ function extractSessionDetails (options) {
211
248
  return { host, port }
212
249
  }
213
250
 
251
+ function startsWith (searchString) {
252
+ return value => String(value).startsWith(searchString)
253
+ }
254
+
214
255
  module.exports = HttpClientPlugin
@@ -62,7 +62,9 @@ class Http2ClientPlugin extends ClientPlugin {
62
62
 
63
63
  addHeaderTags(span, headers, HTTP_REQUEST_HEADERS, this.config)
64
64
 
65
- this.tracer.inject(span, HTTP_HEADERS, headers)
65
+ if (!hasAmazonSignature(headers, path)) {
66
+ this.tracer.inject(span, HTTP_HEADERS, headers)
67
+ }
66
68
 
67
69
  message.parentStore = store
68
70
  message.currentStore = { ...store, span }
@@ -132,6 +134,29 @@ function extractSessionDetails (authority, options) {
132
134
  return { protocol, port, host }
133
135
  }
134
136
 
137
+ function hasAmazonSignature (headers, path) {
138
+ if (headers) {
139
+ headers = Object.keys(headers)
140
+ .reduce((prev, next) => Object.assign(prev, {
141
+ [next.toLowerCase()]: headers[next]
142
+ }), {})
143
+
144
+ if (headers['x-amz-signature']) {
145
+ return true
146
+ }
147
+
148
+ if ([].concat(headers.authorization).some(startsWith('AWS4-HMAC-SHA256'))) {
149
+ return true
150
+ }
151
+ }
152
+
153
+ return path && path.toLowerCase().indexOf('x-amz-signature=') !== -1
154
+ }
155
+
156
+ function startsWith (searchString) {
157
+ return value => String(value).startsWith(searchString)
158
+ }
159
+
135
160
  function getStatusValidator (config) {
136
161
  if (typeof config.validateStatus === 'function') {
137
162
  return config.validateStatus
@@ -219,7 +219,8 @@ class JestPlugin extends CiPlugin {
219
219
  [COMPONENT]: this.constructor.id,
220
220
  ...this.testEnvironmentMetadata,
221
221
  ...testSuiteMetadata
222
- }
222
+ },
223
+ extractedLinks: testSessionSpanContext?._links
223
224
  })
224
225
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
225
226
  if (_ddTestCodeCoverageEnabled) {
@@ -5,14 +5,17 @@ class KafkajsBatchConsumerPlugin extends ConsumerPlugin {
5
5
  static get id () { return 'kafkajs' }
6
6
  static get operation () { return 'consume-batch' }
7
7
 
8
- start ({ topic, partition, messages, groupId }) {
8
+ start ({ topic, partition, messages, groupId, clusterId }) {
9
9
  if (!this.config.dsmEnabled) return
10
10
  for (const message of messages) {
11
11
  if (!message || !message.headers) continue
12
12
  const payloadSize = getMessageSize(message)
13
13
  this.tracer.decodeDataStreamsContext(message.headers)
14
- this.tracer
15
- .setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'], null, payloadSize)
14
+ const edgeTags = ['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka']
15
+ if (clusterId) {
16
+ edgeTags.push(`kafka_cluster_id:${clusterId}`)
17
+ }
18
+ this.tracer.setCheckpoint(edgeTags, null, payloadSize)
16
19
  }
17
20
  }
18
21
  }
@@ -62,7 +62,7 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
62
62
  }
63
63
  }
64
64
 
65
- start ({ topic, partition, message, groupId }) {
65
+ start ({ topic, partition, message, groupId, clusterId }) {
66
66
  const childOf = extract(this.tracer, message.headers)
67
67
  const span = this.startSpan({
68
68
  childOf,
@@ -71,17 +71,22 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
71
71
  meta: {
72
72
  component: 'kafkajs',
73
73
  'kafka.topic': topic,
74
- 'kafka.message.offset': message.offset
74
+ 'kafka.message.offset': message.offset,
75
+ 'kafka.cluster_id': clusterId
75
76
  },
76
77
  metrics: {
77
78
  'kafka.partition': partition
78
- }
79
+ },
80
+ extractedLinks: childOf?._links
79
81
  })
80
82
  if (this.config.dsmEnabled && message?.headers) {
81
83
  const payloadSize = getMessageSize(message)
82
84
  this.tracer.decodeDataStreamsContext(message.headers)
83
- this.tracer
84
- .setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'], span, payloadSize)
85
+ const edgeTags = ['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka']
86
+ if (clusterId) {
87
+ edgeTags.push(`kafka_cluster_id:${clusterId}`)
88
+ }
89
+ this.tracer.setCheckpoint(edgeTags, span, payloadSize)
85
90
  }
86
91
 
87
92
  if (afterStartCh.hasSubscribers) {
@@ -66,12 +66,13 @@ class KafkajsProducerPlugin extends ProducerPlugin {
66
66
  }
67
67
  }
68
68
 
69
- start ({ topic, messages, bootstrapServers }) {
69
+ start ({ topic, messages, bootstrapServers, clusterId }) {
70
70
  const span = this.startSpan({
71
71
  resource: topic,
72
72
  meta: {
73
73
  component: 'kafkajs',
74
- 'kafka.topic': topic
74
+ 'kafka.topic': topic,
75
+ 'kafka.cluster_id': clusterId
75
76
  },
76
77
  metrics: {
77
78
  'kafka.batch_size': messages.length
@@ -85,8 +86,13 @@ class KafkajsProducerPlugin extends ProducerPlugin {
85
86
  this.tracer.inject(span, 'text_map', message.headers)
86
87
  if (this.config.dsmEnabled) {
87
88
  const payloadSize = getMessageSize(message)
88
- const dataStreamsContext = this.tracer
89
- .setCheckpoint(['direction:out', `topic:${topic}`, 'type:kafka'], span, payloadSize)
89
+ const edgeTags = ['direction:out', `topic:${topic}`, 'type:kafka']
90
+
91
+ if (clusterId) {
92
+ edgeTags.push(`kafka_cluster_id:${clusterId}`)
93
+ }
94
+
95
+ const dataStreamsContext = this.tracer.setCheckpoint(edgeTags, span, payloadSize)
90
96
  DsmPathwayCodec.encode(dataStreamsContext, message.headers)
91
97
  }
92
98
  }
@@ -85,7 +85,7 @@ class MochaPlugin extends CiPlugin {
85
85
  }
86
86
 
87
87
  const relativeCoverageFiles = [...coverageFiles, suiteFile]
88
- .map(filename => getTestSuitePath(filename, this.sourceRoot))
88
+ .map(filename => getTestSuitePath(filename, this.repositoryRoot || this.sourceRoot))
89
89
 
90
90
  const { _traceId, _spanId } = testSuiteSpan.context()
91
91
 
@@ -242,7 +242,7 @@ class MochaPlugin extends CiPlugin {
242
242
  }
243
243
  })
244
244
 
245
- this.addSub('ci:mocha:test:retry', (isFirstAttempt) => {
245
+ this.addSub('ci:mocha:test:retry', ({ isFirstAttempt, err }) => {
246
246
  const store = storage.getStore()
247
247
  const span = store?.span
248
248
  if (span) {
@@ -250,6 +250,9 @@ class MochaPlugin extends CiPlugin {
250
250
  if (!isFirstAttempt) {
251
251
  span.setTag(TEST_IS_RETRY, 'true')
252
252
  }
253
+ if (err) {
254
+ span.setTag('error', err)
255
+ }
253
256
 
254
257
  const spanTags = span.context()._tags
255
258
  this.telemetry.ciVisEvent(
@@ -9,7 +9,6 @@ class MoleculerServerPlugin extends ServerPlugin {
9
9
 
10
10
  start ({ action, ctx, broker }) {
11
11
  const followsFrom = this.tracer.extract('text_map', ctx.meta)
12
-
13
12
  this.startSpan(this.operationName(), {
14
13
  childOf: followsFrom || this.activeSpan,
15
14
  service: this.config.service || this.serviceName(),
@@ -19,7 +18,8 @@ class MoleculerServerPlugin extends ServerPlugin {
19
18
  meta: {
20
19
  'resource.name': action.name,
21
20
  ...moleculerTags(broker, ctx, this.config)
22
- }
21
+ },
22
+ extractedLinks: followsFrom?._links
23
23
  })
24
24
  }
25
25
  }