dd-trace 5.62.0 → 5.63.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/README.md +0 -5
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/ai.js +140 -0
- package/packages/datadog-instrumentations/src/couchbase.js +102 -65
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +2 -22
- package/packages/datadog-instrumentations/src/hono.js +11 -8
- package/packages/datadog-instrumentations/src/knex.js +15 -17
- package/packages/datadog-instrumentations/src/mongodb-core.js +4 -6
- package/packages/datadog-instrumentations/src/next.js +4 -8
- package/packages/datadog-instrumentations/src/pg.js +38 -48
- package/packages/datadog-plugin-aerospike/src/index.js +6 -2
- package/packages/datadog-plugin-ai/src/index.js +17 -0
- package/packages/datadog-plugin-ai/src/tracing.js +33 -0
- package/packages/datadog-plugin-ai/src/utils.js +28 -0
- package/packages/datadog-plugin-couchbase/src/index.js +37 -17
- package/packages/datadog-plugin-pg/src/index.js +5 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +14 -7
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
- package/packages/dd-trace/src/appsec/recommended.json +271 -2
- package/packages/dd-trace/src/guardrails/telemetry.js +18 -2
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +351 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +179 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -2
- package/packages/dd-trace/src/opentracing/span_context.js +4 -0
- package/packages/dd-trace/src/plugin_manager.js +8 -4
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +44 -3
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +24 -23
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -2
- package/packages/dd-trace/src/supported-configurations.json +2 -0
- package/packages/dd-trace/src/tracer_metadata.js +1 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const MODEL_METADATA_KEYS = new Set([
|
|
4
|
+
'frequency_penalty',
|
|
5
|
+
'max_tokens',
|
|
6
|
+
'presence_penalty',
|
|
7
|
+
'temperature',
|
|
8
|
+
'top_p',
|
|
9
|
+
'top_k',
|
|
10
|
+
'stop_sequences'
|
|
11
|
+
])
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the span tags from the context (either the attributes or the span tags).
|
|
15
|
+
*
|
|
16
|
+
* @param {Record<string, any>} ctx
|
|
17
|
+
* @returns {Record<string, any>}
|
|
18
|
+
*/
|
|
19
|
+
function getSpanTags (ctx) {
|
|
20
|
+
const span = ctx.currentStore?.span
|
|
21
|
+
const carrier = ctx.attributes ?? span?.context()._tags ?? {}
|
|
22
|
+
return carrier
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the operation name from the span name
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* span._name = 'ai.generateText'
|
|
30
|
+
* getOperation(span) // 'generateText'
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* span._name = 'ai.generateText.doGenerate'
|
|
34
|
+
* getOperation(span) // 'doGenerate'
|
|
35
|
+
*
|
|
36
|
+
* @param {import('../../../opentracing/span')} span
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function getOperation (span) {
|
|
40
|
+
const name = span._name
|
|
41
|
+
if (!name) return
|
|
42
|
+
|
|
43
|
+
return name.split('.').pop()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get the LLM token usage from the span tags
|
|
48
|
+
* @param {Record<string, string>} tags
|
|
49
|
+
* @returns {{inputTokens: number, outputTokens: number, totalTokens: number}}
|
|
50
|
+
*/
|
|
51
|
+
function getUsage (tags) {
|
|
52
|
+
const usage = {}
|
|
53
|
+
const inputTokens = tags['ai.usage.promptTokens']
|
|
54
|
+
const outputTokens = tags['ai.usage.completionTokens']
|
|
55
|
+
|
|
56
|
+
if (inputTokens != null) usage.inputTokens = inputTokens
|
|
57
|
+
if (outputTokens != null) usage.outputTokens = outputTokens
|
|
58
|
+
|
|
59
|
+
const totalTokens = inputTokens + outputTokens
|
|
60
|
+
if (!Number.isNaN(totalTokens)) usage.totalTokens = totalTokens
|
|
61
|
+
|
|
62
|
+
return usage
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Safely JSON parses a string value with a default fallback
|
|
67
|
+
* @param {string} str
|
|
68
|
+
* @param {any} defaultValue
|
|
69
|
+
* @returns {Record<string, any> | string | Array<any>}
|
|
70
|
+
*/
|
|
71
|
+
function getJsonStringValue (str, defaultValue) {
|
|
72
|
+
let maybeValue = defaultValue
|
|
73
|
+
try {
|
|
74
|
+
maybeValue = JSON.parse(str)
|
|
75
|
+
} catch {
|
|
76
|
+
// do nothing
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return maybeValue
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get the model metadata from the span tags (top_p, top_k, temperature, etc.)
|
|
84
|
+
* @param {import('../../../opentracing/span')} span
|
|
85
|
+
* @returns {Record<string, string> | null}
|
|
86
|
+
*/
|
|
87
|
+
function getModelMetadata (tags) {
|
|
88
|
+
const modelMetadata = {}
|
|
89
|
+
for (const metadata of MODEL_METADATA_KEYS) {
|
|
90
|
+
const metadataTagKey = `gen_ai.request.${metadata}`
|
|
91
|
+
const metadataValue = tags[metadataTagKey]
|
|
92
|
+
if (metadataValue) {
|
|
93
|
+
modelMetadata[metadata] = metadataValue
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return Object.keys(modelMetadata).length ? modelMetadata : null
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the generation metadata from the span tags (maxSteps, maxRetries, etc.)
|
|
102
|
+
* @param {Record<string, string>} tags
|
|
103
|
+
* @returns {Record<string, string> | null}
|
|
104
|
+
*/
|
|
105
|
+
function getGenerationMetadata (tags) {
|
|
106
|
+
const metadata = {}
|
|
107
|
+
|
|
108
|
+
for (const tag of Object.keys(tags)) {
|
|
109
|
+
if (!tag.startsWith('ai.settings')) continue
|
|
110
|
+
|
|
111
|
+
const settingKey = tag.split('.').pop()
|
|
112
|
+
const transformedKey = settingKey.replaceAll(/[A-Z]/g, letter => '_' + letter.toLowerCase())
|
|
113
|
+
if (MODEL_METADATA_KEYS.has(transformedKey)) continue
|
|
114
|
+
|
|
115
|
+
const settingValue = tags[tag]
|
|
116
|
+
metadata[settingKey] = settingValue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return Object.keys(metadata).length ? metadata : null
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get the tool name from the span tags.
|
|
124
|
+
* If the tool name is a parsable number, or is not found, null is returned.
|
|
125
|
+
* Older versions of the ai sdk would tag the tool name as its index in the tools array.
|
|
126
|
+
*
|
|
127
|
+
* @param {Record<string, string>} tags
|
|
128
|
+
* @returns {string | null}
|
|
129
|
+
*/
|
|
130
|
+
function getToolNameFromTags (tags) {
|
|
131
|
+
const toolName = tags['ai.toolCall.name']
|
|
132
|
+
if (!toolName) return null
|
|
133
|
+
|
|
134
|
+
const parsedToolName = Number.parseInt(toolName)
|
|
135
|
+
if (!Number.isNaN(parsedToolName)) return null
|
|
136
|
+
|
|
137
|
+
return toolName
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get the content of a tool call result.
|
|
142
|
+
* Version 5 of the ai sdk sets this tag as `content.output`, with a `
|
|
143
|
+
* @param {Record<string, any>} content
|
|
144
|
+
* @returns {string}
|
|
145
|
+
*/
|
|
146
|
+
function getToolCallResultContent (content) {
|
|
147
|
+
const { output, result } = content
|
|
148
|
+
if (output) {
|
|
149
|
+
if (output.type === 'text') {
|
|
150
|
+
return output.value
|
|
151
|
+
} else if (output.type === 'json') {
|
|
152
|
+
return JSON.stringify(output.value)
|
|
153
|
+
}
|
|
154
|
+
return '[Unparsable Tool Result]'
|
|
155
|
+
} else if (result) {
|
|
156
|
+
if (typeof result === 'string') {
|
|
157
|
+
return result
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
return JSON.stringify(result)
|
|
162
|
+
} catch {
|
|
163
|
+
return '[Unparsable Tool Result]'
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
return '[Unsupported Tool Result]'
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
module.exports = {
|
|
171
|
+
getSpanTags,
|
|
172
|
+
getOperation,
|
|
173
|
+
getUsage,
|
|
174
|
+
getJsonStringValue,
|
|
175
|
+
getModelMetadata,
|
|
176
|
+
getGenerationMetadata,
|
|
177
|
+
getToolNameFromTags,
|
|
178
|
+
getToolCallResultContent
|
|
179
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const request = require('../../exporters/common/request')
|
|
4
|
+
const { getEnvironmentVariable } = require('../../config-helper')
|
|
4
5
|
const { URL, format } = require('node:url')
|
|
5
6
|
const path = require('node:path')
|
|
6
7
|
|
|
@@ -17,8 +18,8 @@ const { parseResponseAndLog } = require('./util')
|
|
|
17
18
|
|
|
18
19
|
class BaseLLMObsWriter {
|
|
19
20
|
constructor ({ interval, timeout, eventType, config, endpoint, intake }) {
|
|
20
|
-
this._interval = interval
|
|
21
|
-
this._timeout = timeout
|
|
21
|
+
this._interval = interval ?? getEnvironmentVariable('_DD_LLMOBS_FLUSH_INTERVAL') ?? 1000 // 1s
|
|
22
|
+
this._timeout = timeout ?? getEnvironmentVariable('_DD_LLMOBS_TIMEOUT') ?? 5000 // 5s
|
|
22
23
|
this._eventType = eventType
|
|
23
24
|
|
|
24
25
|
this._buffer = []
|
|
@@ -59,6 +59,10 @@ class DatadogSpanContext {
|
|
|
59
59
|
return this._spanId.toString(10)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
toBigIntSpanId () {
|
|
63
|
+
return this._spanId.toBigInt()
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
toTraceparent () {
|
|
63
67
|
const flags = this._sampling.priority >= AUTO_KEEP ? '01' : '00'
|
|
64
68
|
const traceId = this.toTraceId(true)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { channel } = require('dc-polyfill')
|
|
4
|
-
const { isFalse, normalizePluginEnvName } = require('./util')
|
|
4
|
+
const { isFalse, isTrue, normalizePluginEnvName } = require('./util')
|
|
5
5
|
const plugins = require('./plugins')
|
|
6
6
|
const log = require('./log')
|
|
7
7
|
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
|
|
@@ -32,8 +32,7 @@ loadChannel.subscribe(({ name }) => {
|
|
|
32
32
|
function maybeEnable (Plugin) {
|
|
33
33
|
if (!Plugin || typeof Plugin !== 'function') return
|
|
34
34
|
if (!pluginClasses[Plugin.id]) {
|
|
35
|
-
const
|
|
36
|
-
const enabled = getEnvironmentVariable(normalizePluginEnvName(envName))
|
|
35
|
+
const enabled = getEnvEnabled(Plugin)
|
|
37
36
|
|
|
38
37
|
// TODO: remove the need to load the plugin class in order to disable the plugin
|
|
39
38
|
if (isFalse(enabled) || disabledPlugins.has(Plugin.id)) {
|
|
@@ -46,6 +45,11 @@ function maybeEnable (Plugin) {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
|
|
48
|
+
function getEnvEnabled (Plugin) {
|
|
49
|
+
const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
|
|
50
|
+
return getEnvironmentVariable(normalizePluginEnvName(envName))
|
|
51
|
+
}
|
|
52
|
+
|
|
49
53
|
// TODO this must always be a singleton.
|
|
50
54
|
module.exports = class PluginManager {
|
|
51
55
|
constructor (tracer) {
|
|
@@ -74,7 +78,7 @@ module.exports = class PluginManager {
|
|
|
74
78
|
this._pluginsByName[name] = new Plugin(this._tracer, this._tracerConfig)
|
|
75
79
|
}
|
|
76
80
|
const pluginConfig = this._configsByName[name] || {
|
|
77
|
-
enabled: this._tracerConfig.plugins !== false
|
|
81
|
+
enabled: this._tracerConfig.plugins !== false && (!Plugin.experimental || isTrue(getEnvEnabled(Plugin)))
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
// extracts predetermined configuration from tracer and combines it with plugin-specific config
|
|
@@ -26,6 +26,7 @@ module.exports = {
|
|
|
26
26
|
get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
27
27
|
get '@vitest/runner' () { return require('../../../datadog-plugin-vitest/src') },
|
|
28
28
|
get aerospike () { return require('../../../datadog-plugin-aerospike/src') },
|
|
29
|
+
get ai () { return require('../../../datadog-plugin-ai/src') },
|
|
29
30
|
get amqp10 () { return require('../../../datadog-plugin-amqp10/src') },
|
|
30
31
|
get amqplib () { return require('../../../datadog-plugin-amqplib/src') },
|
|
31
32
|
get avsc () { return require('../../../datadog-plugin-avsc/src') },
|
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
const { BlockList } = require('net')
|
|
4
4
|
const net = require('net')
|
|
5
5
|
|
|
6
|
+
const FORWARED_HEADER_NAME = 'forwarded'
|
|
7
|
+
|
|
6
8
|
const ipHeaderList = [
|
|
7
9
|
'x-forwarded-for',
|
|
8
10
|
'x-real-ip',
|
|
9
11
|
'true-client-ip',
|
|
10
12
|
'x-client-ip',
|
|
13
|
+
FORWARED_HEADER_NAME,
|
|
11
14
|
'forwarded-for',
|
|
12
15
|
'x-cluster-client-ip',
|
|
13
16
|
'fastly-client-ip',
|
|
@@ -49,7 +52,8 @@ function extractIp (config, req) {
|
|
|
49
52
|
let firstPrivateIp
|
|
50
53
|
if (headers) {
|
|
51
54
|
for (const ipHeaderName of ipHeaderList) {
|
|
52
|
-
const
|
|
55
|
+
const header = headers[ipHeaderName]
|
|
56
|
+
const firstIp = ipHeaderName === FORWARED_HEADER_NAME ? findFirstIpForwardedFormat(header) : findFirstIp(header)
|
|
53
57
|
|
|
54
58
|
if (firstIp.public) {
|
|
55
59
|
return firstIp.public
|
|
@@ -62,6 +66,10 @@ function extractIp (config, req) {
|
|
|
62
66
|
return firstPrivateIp || req.socket?.remoteAddress
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
function isPublicIp (ip, type) {
|
|
70
|
+
return !privateIPMatcher.check(ip, type === 6 ? 'ipv6' : 'ipv4')
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
function findFirstIp (str) {
|
|
66
74
|
const result = {}
|
|
67
75
|
if (!str) return result
|
|
@@ -76,10 +84,10 @@ function findFirstIp (str) {
|
|
|
76
84
|
const type = net.isIP(chunk)
|
|
77
85
|
if (!type) continue
|
|
78
86
|
|
|
79
|
-
if (
|
|
87
|
+
if (isPublicIp(chunk, type)) {
|
|
80
88
|
// it's public, return it immediately
|
|
81
89
|
result.public = chunk
|
|
82
|
-
|
|
90
|
+
return result
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
// it's private, only save the first one found
|
|
@@ -89,6 +97,39 @@ function findFirstIp (str) {
|
|
|
89
97
|
return result
|
|
90
98
|
}
|
|
91
99
|
|
|
100
|
+
const forwardedForRegexp = /for="?\[?(([0-9]+\.)+[0-9]+|[0-9a-f:]*:[0-9a-f]*)/i
|
|
101
|
+
const forwardedByRegexp = /by="?\[?(([0-9]+\.)+[0-9]+|[0-9a-f:]*:[0-9a-f]*)/i
|
|
102
|
+
const forwardedRegexps = [forwardedForRegexp, forwardedByRegexp]
|
|
103
|
+
|
|
104
|
+
function findFirstIpForwardedFormat (str) {
|
|
105
|
+
const result = {}
|
|
106
|
+
if (!str) return result
|
|
107
|
+
|
|
108
|
+
const splitted = str.split(',')
|
|
109
|
+
|
|
110
|
+
for (const part of splitted) {
|
|
111
|
+
const chunk = part.trim()
|
|
112
|
+
|
|
113
|
+
for (const regex of forwardedRegexps) {
|
|
114
|
+
const ip = regex.exec(chunk)?.[1]
|
|
115
|
+
|
|
116
|
+
const type = net.isIP(ip)
|
|
117
|
+
if (!type) continue
|
|
118
|
+
|
|
119
|
+
if (isPublicIp(ip, type)) {
|
|
120
|
+
// it's public, return it immediately
|
|
121
|
+
result.public = ip
|
|
122
|
+
return result
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// it's private, only save the first one found
|
|
126
|
+
if (!result.private) result.private = ip
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return result
|
|
131
|
+
}
|
|
132
|
+
|
|
92
133
|
module.exports = {
|
|
93
134
|
extractIp,
|
|
94
135
|
ipHeaderList
|
|
@@ -7,54 +7,55 @@ const { performance } = require('perf_hooks')
|
|
|
7
7
|
// start/error/finish methods to the appropriate diagnostic channels.
|
|
8
8
|
// TODO: Decouple this from TracingPlugin.
|
|
9
9
|
class EventPlugin extends TracingPlugin {
|
|
10
|
+
#eventHandler
|
|
11
|
+
#eventFilter
|
|
12
|
+
#dataSymbol
|
|
13
|
+
#entryType
|
|
14
|
+
|
|
10
15
|
constructor (eventHandler, eventFilter) {
|
|
11
16
|
super()
|
|
12
|
-
this
|
|
13
|
-
this
|
|
14
|
-
this
|
|
15
|
-
this
|
|
17
|
+
this.#eventHandler = eventHandler
|
|
18
|
+
this.#eventFilter = eventFilter
|
|
19
|
+
this.#entryType = this.constructor.entryType
|
|
20
|
+
this.#dataSymbol = Symbol(`dd-trace.profiling.event.${this.#entryType}.${this.constructor.operation}`)
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
start (ctx) {
|
|
19
|
-
this.
|
|
20
|
-
startEvent: ctx,
|
|
21
|
-
startTime: performance.now()
|
|
22
|
-
})
|
|
24
|
+
ctx[this.#dataSymbol] = performance.now()
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
error (ctx) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
data.error = true
|
|
29
|
-
}
|
|
28
|
+
// We don't emit perf events for failed operations
|
|
29
|
+
ctx[this.#dataSymbol] = undefined
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
finish (ctx) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const startTime = ctx[this.#dataSymbol]
|
|
34
|
+
if (startTime === undefined) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
ctx[this.#dataSymbol] = undefined
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return // don't emit perf events for failed operations or ignored events
|
|
39
|
+
if (this.ignoreEvent(ctx)) {
|
|
40
|
+
return // don't emit perf events for ignored events
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const duration = performance.now() - startTime
|
|
43
44
|
const event = {
|
|
44
|
-
entryType: this
|
|
45
|
+
entryType: this.#entryType,
|
|
45
46
|
startTime,
|
|
46
47
|
duration
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
if (!this
|
|
50
|
+
if (!this.#eventFilter(event)) {
|
|
50
51
|
return
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
const context = (ctx.currentStore?.span || this.activeSpan)?.context()
|
|
54
|
-
event._ddSpanId = context?.
|
|
55
|
-
event._ddRootSpanId = context?._trace.started[0]?.context().
|
|
55
|
+
event._ddSpanId = context?.toBigIntSpanId()
|
|
56
|
+
event._ddRootSpanId = context?._trace.started[0]?.context().toBigIntSpanId() || event._ddSpanId
|
|
56
57
|
|
|
57
|
-
this
|
|
58
|
+
this.#eventHandler(this.extendEvent(event, ctx))
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
ignoreEvent () {
|
|
@@ -273,10 +273,11 @@ class EventSerializer {
|
|
|
273
273
|
new Label({ key: this.timestampLabelKey, num: dateOffset + BigInt(Math.round(endTime * MS_TO_NS)) })
|
|
274
274
|
]
|
|
275
275
|
if (_ddSpanId) {
|
|
276
|
-
label.push(
|
|
276
|
+
label.push(
|
|
277
|
+
new Label({ key: this.spanIdKey, num: _ddSpanId }))
|
|
277
278
|
}
|
|
278
279
|
if (_ddRootSpanId) {
|
|
279
|
-
label.push(
|
|
280
|
+
label.push(new Label({ key: this.rootSpanIdKey, num: _ddRootSpanId }))
|
|
280
281
|
}
|
|
281
282
|
|
|
282
283
|
const sampleInput = {
|
|
@@ -215,10 +215,10 @@ class NativeWallProfiler {
|
|
|
215
215
|
|
|
216
216
|
_updateContext (context) {
|
|
217
217
|
if (context.spanId !== null && typeof context.spanId === 'object') {
|
|
218
|
-
context.spanId = context.spanId.
|
|
218
|
+
context.spanId = context.spanId.toBigInt()
|
|
219
219
|
}
|
|
220
220
|
if (context.rootSpanId !== null && typeof context.rootSpanId === 'object') {
|
|
221
|
-
context.rootSpanId = context.rootSpanId.
|
|
221
|
+
context.rootSpanId = context.rootSpanId.toBigInt()
|
|
222
222
|
}
|
|
223
223
|
if (context.webTags !== undefined && context.endpoint === undefined) {
|
|
224
224
|
// endpoint may not be determined yet, but keep it as fallback
|
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
"DD_PROFILING_HEAP_ENABLED": ["A"],
|
|
130
130
|
"DD_PROFILING_PROFILERS": ["A"],
|
|
131
131
|
"DD_PROFILING_SOURCE_MAP": ["A"],
|
|
132
|
+
"DD_PROFILING_TIMELINE_ENABLED": ["A"],
|
|
132
133
|
"DD_PROFILING_UPLOAD_PERIOD": ["A"],
|
|
133
134
|
"DD_PROFILING_V8_PROFILER_BUG_WORKAROUND": ["A"],
|
|
134
135
|
"DD_PROFILING_WALLTIME_ENABLED": ["A"],
|
|
@@ -160,6 +161,7 @@
|
|
|
160
161
|
"DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
|
|
161
162
|
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
|
|
162
163
|
"DD_TRACE_AEROSPIKE_ENABLED": ["A"],
|
|
164
|
+
"DD_TRACE_AI_ENABLED": ["A"],
|
|
163
165
|
"DD_TRACE_AGENT_PORT": ["A"],
|
|
164
166
|
"DD_TRACE_AGENT_PROTOCOL_VERSION": ["A"],
|
|
165
167
|
"DD_TRACE_AGENT_URL": ["A"],
|