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.
- package/LICENSE-3rdparty.csv +1 -0
- package/index.d.ts +335 -0
- package/package.json +13 -7
- package/packages/datadog-code-origin/index.js +4 -4
- package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-instrumentations/src/amqplib.js +65 -5
- package/packages/datadog-instrumentations/src/child_process.js +135 -27
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -0
- package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
- package/packages/datadog-instrumentations/src/multer.js +37 -0
- package/packages/datadog-instrumentations/src/openai.js +2 -2
- package/packages/datadog-instrumentations/src/url.js +84 -0
- package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
- package/packages/datadog-plugin-amqplib/src/consumer.js +4 -4
- 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/s3.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-fastify/src/code_origin.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +8 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
- package/packages/datadog-plugin-grpc/src/client.js +3 -0
- package/packages/datadog-plugin-grpc/src/server.js +3 -0
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +8 -4
- package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
- package/packages/datadog-plugin-mocha/src/index.js +4 -1
- package/packages/datadog-plugin-openai/src/index.js +9 -1015
- package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
- package/packages/dd-trace/src/appsec/addresses.js +2 -0
- package/packages/dd-trace/src/appsec/channels.js +3 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +55 -7
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -2
- package/packages/dd-trace/src/appsec/index.js +3 -0
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
- package/packages/dd-trace/src/appsec/rasp/index.js +3 -0
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
- package/packages/dd-trace/src/appsec/rasp/utils.js +3 -2
- package/packages/dd-trace/src/appsec/recommended.json +2 -4
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +2 -0
- package/packages/dd-trace/src/appsec/reporter.js +5 -4
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
- package/packages/dd-trace/src/azure_metadata.js +120 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
- package/packages/dd-trace/src/config.js +75 -6
- package/packages/dd-trace/src/constants.js +3 -1
- package/packages/dd-trace/src/datastreams/pathway.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +9 -13
- package/packages/dd-trace/src/debugger/devtools_client/send.js +15 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +57 -23
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +12 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +31 -20
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +11 -2
- package/packages/dd-trace/src/debugger/index.js +10 -3
- package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
- package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
- package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
- package/packages/dd-trace/src/llmobs/index.js +103 -0
- package/packages/dd-trace/src/llmobs/noop.js +82 -0
- package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
- package/packages/dd-trace/src/llmobs/sdk.js +377 -0
- package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
- package/packages/dd-trace/src/llmobs/storage.js +7 -0
- package/packages/dd-trace/src/llmobs/tagger.js +322 -0
- package/packages/dd-trace/src/llmobs/util.js +176 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
- package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +49 -0
- package/packages/dd-trace/src/noop/proxy.js +3 -0
- package/packages/dd-trace/src/noop/span.js +3 -0
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +73 -12
- package/packages/dd-trace/src/opentracing/span.js +12 -0
- package/packages/dd-trace/src/opentracing/tracer.js +8 -1
- package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
- package/packages/dd-trace/src/plugins/outbound.js +9 -0
- package/packages/dd-trace/src/priority_sampler.js +16 -0
- package/packages/dd-trace/src/profiling/config.js +3 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -1
- package/packages/dd-trace/src/proxy.js +8 -1
- package/packages/dd-trace/src/span_processor.js +5 -0
- 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
|
|
@@ -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
|
-
|
|
112
|
-
|
|
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.
|
|
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
|
|
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.
|
|
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
|
-
|
|
532
|
-
|
|
533
|
-
|
|
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
|
-
|
|
536
|
-
|
|
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 (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
|
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.
|