dd-trace 5.62.0 → 5.63.1
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/moleculer/client.js +2 -3
- 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 +8 -3
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +2 -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 +6 -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 = []
|
|
@@ -119,7 +120,11 @@ class BaseLLMObsWriter {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
const { hostname, port } = this._config
|
|
122
|
-
|
|
123
|
+
|
|
124
|
+
const overrideOriginEnv = getEnvironmentVariable('_DD_LLMOBS_OVERRIDE_ORIGIN')
|
|
125
|
+
const overrideOriginUrl = overrideOriginEnv && new URL(overrideOriginEnv)
|
|
126
|
+
|
|
127
|
+
const base = overrideOriginUrl ?? this._config.url ?? new URL(format({
|
|
123
128
|
protocol: 'http:',
|
|
124
129
|
hostname,
|
|
125
130
|
port
|
|
@@ -148,13 +148,13 @@ class TextMapPropagator {
|
|
|
148
148
|
|
|
149
149
|
// Check for item count limit exceeded
|
|
150
150
|
if (itemCounter > this._config.baggageMaxItems) {
|
|
151
|
-
tracerMetrics.count('
|
|
151
|
+
tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_item_count_exceeded']).inc()
|
|
152
152
|
break
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
// Check for byte count limit exceeded
|
|
156
156
|
if (byteCounter > this._config.baggageMaxBytes) {
|
|
157
|
-
tracerMetrics.count('
|
|
157
|
+
tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_byte_count_exceeded']).inc()
|
|
158
158
|
break
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -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
|
|
@@ -118,6 +118,7 @@
|
|
|
118
118
|
"DD_PLAYWRIGHT_WORKER": ["A"],
|
|
119
119
|
"DD_PROFILING_CODEHOTSPOTS_ENABLED": ["A"],
|
|
120
120
|
"DD_PROFILING_CPU_ENABLED": ["A"],
|
|
121
|
+
"DD_PROFILING_DEBUG_SOURCE_MAPS": ["A"],
|
|
121
122
|
"DD_PROFILING_DEBUG_UPLOAD_COMPRESSION": ["A"],
|
|
122
123
|
"DD_PROFILING_ENABLED": ["A"],
|
|
123
124
|
"DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["A"],
|
|
@@ -127,9 +128,13 @@
|
|
|
127
128
|
"DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED": ["A"],
|
|
128
129
|
"DD_PROFILING_EXPORTERS": ["A"],
|
|
129
130
|
"DD_PROFILING_HEAP_ENABLED": ["A"],
|
|
131
|
+
"DD_PROFILING_HEAP_SAMPLING_INTERVAL": ["A"],
|
|
132
|
+
"DD_PROFILING_PPROF_PREFIX": ["A"],
|
|
130
133
|
"DD_PROFILING_PROFILERS": ["A"],
|
|
131
134
|
"DD_PROFILING_SOURCE_MAP": ["A"],
|
|
135
|
+
"DD_PROFILING_TIMELINE_ENABLED": ["A"],
|
|
132
136
|
"DD_PROFILING_UPLOAD_PERIOD": ["A"],
|
|
137
|
+
"DD_PROFILING_UPLOAD_TIMEOUT": ["A"],
|
|
133
138
|
"DD_PROFILING_V8_PROFILER_BUG_WORKAROUND": ["A"],
|
|
134
139
|
"DD_PROFILING_WALLTIME_ENABLED": ["A"],
|
|
135
140
|
"DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": ["A"],
|
|
@@ -160,6 +165,7 @@
|
|
|
160
165
|
"DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
|
|
161
166
|
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
|
|
162
167
|
"DD_TRACE_AEROSPIKE_ENABLED": ["A"],
|
|
168
|
+
"DD_TRACE_AI_ENABLED": ["A"],
|
|
163
169
|
"DD_TRACE_AGENT_PORT": ["A"],
|
|
164
170
|
"DD_TRACE_AGENT_PROTOCOL_VERSION": ["A"],
|
|
165
171
|
"DD_TRACE_AGENT_URL": ["A"],
|