dd-trace 5.24.0 → 5.25.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 (98) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/index.d.ts +335 -0
  3. package/package.json +13 -7
  4. package/packages/datadog-code-origin/index.js +4 -4
  5. package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
  6. package/packages/datadog-esbuild/index.js +4 -2
  7. package/packages/datadog-instrumentations/src/amqplib.js +65 -5
  8. package/packages/datadog-instrumentations/src/child_process.js +135 -27
  9. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
  10. package/packages/datadog-instrumentations/src/helpers/register.js +9 -0
  11. package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
  12. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
  13. package/packages/datadog-instrumentations/src/multer.js +37 -0
  14. package/packages/datadog-instrumentations/src/openai.js +2 -2
  15. package/packages/datadog-instrumentations/src/url.js +84 -0
  16. package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
  17. package/packages/datadog-plugin-amqplib/src/consumer.js +4 -4
  18. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  19. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  20. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -0
  21. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  22. package/packages/datadog-plugin-fastify/src/code_origin.js +2 -2
  23. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +8 -1
  24. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
  25. package/packages/datadog-plugin-grpc/src/client.js +3 -0
  26. package/packages/datadog-plugin-grpc/src/server.js +3 -0
  27. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
  28. package/packages/datadog-plugin-kafkajs/src/consumer.js +8 -4
  29. package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
  30. package/packages/datadog-plugin-mocha/src/index.js +4 -1
  31. package/packages/datadog-plugin-openai/src/index.js +9 -1015
  32. package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
  33. package/packages/dd-trace/src/appsec/addresses.js +2 -0
  34. package/packages/dd-trace/src/appsec/channels.js +3 -1
  35. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +55 -7
  36. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -2
  37. package/packages/dd-trace/src/appsec/index.js +3 -0
  38. package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
  39. package/packages/dd-trace/src/appsec/rasp/index.js +3 -0
  40. package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
  41. package/packages/dd-trace/src/appsec/rasp/utils.js +3 -2
  42. package/packages/dd-trace/src/appsec/recommended.json +2 -4
  43. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -0
  44. package/packages/dd-trace/src/appsec/remote_config/index.js +2 -0
  45. package/packages/dd-trace/src/appsec/reporter.js +5 -4
  46. package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -3
  47. package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
  48. package/packages/dd-trace/src/azure_metadata.js +120 -0
  49. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
  50. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
  51. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
  52. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
  53. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
  54. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
  55. package/packages/dd-trace/src/config.js +75 -6
  56. package/packages/dd-trace/src/constants.js +3 -1
  57. package/packages/dd-trace/src/datastreams/pathway.js +1 -0
  58. package/packages/dd-trace/src/debugger/devtools_client/index.js +9 -13
  59. package/packages/dd-trace/src/debugger/devtools_client/send.js +15 -1
  60. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +57 -23
  61. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +12 -2
  62. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +31 -20
  63. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
  64. package/packages/dd-trace/src/debugger/devtools_client/state.js +11 -2
  65. package/packages/dd-trace/src/debugger/index.js +10 -3
  66. package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
  67. package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
  68. package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
  69. package/packages/dd-trace/src/llmobs/index.js +103 -0
  70. package/packages/dd-trace/src/llmobs/noop.js +82 -0
  71. package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
  72. package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
  73. package/packages/dd-trace/src/llmobs/sdk.js +377 -0
  74. package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
  75. package/packages/dd-trace/src/llmobs/storage.js +7 -0
  76. package/packages/dd-trace/src/llmobs/tagger.js +322 -0
  77. package/packages/dd-trace/src/llmobs/util.js +176 -0
  78. package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
  79. package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
  80. package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
  81. package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
  82. package/packages/dd-trace/src/llmobs/writers/spans/base.js +49 -0
  83. package/packages/dd-trace/src/noop/proxy.js +3 -0
  84. package/packages/dd-trace/src/noop/span.js +3 -0
  85. package/packages/dd-trace/src/opentelemetry/span.js +1 -1
  86. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
  87. package/packages/dd-trace/src/opentracing/propagation/text_map.js +73 -12
  88. package/packages/dd-trace/src/opentracing/span.js +12 -0
  89. package/packages/dd-trace/src/opentracing/tracer.js +8 -1
  90. package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
  91. package/packages/dd-trace/src/plugins/outbound.js +9 -0
  92. package/packages/dd-trace/src/priority_sampler.js +16 -0
  93. package/packages/dd-trace/src/profiling/config.js +3 -1
  94. package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
  95. package/packages/dd-trace/src/profiling/profilers/wall.js +2 -1
  96. package/packages/dd-trace/src/proxy.js +8 -1
  97. package/packages/dd-trace/src/span_processor.js +5 -0
  98. package/packages/dd-trace/src/telemetry/index.js +11 -1
@@ -0,0 +1,111 @@
1
+ 'use strict'
2
+
3
+ const request = require('../../exporters/common/request')
4
+ const { URL, format } = require('url')
5
+
6
+ const logger = require('../../log')
7
+
8
+ const { encodeUnicode } = require('../util')
9
+ const log = require('../../log')
10
+
11
+ class BaseLLMObsWriter {
12
+ constructor ({ interval, timeout, endpoint, intake, eventType, protocol, port }) {
13
+ this._interval = interval || 1000 // 1s
14
+ this._timeout = timeout || 5000 // 5s
15
+ this._eventType = eventType
16
+
17
+ this._buffer = []
18
+ this._bufferLimit = 1000
19
+ this._bufferSize = 0
20
+
21
+ this._url = new URL(format({
22
+ protocol: protocol || 'https:',
23
+ hostname: intake,
24
+ port: port || 443,
25
+ pathname: endpoint
26
+ }))
27
+
28
+ this._headers = {
29
+ 'Content-Type': 'application/json'
30
+ }
31
+
32
+ this._periodic = setInterval(() => {
33
+ this.flush()
34
+ }, this._interval).unref()
35
+
36
+ process.once('beforeExit', () => {
37
+ this.destroy()
38
+ })
39
+
40
+ this._destroyed = false
41
+
42
+ logger.debug(`Started ${this.constructor.name} to ${this._url}`)
43
+ }
44
+
45
+ append (event, byteLength) {
46
+ if (this._buffer.length >= this._bufferLimit) {
47
+ logger.warn(`${this.constructor.name} event buffer full (limit is ${this._bufferLimit}), dropping event`)
48
+ return
49
+ }
50
+
51
+ this._bufferSize += byteLength || Buffer.from(JSON.stringify(event)).byteLength
52
+ this._buffer.push(event)
53
+ }
54
+
55
+ flush () {
56
+ if (this._buffer.length === 0) {
57
+ return
58
+ }
59
+
60
+ const events = this._buffer
61
+ this._buffer = []
62
+ this._bufferSize = 0
63
+ const payload = this._encode(this.makePayload(events))
64
+
65
+ const options = {
66
+ headers: this._headers,
67
+ method: 'POST',
68
+ url: this._url,
69
+ timeout: this._timeout
70
+ }
71
+
72
+ log.debug(`Encoded LLMObs payload: ${payload}`)
73
+
74
+ request(payload, options, (err, resp, code) => {
75
+ if (err) {
76
+ logger.error(
77
+ `Error sending ${events.length} LLMObs ${this._eventType} events to ${this._url}: ${err.message}`
78
+ )
79
+ } else if (code >= 300) {
80
+ logger.error(
81
+ `Error sending ${events.length} LLMObs ${this._eventType} events to ${this._url}: ${code}`
82
+ )
83
+ } else {
84
+ logger.debug(`Sent ${events.length} LLMObs ${this._eventType} events to ${this._url}`)
85
+ }
86
+ })
87
+ }
88
+
89
+ makePayload (events) {}
90
+
91
+ destroy () {
92
+ if (!this._destroyed) {
93
+ logger.debug(`Stopping ${this.constructor.name}`)
94
+ clearInterval(this._periodic)
95
+ process.removeListener('beforeExit', this.destroy)
96
+ this.flush()
97
+ this._destroyed = true
98
+ }
99
+ }
100
+
101
+ _encode (payload) {
102
+ return JSON.stringify(payload, (key, value) => {
103
+ if (typeof value === 'string') {
104
+ return encodeUnicode(value) // serialize unicode characters
105
+ }
106
+ return value
107
+ }).replace(/\\\\u/g, '\\u') // remove double escaping
108
+ }
109
+ }
110
+
111
+ module.exports = BaseLLMObsWriter
@@ -0,0 +1,29 @@
1
+ 'use strict'
2
+
3
+ const { AGENTLESS_EVALULATIONS_ENDPOINT } = require('../constants/writers')
4
+ const BaseWriter = require('./base')
5
+
6
+ class LLMObsEvalMetricsWriter extends BaseWriter {
7
+ constructor (config) {
8
+ super({
9
+ endpoint: AGENTLESS_EVALULATIONS_ENDPOINT,
10
+ intake: `api.${config.site}`,
11
+ eventType: 'evaluation_metric'
12
+ })
13
+
14
+ this._headers['DD-API-KEY'] = config.apiKey
15
+ }
16
+
17
+ makePayload (events) {
18
+ return {
19
+ data: {
20
+ type: this._eventType,
21
+ attributes: {
22
+ metrics: events
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+
29
+ module.exports = LLMObsEvalMetricsWriter
@@ -0,0 +1,23 @@
1
+ 'use strict'
2
+
3
+ const {
4
+ EVP_SUBDOMAIN_HEADER_NAME,
5
+ EVP_SUBDOMAIN_HEADER_VALUE,
6
+ EVP_PROXY_AGENT_ENDPOINT
7
+ } = require('../../constants/writers')
8
+ const LLMObsBaseSpanWriter = require('./base')
9
+
10
+ class LLMObsAgentProxySpanWriter extends LLMObsBaseSpanWriter {
11
+ constructor (config) {
12
+ super({
13
+ intake: config.hostname || 'localhost',
14
+ protocol: 'http:',
15
+ endpoint: EVP_PROXY_AGENT_ENDPOINT,
16
+ port: config.port
17
+ })
18
+
19
+ this._headers[EVP_SUBDOMAIN_HEADER_NAME] = EVP_SUBDOMAIN_HEADER_VALUE
20
+ }
21
+ }
22
+
23
+ module.exports = LLMObsAgentProxySpanWriter
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ const { AGENTLESS_SPANS_ENDPOINT } = require('../../constants/writers')
4
+ const LLMObsBaseSpanWriter = require('./base')
5
+
6
+ class LLMObsAgentlessSpanWriter extends LLMObsBaseSpanWriter {
7
+ constructor (config) {
8
+ super({
9
+ intake: `llmobs-intake.${config.site}`,
10
+ endpoint: AGENTLESS_SPANS_ENDPOINT
11
+ })
12
+
13
+ this._headers['DD-API-KEY'] = config.apiKey
14
+ }
15
+ }
16
+
17
+ module.exports = LLMObsAgentlessSpanWriter
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const { EVP_EVENT_SIZE_LIMIT, EVP_PAYLOAD_SIZE_LIMIT } = require('../../constants/writers')
4
+ const { DROPPED_VALUE_TEXT } = require('../../constants/text')
5
+ const { DROPPED_IO_COLLECTION_ERROR } = require('../../constants/tags')
6
+ const BaseWriter = require('../base')
7
+ const logger = require('../../../log')
8
+
9
+ class LLMObsSpanWriter extends BaseWriter {
10
+ constructor (options) {
11
+ super({
12
+ ...options,
13
+ eventType: 'span'
14
+ })
15
+ }
16
+
17
+ append (event) {
18
+ const eventSizeBytes = Buffer.from(JSON.stringify(event)).byteLength
19
+ if (eventSizeBytes > EVP_EVENT_SIZE_LIMIT) {
20
+ logger.warn(`Dropping event input/output because its size (${eventSizeBytes}) exceeds the 1MB event size limit`)
21
+ event = this._truncateSpanEvent(event)
22
+ }
23
+
24
+ if (this._bufferSize + eventSizeBytes > EVP_PAYLOAD_SIZE_LIMIT) {
25
+ logger.debug('Flusing queue because queing next event will exceed EvP payload limit')
26
+ this.flush()
27
+ }
28
+
29
+ super.append(event, eventSizeBytes)
30
+ }
31
+
32
+ makePayload (events) {
33
+ return {
34
+ '_dd.stage': 'raw',
35
+ event_type: this._eventType,
36
+ spans: events
37
+ }
38
+ }
39
+
40
+ _truncateSpanEvent (event) {
41
+ event.meta.input = { value: DROPPED_VALUE_TEXT }
42
+ event.meta.output = { value: DROPPED_VALUE_TEXT }
43
+
44
+ event.collection_errors = [DROPPED_IO_COLLECTION_ERROR]
45
+ return event
46
+ }
47
+ }
48
+
49
+ module.exports = LLMObsSpanWriter
@@ -3,16 +3,19 @@
3
3
  const NoopTracer = require('./tracer')
4
4
  const NoopAppsecSdk = require('../appsec/sdk/noop')
5
5
  const NoopDogStatsDClient = require('./dogstatsd')
6
+ const NoopLLMObsSDK = require('../llmobs/noop')
6
7
 
7
8
  const noop = new NoopTracer()
8
9
  const noopAppsec = new NoopAppsecSdk()
9
10
  const noopDogStatsDClient = new NoopDogStatsDClient()
11
+ const noopLLMObs = new NoopLLMObsSDK(noop)
10
12
 
11
13
  class Tracer {
12
14
  constructor () {
13
15
  this._tracer = noop
14
16
  this.appsec = noopAppsec
15
17
  this.dogstatsd = noopDogStatsDClient
18
+ this.llmobs = noopLLMObs
16
19
  }
17
20
 
18
21
  init () {
@@ -16,6 +16,9 @@ class NoopSpan {
16
16
  setOperationName (name) { return this }
17
17
  setBaggageItem (key, value) { return this }
18
18
  getBaggageItem (key) {}
19
+ getAllBaggageItems () {}
20
+ removeBaggageItem (key) { return this }
21
+ removeAllBaggageItems () { return this }
19
22
  setTag (key, value) { return this }
20
23
  addTags (keyValueMap) { return this }
21
24
  addLink (link) { return this }
@@ -142,7 +142,7 @@ class Span {
142
142
  context: spanContext._ddContext,
143
143
  startTime,
144
144
  hostname: _tracer._hostname,
145
- integrationName: 'otel',
145
+ integrationName: parentTracer?._isOtelLibrary ? 'otel.library' : 'otel',
146
146
  tags: {
147
147
  [SERVICE_NAME]: _tracer._service,
148
148
  [RESOURCE_NAME]: spanName
@@ -16,6 +16,7 @@ class Tracer {
16
16
  this._tracerProvider = tracerProvider
17
17
  // Is there a reason this is public?
18
18
  this.instrumentationLibrary = library
19
+ this._isOtelLibrary = library?.name?.startsWith('@opentelemetry/instrumentation-')
19
20
  this._spanLimits = {}
20
21
  }
21
22
 
@@ -53,6 +53,8 @@ class TextMapPropagator {
53
53
  }
54
54
 
55
55
  inject (spanContext, carrier) {
56
+ if (!spanContext || !carrier) return
57
+
56
58
  this._injectBaggageItems(spanContext, carrier)
57
59
  this._injectDatadog(spanContext, carrier)
58
60
  this._injectB3MultipleHeaders(spanContext, carrier)
@@ -107,10 +109,35 @@ class TextMapPropagator {
107
109
  }
108
110
  }
109
111
 
112
+ _encodeOtelBaggageKey (key) {
113
+ let encoded = encodeURIComponent(key)
114
+ encoded = encoded.replaceAll('(', '%28')
115
+ encoded = encoded.replaceAll(')', '%29')
116
+ return encoded
117
+ }
118
+
110
119
  _injectBaggageItems (spanContext, carrier) {
111
- spanContext._baggageItems && Object.keys(spanContext._baggageItems).forEach(key => {
112
- carrier[baggagePrefix + key] = String(spanContext._baggageItems[key])
113
- })
120
+ if (this._config.legacyBaggageEnabled) {
121
+ spanContext._baggageItems && Object.keys(spanContext._baggageItems).forEach(key => {
122
+ carrier[baggagePrefix + key] = String(spanContext._baggageItems[key])
123
+ })
124
+ }
125
+ if (this._hasPropagationStyle('inject', 'baggage')) {
126
+ let baggage = ''
127
+ let itemCounter = 0
128
+ let byteCounter = 0
129
+
130
+ for (const [key, value] of Object.entries(spanContext._baggageItems)) {
131
+ const item = `${this._encodeOtelBaggageKey(String(key).trim())}=${encodeURIComponent(String(value).trim())},`
132
+ itemCounter += 1
133
+ byteCounter += item.length
134
+ if (itemCounter > this._config.baggageMaxItems || byteCounter > this._config.baggageMaxBytes) break
135
+ baggage += item
136
+ }
137
+
138
+ baggage = baggage.slice(0, baggage.length - 1)
139
+ if (baggage) carrier.baggage = baggage
140
+ }
114
141
  }
115
142
 
116
143
  _injectTags (spanContext, carrier) {
@@ -299,6 +326,11 @@ class TextMapPropagator {
299
326
  default:
300
327
  log.warn(`Unknown propagation style: ${extractor}`)
301
328
  }
329
+
330
+ if (this._config.tracePropagationStyle.extract.includes('baggage') && carrier.baggage) {
331
+ spanContext = spanContext || new DatadogSpanContext()
332
+ this._extractBaggageItems(carrier, spanContext)
333
+ }
302
334
  }
303
335
 
304
336
  return spanContext || this._extractSqsdContext(carrier)
@@ -310,7 +342,7 @@ class TextMapPropagator {
310
342
  if (!spanContext) return spanContext
311
343
 
312
344
  this._extractOrigin(carrier, spanContext)
313
- this._extractBaggageItems(carrier, spanContext)
345
+ this._extractLegacyBaggageItems(carrier, spanContext)
314
346
  this._extractSamplingPriority(carrier, spanContext)
315
347
  this._extractTags(carrier, spanContext)
316
348
 
@@ -383,7 +415,7 @@ class TextMapPropagator {
383
415
  return null
384
416
  }
385
417
  const matches = headerValue.trim().match(traceparentExpr)
386
- if (matches.length) {
418
+ if (matches?.length) {
387
419
  const [version, traceId, spanId, flags, tail] = matches.slice(1)
388
420
  const traceparent = { version }
389
421
  const tracestate = TraceState.fromString(carrier.tracestate)
@@ -444,7 +476,7 @@ class TextMapPropagator {
444
476
  }
445
477
  })
446
478
 
447
- this._extractBaggageItems(carrier, spanContext)
479
+ this._extractLegacyBaggageItems(carrier, spanContext)
448
480
  return spanContext
449
481
  }
450
482
  return null
@@ -528,14 +560,43 @@ class TextMapPropagator {
528
560
  }
529
561
  }
530
562
 
531
- _extractBaggageItems (carrier, spanContext) {
532
- Object.keys(carrier).forEach(key => {
533
- const match = key.match(baggageExpr)
563
+ _decodeOtelBaggageKey (key) {
564
+ let decoded = decodeURIComponent(key)
565
+ decoded = decoded.replaceAll('%28', '(')
566
+ decoded = decoded.replaceAll('%29', ')')
567
+ return decoded
568
+ }
534
569
 
535
- if (match) {
536
- spanContext._baggageItems[match[1]] = carrier[key]
570
+ _extractLegacyBaggageItems (carrier, spanContext) {
571
+ if (this._config.legacyBaggageEnabled) {
572
+ Object.keys(carrier).forEach(key => {
573
+ const match = key.match(baggageExpr)
574
+
575
+ if (match) {
576
+ spanContext._baggageItems[match[1]] = carrier[key]
577
+ }
578
+ })
579
+ }
580
+ }
581
+
582
+ _extractBaggageItems (carrier, spanContext) {
583
+ const baggages = carrier.baggage.split(',')
584
+ for (const keyValue of baggages) {
585
+ if (!keyValue.includes('=')) {
586
+ spanContext._baggageItems = {}
587
+ return
537
588
  }
538
- })
589
+ let [key, value] = keyValue.split('=')
590
+ key = this._decodeOtelBaggageKey(key.trim())
591
+ value = decodeURIComponent(value.trim())
592
+ if (!key || !value) {
593
+ spanContext._baggageItems = {}
594
+ return
595
+ }
596
+ // the current code assumes precedence of ot-baggage- (legacy opentracing baggage) over baggage
597
+ if (key in spanContext._baggageItems) return
598
+ spanContext._baggageItems[key] = value
599
+ }
539
600
  }
540
601
 
541
602
  _extractSamplingPriority (carrier, spanContext) {
@@ -145,6 +145,18 @@ class DatadogSpan {
145
145
  return this._spanContext._baggageItems[key]
146
146
  }
147
147
 
148
+ getAllBaggageItems () {
149
+ return JSON.stringify(this._spanContext._baggageItems)
150
+ }
151
+
152
+ removeBaggageItem (key) {
153
+ delete this._spanContext._baggageItems[key]
154
+ }
155
+
156
+ removeAllBaggageItems () {
157
+ this._spanContext._baggageItems = {}
158
+ }
159
+
148
160
  setTag (key, value) {
149
161
  this._addTags({ [key]: value })
150
162
  return this
@@ -52,8 +52,15 @@ class DatadogTracer {
52
52
  ? getContext(options.childOf)
53
53
  : getParent(options.references)
54
54
 
55
+ // as per spec, allow the setting of service name through options
55
56
  const tags = {
56
- 'service.name': this._service
57
+ 'service.name': options?.tags?.service ? String(options.tags.service) : this._service
58
+ }
59
+
60
+ // As per unified service tagging spec if a span is created with a service name different from the global
61
+ // service name it will not inherit the global version value
62
+ if (options?.tags?.service && options.tags.service !== this._service) {
63
+ options.tags.version = undefined
57
64
  }
58
65
 
59
66
  const span = new Span(this, this._processor, this._prioritySampler, {
@@ -17,14 +17,82 @@
17
17
  "$.Attributes.Token",
18
18
  "$.Endpoints.*.Token",
19
19
  "$.PhoneNumber",
20
- "$.PhoneNumbers",
21
- "$.phoneNumbers",
22
20
  "$.PlatformApplication.*.PlatformCredential",
23
21
  "$.PlatformApplication.*.PlatformPrincipal",
24
- "$.Subscriptions.*.Endpoint"
22
+ "$.Subscriptions.*.Endpoint",
23
+ "$.PhoneNumbers[*].PhoneNumber",
24
+ "$.phoneNumbers[*]"
25
25
  ],
26
26
  "expand": [
27
27
  "$.MessageAttributes.*.StringValue"
28
28
  ]
29
+ },
30
+ "eventbridge": {
31
+ "request": [
32
+ "$.AuthParameters.OAuthParameters.OAuthHttpParameters.HeaderParameters[*].Value",
33
+ "$.AuthParameters.OAuthParameters.OAuthHttpParameters.QueryStringParameters[*].Value",
34
+ "$.AuthParameters.OAuthParameters.OAuthHttpParameters.BodyParameters[*].Value",
35
+ "$.AuthParameters.InvocationHttpParameters.HeaderParameters[*].Value",
36
+ "$.AuthParameters.InvocationHttpParameters.QueryStringParameters[*].Value",
37
+ "$.AuthParameters.InvocationHttpParameters.BodyParameters[*].Value",
38
+ "$.Targets[*].RedshiftDataParameters.Sql",
39
+ "$.Targets[*].RedshiftDataParameters.Sqls",
40
+ "$.Targets[*].AppSyncParameters.GraphQLOperation",
41
+ "$.AuthParameters.BasicAuthParameters.Password",
42
+ "$.AuthParameters.OAuthParameters.ClientParameters.ClientSecret",
43
+ "$.AuthParameters.ApiKeyAuthParameters.ApiKeyValue"
44
+ ],
45
+ "response": [
46
+ "$.AuthParameters.OAuthParameters.OAuthHttpParameters.HeaderParameters[*].Value",
47
+ "$.AuthParameters.OAuthParameters.OAuthHttpParameters.QueryStringParameters[*].Value",
48
+ "$.AuthParameters.OAuthParameters.OAuthHttpParameters.BodyParameters[*].Value",
49
+ "$.AuthParameters.InvocationHttpParameters.HeaderParameters[*].Value",
50
+ "$.AuthParameters.InvocationHttpParameters.QueryStringParameters[*].Value",
51
+ "$.AuthParameters.InvocationHttpParameters.BodyParameters[*].Value",
52
+ "$.Targets[*].RedshiftDataParameters.Sql",
53
+ "$.Targets[*].RedshiftDataParameters.Sqls",
54
+ "$.Targets[*].AppSyncParameters.GraphQLOperation"
55
+ ],
56
+ "expand": [
57
+ ]
58
+ },
59
+ "s3": {
60
+ "request": [
61
+ "$.SSEKMSKeyId",
62
+ "$.SSEKMSEncryptionContext",
63
+ "$.ServerSideEncryptionConfiguration.Rules[*].ApplyServerSideEncryptionByDefault.KMSMasterKeyID",
64
+ "$.InventoryConfiguration.Destination.S3BucketDestination.Encryption.SSEKMS.KeyId",
65
+ "$.SSECustomerKey",
66
+ "$.CopySourceSSECustomerKey",
67
+ "$.RestoreRequest.OutputLocation.S3.Encryption.KMSKeyId"
68
+
69
+ ],
70
+ "response": [
71
+ "$.SSEKMSKeyId",
72
+ "$.SSEKMSEncryptionContext",
73
+ "$.ServerSideEncryptionConfiguration.Rules[*].ApplyServerSideEncryptionByDefault.KMSMasterKeyID",
74
+ "$.InventoryConfiguration.Destination.S3BucketDestination.Encryption.SSEKMS.KeyId",
75
+ "$.Credentials.SecretAccessKey",
76
+ "$.Credentials.SessionToken",
77
+ "$.InventoryConfigurationList[*].Destination.S3BucketDestination.Encryption.SSEKMS.KeyId"
78
+ ],
79
+ "expand": [
80
+ ]
81
+ },
82
+ "sqs": {
83
+ "request": [
84
+ ],
85
+ "response": [
86
+ ],
87
+ "expand": [
88
+ ]
89
+ },
90
+ "kinesis": {
91
+ "request": [
92
+ ],
93
+ "response": [
94
+ ],
95
+ "expand": [
96
+ ]
29
97
  }
30
98
  }
@@ -7,6 +7,7 @@ const {
7
7
  PEER_SERVICE_REMAP_KEY
8
8
  } = require('../constants')
9
9
  const TracingPlugin = require('./tracing')
10
+ const { exitTags } = require('../../../datadog-code-origin')
10
11
 
11
12
  const COMMON_PEER_SVC_SOURCE_TAGS = [
12
13
  'net.peer.name',
@@ -25,6 +26,14 @@ class OutboundPlugin extends TracingPlugin {
25
26
  })
26
27
  }
27
28
 
29
+ startSpan (...args) {
30
+ const span = super.startSpan(...args)
31
+ if (this._tracerConfig.codeOriginForSpans.enabled) {
32
+ span.addTags(exitTags(this.startSpan))
33
+ }
34
+ return span
35
+ }
36
+
28
37
  getPeerService (tags) {
29
38
  /**
30
39
  * Compute `peer.service` and associated metadata from available tags, based
@@ -108,6 +108,18 @@ class PrioritySampler {
108
108
  }
109
109
  }
110
110
 
111
+ setPriority (span, samplingPriority, mechanism = SAMPLING_MECHANISM_MANUAL) {
112
+ if (!span || !this.validate(samplingPriority)) return
113
+
114
+ const context = this._getContext(span)
115
+
116
+ context._sampling.priority = samplingPriority
117
+ context._sampling.mechanism = mechanism
118
+
119
+ const root = context._trace.started[0]
120
+ this._addDecisionMaker(root)
121
+ }
122
+
111
123
  _getContext (span) {
112
124
  return typeof span.context === 'function' ? span.context() : span
113
125
  }
@@ -201,6 +213,10 @@ class PrioritySampler {
201
213
  if (rule.match(span)) return rule
202
214
  }
203
215
  }
216
+
217
+ static keepTrace (span, mechanism) {
218
+ span?._prioritySampler?.setPriority(span, USER_KEEP, mechanism)
219
+ }
204
220
  }
205
221
 
206
222
  module.exports = PrioritySampler
@@ -14,6 +14,7 @@ const { oomExportStrategies, snapshotKinds } = require('./constants')
14
14
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
15
15
  const { tagger } = require('./tagger')
16
16
  const { isFalse, isTrue } = require('../util')
17
+ const { getAzureTagsFromMetadata, getAzureAppMetadata } = require('../azure_metadata')
17
18
 
18
19
  class Config {
19
20
  constructor (options = {}) {
@@ -71,7 +72,8 @@ class Config {
71
72
  this.tags = Object.assign(
72
73
  tagger.parse(DD_TAGS),
73
74
  tagger.parse(options.tags),
74
- tagger.parse({ env, host, service, version, functionname })
75
+ tagger.parse({ env, host, service, version, functionname }),
76
+ getAzureTagsFromMetadata(getAzureAppMetadata())
75
77
  )
76
78
 
77
79
  // Add source code integration tags if available
@@ -195,11 +195,13 @@ class AgentExporter {
195
195
  })
196
196
 
197
197
  sendRequest(options, form, (err, response) => {
198
- if (operation.retry(err)) {
199
- this._logger.error(`Error from the agent: ${err.message}`)
200
- return
201
- } else if (err) {
202
- reject(err)
198
+ if (err) {
199
+ const { status } = err
200
+ if ((typeof status !== 'number' || status >= 500 || status === 429) && operation.retry(err)) {
201
+ this._logger.error(`Error from the agent: ${err.message}`)
202
+ } else {
203
+ reject(err)
204
+ }
203
205
  return
204
206
  }
205
207
 
@@ -301,7 +301,8 @@ class NativeWallProfiler {
301
301
 
302
302
  const labels = { ...getThreadLabels() }
303
303
 
304
- const { context: { ref: { spanId, rootSpanId, webTags, endpoint } }, timestamp } = context
304
+ const { context: { ref }, timestamp } = context
305
+ const { spanId, rootSpanId, webTags, endpoint } = ref ?? {}
305
306
 
306
307
  if (this._timelineEnabled) {
307
308
  // Incoming timestamps are in microseconds, we emit nanos.