dd-trace 6.13.0 → 6.14.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 +3 -1
- package/ci/init.js +8 -3
- package/ci/test-optimization-validation/ci-package-scripts.js +2 -2
- package/ci/test-optimization-validation/ci-remediation.js +6 -6
- package/ci/test-optimization-validation/command-blocker.js +7 -5
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +1 -1
- package/ci/test-optimization-validation/framework-adapters/vitest.js +3 -3
- package/ci/test-optimization-validation/package-check.js +1 -1
- package/ci/test-optimization-validation/report-writer.js +7 -5
- package/ci/vitest-no-worker-init-runner-setup.mjs +8 -0
- package/ci/vitest-no-worker-init-setup.mjs +13 -13
- package/ci/vitest-no-worker-init-v5-setup.mjs +4 -0
- package/package.json +13 -10
- package/packages/datadog-esbuild/index.js +3 -1
- package/packages/datadog-instrumentations/src/cypress-config.js +19 -17
- package/packages/datadog-instrumentations/src/fs.js +24 -20
- package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -2
- package/packages/datadog-instrumentations/src/graphql.js +16 -16
- package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +504 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +265 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +95 -30
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +0 -25
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +83 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +85 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/mercurius.js +30 -12
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +13 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +251 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +11 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +562 -27
- package/packages/datadog-instrumentations/src/jest.js +25 -20
- package/packages/datadog-instrumentations/src/knex.js +76 -0
- package/packages/datadog-instrumentations/src/mariadb.js +6 -0
- package/packages/datadog-instrumentations/src/mocha/common.js +59 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +25 -15
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +98 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -8
- package/packages/datadog-instrumentations/src/net.js +14 -17
- package/packages/datadog-instrumentations/src/next.js +212 -62
- package/packages/datadog-instrumentations/src/openai.js +42 -40
- package/packages/datadog-instrumentations/src/pg.js +15 -0
- package/packages/datadog-instrumentations/src/playwright.js +109 -13
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +40 -0
- package/packages/datadog-instrumentations/src/sequelize.js +94 -2
- package/packages/datadog-instrumentations/src/undici.js +53 -4
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +37 -3
- package/packages/datadog-instrumentations/src/vitest-main.js +92 -9
- package/packages/datadog-instrumentations/src/vitest-worker.js +71 -14
- package/packages/datadog-instrumentations/src/webdriverio.js +965 -6
- package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
- package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
- package/packages/datadog-plugin-amqp10/src/util.js +2 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +16 -5
- package/packages/datadog-plugin-cassandra-driver/src/index.js +8 -3
- package/packages/datadog-plugin-cucumber/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +262 -48
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -1
- package/packages/datadog-plugin-graphql/src/execute.js +998 -196
- package/packages/datadog-plugin-graphql/src/index.js +27 -7
- package/packages/datadog-plugin-graphql/src/jit.js +136 -0
- package/packages/datadog-plugin-graphql/src/request.js +18 -27
- package/packages/datadog-plugin-graphql/src/resolve-error.js +108 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -2
- package/packages/datadog-plugin-graphql/src/tools/transforms.js +45 -3
- package/packages/datadog-plugin-graphql/src/utils.js +208 -120
- package/packages/datadog-plugin-graphql/src/validate.js +10 -23
- package/packages/datadog-plugin-jest/src/index.js +0 -6
- package/packages/datadog-plugin-langchain/src/tracing.js +7 -0
- package/packages/datadog-plugin-mocha/src/index.js +403 -75
- package/packages/datadog-plugin-mongodb-core/src/query.js +6 -0
- package/packages/datadog-plugin-mysql/src/index.js +41 -15
- package/packages/datadog-plugin-net/src/tcp.js +3 -1
- package/packages/datadog-plugin-next/src/index.js +63 -29
- package/packages/datadog-plugin-playwright/src/index.js +167 -27
- package/packages/datadog-plugin-undici/src/index.js +27 -41
- package/packages/datadog-plugin-vitest/src/index.js +6 -12
- package/packages/dd-trace/src/aiguard/evaluation.js +2 -1
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +8 -1
- package/packages/dd-trace/src/aiguard/messages/openai.js +8 -1
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +20 -6
- package/packages/dd-trace/src/appsec/api_security/index.js +23 -6
- package/packages/dd-trace/src/appsec/api_security/sampler.js +99 -40
- package/packages/dd-trace/src/appsec/graphql.js +6 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +8 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +11 -36
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/lambda.js +44 -26
- package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +32 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +8 -8
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +6 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +20 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +5 -173
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agents.js +54 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +394 -225
- package/packages/dd-trace/src/ci-visibility/exporters/limits.js +9 -0
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +323 -31
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +42 -0
- package/packages/dd-trace/src/ci-visibility/final-flush.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +57 -18
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +0 -3
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +164 -71
- package/packages/dd-trace/src/ci-visibility/requests/video-request.js +176 -0
- package/packages/dd-trace/src/ci-visibility/telemetry.js +10 -7
- package/packages/dd-trace/src/ci-visibility/test-video.js +61 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
- package/packages/dd-trace/src/config/index.js +73 -13
- package/packages/dd-trace/src/config/parsers.js +11 -1
- package/packages/dd-trace/src/config/stable.js +3 -3
- package/packages/dd-trace/src/config/supported-configurations.json +20 -2
- package/packages/dd-trace/src/crashtracking/crashtracker.js +82 -18
- package/packages/dd-trace/src/debugger/config.js +12 -1
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/request-options.js +33 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -40
- package/packages/dd-trace/src/debugger/devtools_client/status.js +11 -6
- package/packages/dd-trace/src/debugger/devtools_client/tags.js +41 -0
- package/packages/dd-trace/src/debugger/index.js +23 -3
- package/packages/dd-trace/src/dogstatsd.js +510 -76
- package/packages/dd-trace/src/encode/0.4-cross-payload.js +170 -0
- package/packages/dd-trace/src/encode/0.4.js +5 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -8
- package/packages/dd-trace/src/evp_proxy/direct.js +27 -23
- package/packages/dd-trace/src/exporters/agent/index.js +2 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +24 -7
- package/packages/dd-trace/src/exporters/agentless/index.js +7 -9
- package/packages/dd-trace/src/exporters/agentless/writer.js +100 -118
- package/packages/dd-trace/src/exporters/common/agents.js +28 -6
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +191 -0
- package/packages/dd-trace/src/exporters/common/request.js +31 -11
- package/packages/dd-trace/src/exporters/common/url.js +40 -1
- package/packages/dd-trace/src/exporters/common/writer.js +9 -7
- package/packages/dd-trace/src/flush.js +6 -3
- package/packages/dd-trace/src/id.js +14 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +2 -1
- package/packages/dd-trace/src/llmobs/index.js +32 -32
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +22 -71
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +23 -13
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +7 -0
- package/packages/dd-trace/src/llmobs/util.js +0 -33
- package/packages/dd-trace/src/llmobs/writers/base.js +49 -32
- package/packages/dd-trace/src/log/index.js +7 -1
- package/packages/dd-trace/src/{ci-visibility/log-submission → log-submission}/log-submission-plugin.js +48 -19
- package/packages/dd-trace/src/openfeature/writers/base.js +14 -12
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/index.js +5 -24
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +14 -4
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +15 -22
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +14 -4
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +10 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +19 -4
- package/packages/dd-trace/src/opentelemetry/resource-attributes.js +55 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +10 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +93 -18
- package/packages/dd-trace/src/payload-tagging/index.js +2 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +1 -6
- package/packages/dd-trace/src/plugins/tracing.js +12 -10
- package/packages/dd-trace/src/plugins/util/ci.js +3 -1
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +16 -15
- package/packages/dd-trace/src/plugins/util/test.js +83 -20
- package/packages/dd-trace/src/plugins/util/url.js +2 -2
- package/packages/dd-trace/src/plugins/util/web.js +4 -9
- package/packages/dd-trace/src/profiling/config.js +1 -0
- package/packages/dd-trace/src/profiling/oom.js +7 -2
- package/packages/dd-trace/src/profiling/profiler.js +23 -13
- package/packages/dd-trace/src/profiling/profilers/space.js +38 -11
- package/packages/dd-trace/src/profiling/webspan-utils.js +7 -4
- package/packages/dd-trace/src/proxy.js +75 -5
- package/packages/dd-trace/src/remote_config/index.js +319 -101
- package/packages/dd-trace/src/remote_config/scheduler.js +37 -12
- package/packages/dd-trace/src/runtime_metrics/client.js +37 -8
- package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +5 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -1
- package/packages/dd-trace/src/sampling_rule.js +36 -9
- package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +4 -8
- package/packages/dd-trace/src/serverless/vercel.js +53 -20
- package/packages/dd-trace/src/serverless.js +10 -3
- package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
- package/packages/dd-trace/src/span_stats.js +24 -28
- package/packages/dd-trace/src/startup-log.js +3 -2
- package/packages/dd-trace/src/telemetry/agentless-url.js +28 -0
- package/packages/dd-trace/src/telemetry/send-data.js +18 -16
- package/packages/dd-trace/src/telemetry/session-propagation.js +3 -2
- package/packages/dd-trace/src/tracer.js +4 -5
- package/packages/dd-trace/src/tracer_metadata.js +11 -3
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +0 -27
- package/packages/dd-trace/src/encode/agentless-json.js +0 -210
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const net = require('node:net')
|
|
4
|
+
const { format } = require('node:url')
|
|
4
5
|
|
|
5
6
|
const { urlToHttpOptions } = require('./url-to-http-options-polyfill')
|
|
6
7
|
|
|
@@ -16,6 +17,44 @@ function isLoopbackHost (hostname) {
|
|
|
16
17
|
(hostname.startsWith('127.') && net.isIPv4(hostname))
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @param {string|undefined} protocol
|
|
22
|
+
* @param {string|undefined} hostname
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
function canSendApiKey (protocol, hostname) {
|
|
26
|
+
return protocol === 'https:' || protocol === 'unix:' ||
|
|
27
|
+
typeof hostname === 'string' && isLoopbackHost(hostname)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} site
|
|
32
|
+
* @param {string} [intake]
|
|
33
|
+
* @returns {URL | undefined}
|
|
34
|
+
*/
|
|
35
|
+
function createSiteUrl (site, intake) {
|
|
36
|
+
const hostname = `${intake === undefined ? '' : `${intake}.`}${site}`.toLowerCase()
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const url = new URL(format({
|
|
40
|
+
protocol: 'https:',
|
|
41
|
+
hostname,
|
|
42
|
+
}))
|
|
43
|
+
if (
|
|
44
|
+
url.hostname !== hostname ||
|
|
45
|
+
url.username ||
|
|
46
|
+
url.password ||
|
|
47
|
+
url.port ||
|
|
48
|
+
url.pathname !== '/' ||
|
|
49
|
+
url.search ||
|
|
50
|
+
url.hash
|
|
51
|
+
) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
return url
|
|
55
|
+
} catch {}
|
|
56
|
+
}
|
|
57
|
+
|
|
19
58
|
/**
|
|
20
59
|
* Convert an agent/intake URL into Node http(s) request options.
|
|
21
60
|
*
|
|
@@ -43,4 +82,4 @@ function parseUrl (urlObjOrString) {
|
|
|
43
82
|
return url
|
|
44
83
|
}
|
|
45
84
|
|
|
46
|
-
module.exports = { isLoopbackHost, parseUrl }
|
|
85
|
+
module.exports = { canSendApiKey, createSiteUrl, isLoopbackHost, parseUrl }
|
|
@@ -8,13 +8,16 @@ const request = require('./request')
|
|
|
8
8
|
const { safeJSONStringify } = require('./util')
|
|
9
9
|
|
|
10
10
|
const firstFlushChannel = channel('dd-trace:exporter:first-flush')
|
|
11
|
+
const noop = () => {}
|
|
11
12
|
|
|
12
13
|
class Writer {
|
|
13
14
|
#deliveryTracker
|
|
15
|
+
#retainOnBackpressure
|
|
14
16
|
|
|
15
|
-
constructor ({ url, beforeFirstFlush, deliveryTracker }) {
|
|
17
|
+
constructor ({ url, beforeFirstFlush, deliveryTracker, retainOnBackpressure = false }) {
|
|
16
18
|
this._url = url
|
|
17
19
|
this._beforeFirstFlush = beforeFirstFlush
|
|
20
|
+
this.#retainOnBackpressure = retainOnBackpressure
|
|
18
21
|
this.#deliveryTracker = deliveryTracker
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -39,10 +42,10 @@ class Writer {
|
|
|
39
42
|
* @param {{ deadline?: number }} [options]
|
|
40
43
|
* @returns {void}
|
|
41
44
|
*/
|
|
42
|
-
flushDirect (done =
|
|
45
|
+
flushDirect (done = noop, options) {
|
|
43
46
|
const count = this._encoder.count()
|
|
44
47
|
|
|
45
|
-
if (!request.writable && options?.deadline === undefined) {
|
|
48
|
+
if (!request.writable && options?.deadline === undefined && !this.#retainOnBackpressure) {
|
|
46
49
|
this._encoder.reset()
|
|
47
50
|
done()
|
|
48
51
|
} else if (count > 0) {
|
|
@@ -77,7 +80,7 @@ class Writer {
|
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
append (payload, options) {
|
|
80
|
-
if (!request.writable && options?.deadline === undefined) {
|
|
83
|
+
if (!request.writable && options?.deadline === undefined && !this.#retainOnBackpressure) {
|
|
81
84
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
82
85
|
log.debug(() => `Maximum number of active requests reached. Payload discarded: ${safeJSONStringify(payload)}`)
|
|
83
86
|
return false
|
|
@@ -86,12 +89,11 @@ class Writer {
|
|
|
86
89
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
87
90
|
log.debug(() => `Encoding payload: ${safeJSONStringify(payload)}`)
|
|
88
91
|
|
|
89
|
-
this._encode(payload)
|
|
90
|
-
return true
|
|
92
|
+
return this._encode(payload) !== false
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
_encode (payload) {
|
|
94
|
-
this._encoder.encode(payload)
|
|
96
|
+
return this._encoder.encode(payload)
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
setUrl (url) {
|
|
@@ -43,12 +43,16 @@ function registerTelemetryFlusher (flusher, options) {
|
|
|
43
43
|
* @param {{ timeout?: number }} [options]
|
|
44
44
|
* @param {TraceFlushers} [traceFlushers]
|
|
45
45
|
*/
|
|
46
|
-
function flushServerlessTelemetry (done, options, traceFlushers
|
|
47
|
-
const
|
|
46
|
+
function flushServerlessTelemetry (done, options, traceFlushers) {
|
|
47
|
+
const traceFlusher = traceFlushers?.trace
|
|
48
|
+
const spanStatsFlusher = traceFlushers?.spanStats
|
|
48
49
|
// TODO: Include DSM after DataStreamsProcessor exposes a completion-aware flush API.
|
|
49
50
|
let pending = telemetryFlushers.size + postTraceTelemetryFlushers.size +
|
|
50
51
|
(typeof traceFlusher === 'function' ? 1 : 0) +
|
|
51
52
|
(typeof spanStatsFlusher === 'function' ? 1 : 0)
|
|
53
|
+
|
|
54
|
+
if (pending === 0) return done?.()
|
|
55
|
+
|
|
52
56
|
let completed = false
|
|
53
57
|
let timeout
|
|
54
58
|
|
|
@@ -62,7 +66,6 @@ function flushServerlessTelemetry (done, options, traceFlushers = {}) {
|
|
|
62
66
|
if (--pending === 0) finish()
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
if (pending === 0) return finish()
|
|
66
69
|
if (options?.timeout) {
|
|
67
70
|
timeout = setTimeout(() => {
|
|
68
71
|
log.warn('Timed out waiting for telemetry flush after %dms', options.timeout)
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const { randomFillSync } = require('crypto')
|
|
4
4
|
|
|
5
|
+
const { channel } = require('dc-polyfill')
|
|
6
|
+
|
|
5
7
|
const UINT_MAX = 4_294_967_296
|
|
6
8
|
|
|
7
9
|
const data = new Uint8Array(8 * 8192)
|
|
@@ -9,6 +11,8 @@ const zeroId = new Uint8Array(8)
|
|
|
9
11
|
|
|
10
12
|
let batch = 0
|
|
11
13
|
|
|
14
|
+
channel('datadog:identity:update').subscribe(reseed)
|
|
15
|
+
|
|
12
16
|
// Internal representation of a trace or span ID.
|
|
13
17
|
class Identifier {
|
|
14
18
|
/** @type {number[] | Uint8Array} */
|
|
@@ -254,6 +258,16 @@ function writeUInt32BE (buffer, value, offset) {
|
|
|
254
258
|
buffer[0 + offset] = value & 255
|
|
255
259
|
}
|
|
256
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Resets the batch cursor, forcing the next ID batch to draw a fresh
|
|
263
|
+
* randomFillSync() call on MicroVM clone resume. Node's crypto RNG is
|
|
264
|
+
* re-seeded from the kernel CSPRNG on snapshot resume, so re-invoking it
|
|
265
|
+
* is sufficient — no need to read /dev/urandom directly.
|
|
266
|
+
*/
|
|
267
|
+
function reseed () {
|
|
268
|
+
batch = 0
|
|
269
|
+
}
|
|
270
|
+
|
|
257
271
|
/**
|
|
258
272
|
* @param {string} [value]
|
|
259
273
|
* @param {number} [radix]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { getValueFromEnvSources } = require('./config/helper')
|
|
3
|
+
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
|
|
4
|
+
const { isTrue } = require('./util')
|
|
4
5
|
|
|
5
6
|
// Global `jest` is only present in Jest workers.
|
|
6
7
|
const inJestWorker = typeof jest !== 'undefined'
|
|
@@ -8,8 +9,10 @@ const inJestWorker = typeof jest !== 'undefined'
|
|
|
8
9
|
// skipDefault: distinguish an unset DD_TRACE_ENABLED (fall back to the OTel signal) from an
|
|
9
10
|
// explicit value; the registered default would otherwise mask the OTEL_TRACES_EXPORTER check.
|
|
10
11
|
const ddTraceEnabled = getValueFromEnvSources('DD_TRACE_ENABLED', true)
|
|
12
|
+
const agentlessTracingEnabled = getValueFromEnvSources('DD_AGENTLESS_ENABLED') ||
|
|
13
|
+
isTrue(getEnvironmentVariable('_DD_APM_TRACING_AGENTLESS_ENABLED'))
|
|
11
14
|
const ddTraceDisabled = ddTraceEnabled === undefined
|
|
12
|
-
? getValueFromEnvSources('OTEL_TRACES_EXPORTER') === 'none'
|
|
15
|
+
? !agentlessTracingEnabled && getValueFromEnvSources('OTEL_TRACES_EXPORTER') === 'none'
|
|
13
16
|
: ddTraceEnabled === false
|
|
14
17
|
|
|
15
18
|
module.exports = ddTraceDisabled || inJestWorker
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { randomUUID } = require('node:crypto')
|
|
4
|
-
const
|
|
4
|
+
const createRfdc = require('../../../../../vendor/dist/rfdc')
|
|
5
|
+
const snapshotPayload = createRfdc({ proto: false, circles: false })
|
|
5
6
|
|
|
6
7
|
/** @typedef {{add?: string[], remove?: string[], replace?: string[]}} TagOperations */
|
|
7
8
|
/**
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const { channel } = require('dc-polyfill')
|
|
4
4
|
|
|
5
|
-
const { readDatadogTags, writeDatadogTags } = require('../carrier')
|
|
6
5
|
const { registerTelemetryFlusher } = require('../flush')
|
|
7
6
|
const log = require('../log')
|
|
8
7
|
const { createServerlessDeliveryTracker } = require('../serverless')
|
|
@@ -25,7 +24,7 @@ const {
|
|
|
25
24
|
PROPAGATED_TRACE_ID_KEY,
|
|
26
25
|
} = require('./constants/tags')
|
|
27
26
|
const { storage } = require('./storage')
|
|
28
|
-
const { agentNameWireSafe,
|
|
27
|
+
const { agentNameWireSafe, resolveAgentAttribution } = require('./util')
|
|
29
28
|
const telemetry = require('./telemetry')
|
|
30
29
|
const LLMObsSpanProcessor = require('./span_processor')
|
|
31
30
|
const LLMObsEvalMetricsWriter = require('./writers/evaluations')
|
|
@@ -64,6 +63,13 @@ let unregisterTelemetryFlusher
|
|
|
64
63
|
/** @type {import('../config/config-base')} */
|
|
65
64
|
let globalTracerConfig
|
|
66
65
|
|
|
66
|
+
/**
|
|
67
|
+
* @typedef {object} TraceTagInjection
|
|
68
|
+
* @property {import('../opentracing/span_context')} spanContext
|
|
69
|
+
* @property {Array<string | undefined>} [traceTagReplacements]
|
|
70
|
+
* @property {number} [optionalTraceTagCount]
|
|
71
|
+
*/
|
|
72
|
+
|
|
67
73
|
/**
|
|
68
74
|
* @param {@type import('../config/config-base')} config
|
|
69
75
|
*/
|
|
@@ -163,7 +169,8 @@ function retireWriters (retiredSpanWriter, retiredEvalWriter) {
|
|
|
163
169
|
|
|
164
170
|
// since LLMObs traces can extend between services and be the same trace,
|
|
165
171
|
// we need to propagate the parent id, mlApp, session id, and sampling rate/decision.
|
|
166
|
-
|
|
172
|
+
/** @param {TraceTagInjection} injection */
|
|
173
|
+
function handleLLMObsInjection (injection) {
|
|
167
174
|
// Respect the standard propagator's gate: when trace tag propagation is
|
|
168
175
|
// disabled, don't write `x-datadog-tags` for LLMObs either.
|
|
169
176
|
if (globalTracerConfig.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) return
|
|
@@ -201,37 +208,30 @@ function handleLLMObsInjection ({ carrier }) {
|
|
|
201
208
|
mlObsSpanTags, parent
|
|
202
209
|
)
|
|
203
210
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
if (sampleRate != null) tags += `${tags ? ',' : ''}${PROPAGATED_SAMPLE_RATE_KEY}=${sampleRate}`
|
|
212
|
-
if (samplingDecision != null) tags += `${tags ? ',' : ''}${PROPAGATED_SAMPLING_DECISION_KEY}=${samplingDecision}`
|
|
213
|
-
if (propagatedTraceId != null) tags += `${tags ? ',' : ''}${PROPAGATED_TRACE_ID_KEY}=${propagatedTraceId}`
|
|
214
|
-
// When a local agent attribution is resolved, strip any stale upstream pagent entries that
|
|
215
|
-
// `_injectTags` may have already written into the carrier (it propagates all `_dd.p.*` from
|
|
216
|
-
// `_trace.tags`). This ensures the downstream sees a consistent id-only or id+name pair
|
|
217
|
-
// rather than a mix from different hops. The id is always digit-safe; an unsafe name is wiped.
|
|
218
|
-
if (parentAgentSpanId) {
|
|
219
|
-
tags = stripTagsetEntry(tags, PROPAGATED_PARENT_AGENT_ID_KEY)
|
|
220
|
-
tags = stripTagsetEntry(tags, PROPAGATED_PARENT_AGENT_NAME_KEY)
|
|
211
|
+
const traceTagReplacements = []
|
|
212
|
+
if (parentId) traceTagReplacements.push(PROPAGATED_PARENT_ID_KEY, parentId)
|
|
213
|
+
if (mlApp) traceTagReplacements.push(PROPAGATED_ML_APP_KEY, mlApp)
|
|
214
|
+
if (sessionId) traceTagReplacements.push(PROPAGATED_SESSION_ID_KEY, sessionId)
|
|
215
|
+
if (sampleRate != null) traceTagReplacements.push(PROPAGATED_SAMPLE_RATE_KEY, sampleRate.toString())
|
|
216
|
+
if (samplingDecision != null) {
|
|
217
|
+
traceTagReplacements.push(PROPAGATED_SAMPLING_DECISION_KEY, samplingDecision.toString())
|
|
221
218
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
219
|
+
if (propagatedTraceId != null) traceTagReplacements.push(PROPAGATED_TRACE_ID_KEY, propagatedTraceId)
|
|
220
|
+
|
|
221
|
+
let optionalTraceTagCount = 0
|
|
222
|
+
if (parentAgentSpanId) {
|
|
223
|
+
traceTagReplacements.push(PROPAGATED_PARENT_AGENT_ID_KEY, parentAgentSpanId)
|
|
224
|
+
optionalTraceTagCount++
|
|
225
|
+
if (parentAgentName && agentNameWireSafe(parentAgentName)) {
|
|
226
|
+
traceTagReplacements.push(PROPAGATED_PARENT_AGENT_NAME_KEY, parentAgentName)
|
|
227
|
+
} else {
|
|
228
|
+
traceTagReplacements.push(PROPAGATED_PARENT_AGENT_NAME_KEY, undefined)
|
|
229
|
+
}
|
|
230
|
+
optionalTraceTagCount++
|
|
233
231
|
}
|
|
234
|
-
|
|
232
|
+
|
|
233
|
+
injection.traceTagReplacements = traceTagReplacements
|
|
234
|
+
injection.optionalTraceTagCount = optionalTraceTagCount
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
/**
|
|
@@ -4,7 +4,6 @@ const { channel } = require('dc-polyfill')
|
|
|
4
4
|
const BaseLLMObsPlugin = require('../base')
|
|
5
5
|
const { getModelProvider } = require('../../../../../datadog-plugin-ai/src/utils')
|
|
6
6
|
|
|
7
|
-
const toolCreationCh = channel('tracing:orchestrion:ai:tool:start')
|
|
8
7
|
const setAttributesCh = channel('dd-trace:vercel-ai:span:setAttributes')
|
|
9
8
|
|
|
10
9
|
const { MODEL_NAME, MODEL_PROVIDER, NAME } = require('../../constants/tags')
|
|
@@ -21,16 +20,10 @@ const {
|
|
|
21
20
|
getTelemetryMetadata,
|
|
22
21
|
} = require('./util')
|
|
23
22
|
|
|
24
|
-
/**
|
|
25
|
-
* @typedef {Record<string, unknown> & { description?: string, id?: string }} AvailableToolArgs
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
23
|
/**
|
|
29
24
|
* @typedef {string | number | boolean | null | undefined | string[] | number[] | boolean[]} TagValue
|
|
30
25
|
* @typedef {Record<string, TagValue>} SpanTags
|
|
31
26
|
*
|
|
32
|
-
* @typedef {{ name?: string, description?: string }} ToolForModel
|
|
33
|
-
*
|
|
34
27
|
* @typedef {{ type: 'text' | 'reasoning' | 'redacted-reasoning', text?: string, data?: string }} TextPart
|
|
35
28
|
* @typedef {{ type: 'tool-call', toolName: string, toolCallId: string, args?: unknown, input?: unknown }} ToolCallPart
|
|
36
29
|
* @typedef {(
|
|
@@ -76,58 +69,14 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
76
69
|
static integration = 'ai'
|
|
77
70
|
static prefix = 'tracing:dd-trace:vercel-ai'
|
|
78
71
|
|
|
79
|
-
/**
|
|
80
|
-
* The available tools within the runtime scope of this integration.
|
|
81
|
-
* This essentially acts as a global registry for all tools made through the Vercel AI SDK.
|
|
82
|
-
* @type {Set<AvailableToolArgs>}
|
|
83
|
-
*/
|
|
84
|
-
#availableTools
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* A mapping of tool call IDs to tool names.
|
|
88
|
-
* This is used to map the tool call ID to the tool name for the output message.
|
|
89
|
-
* @type {Record<string, string>}
|
|
90
|
-
*/
|
|
91
|
-
#toolCallIdsToName
|
|
92
|
-
|
|
93
72
|
constructor (...args) {
|
|
94
73
|
super(...args)
|
|
95
74
|
|
|
96
|
-
this.#toolCallIdsToName = {}
|
|
97
|
-
this.#availableTools = new Set()
|
|
98
|
-
toolCreationCh.subscribe(ctx => {
|
|
99
|
-
const toolArgs = ctx.arguments
|
|
100
|
-
const tool = toolArgs[0] ?? {}
|
|
101
|
-
this.#availableTools.add(tool)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
75
|
setAttributesCh.subscribe(({ ctx, attributes }) => {
|
|
105
76
|
Object.assign(ctx.attributes, attributes)
|
|
106
77
|
})
|
|
107
78
|
}
|
|
108
79
|
|
|
109
|
-
/**
|
|
110
|
-
* Does a best-effort attempt to find the right tool name for the given tool description.
|
|
111
|
-
* This is because the Vercel AI SDK does not tag tools by name properly, but
|
|
112
|
-
* rather by the index they were passed in. Tool names appear nowhere in the span tags.
|
|
113
|
-
*
|
|
114
|
-
* We use the tool description as the next best identifier for a tool.
|
|
115
|
-
*
|
|
116
|
-
* @param {string} toolName
|
|
117
|
-
* @param {string | undefined} toolDescription
|
|
118
|
-
* @returns {string | undefined}
|
|
119
|
-
*/
|
|
120
|
-
findToolName (toolName, toolDescription) {
|
|
121
|
-
if (Number.isNaN(Number.parseInt(toolName, 10))) return toolName
|
|
122
|
-
|
|
123
|
-
for (const availableTool of this.#availableTools) {
|
|
124
|
-
const description = availableTool.description
|
|
125
|
-
if (description === toolDescription && availableTool.id) {
|
|
126
|
-
return availableTool.id
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
80
|
/**
|
|
132
81
|
* @override
|
|
133
82
|
*/
|
|
@@ -232,7 +181,13 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
232
181
|
const lastUserPrompt =
|
|
233
182
|
promptInfo.prompt ??
|
|
234
183
|
promptInfo.messages.reverse().find(message => message.role === 'user')?.content
|
|
235
|
-
|
|
184
|
+
let prompt = lastUserPrompt
|
|
185
|
+
if (Array.isArray(lastUserPrompt)) {
|
|
186
|
+
prompt = ''
|
|
187
|
+
for (const part of lastUserPrompt) {
|
|
188
|
+
if (typeof part.text === 'string') prompt += part.text
|
|
189
|
+
}
|
|
190
|
+
}
|
|
236
191
|
|
|
237
192
|
const output = tags['ai.response.object']
|
|
238
193
|
|
|
@@ -248,7 +203,13 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
248
203
|
const lastUserPrompt =
|
|
249
204
|
promptInfo.prompt ??
|
|
250
205
|
promptInfo.messages.reverse().find(message => message.role === 'user')?.content
|
|
251
|
-
|
|
206
|
+
let prompt = lastUserPrompt
|
|
207
|
+
if (Array.isArray(lastUserPrompt)) {
|
|
208
|
+
prompt = ''
|
|
209
|
+
for (const part of lastUserPrompt) {
|
|
210
|
+
if (typeof part.text === 'string') prompt += part.text
|
|
211
|
+
}
|
|
212
|
+
}
|
|
252
213
|
|
|
253
214
|
const output = tags['ai.response.text']
|
|
254
215
|
|
|
@@ -263,16 +224,14 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
263
224
|
* @param {SpanTags} tags
|
|
264
225
|
*/
|
|
265
226
|
setLLMOperationTags (span, tags) {
|
|
266
|
-
const toolsForModel = tags['ai.prompt.tools']?.map(getJsonStringValue)
|
|
267
|
-
|
|
268
227
|
const inputMessages = getJsonStringValue(tags['ai.prompt.messages'], [])
|
|
269
228
|
const parsedInputMessages = []
|
|
270
229
|
for (const message of inputMessages) {
|
|
271
|
-
const formattedMessages = this.formatMessage(message
|
|
230
|
+
const formattedMessages = this.formatMessage(message)
|
|
272
231
|
parsedInputMessages.push(...formattedMessages)
|
|
273
232
|
}
|
|
274
233
|
|
|
275
|
-
const outputMessage = this.formatOutputMessage(tags
|
|
234
|
+
const outputMessage = this.formatOutputMessage(tags)
|
|
276
235
|
|
|
277
236
|
this._tagger.tagLLMIO(span, parsedInputMessages, outputMessage)
|
|
278
237
|
|
|
@@ -284,8 +243,8 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
284
243
|
}
|
|
285
244
|
|
|
286
245
|
setToolTags (span, tags) {
|
|
287
|
-
const
|
|
288
|
-
|
|
246
|
+
const name = getToolNameFromTags(tags)
|
|
247
|
+
|
|
289
248
|
if (name) this._tagger._setTag(span, NAME, name)
|
|
290
249
|
|
|
291
250
|
const input = tags['ai.toolCall.args']
|
|
@@ -294,7 +253,7 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
294
253
|
this._tagger.tagTextIO(span, input, output)
|
|
295
254
|
}
|
|
296
255
|
|
|
297
|
-
formatOutputMessage (tags
|
|
256
|
+
formatOutputMessage (tags) {
|
|
298
257
|
const outputMessageText = tags['ai.response.text'] ?? tags['ai.response.object']
|
|
299
258
|
const outputMessageToolCalls = getJsonStringValue(tags['ai.response.toolCalls'], [])
|
|
300
259
|
|
|
@@ -302,13 +261,9 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
302
261
|
for (const toolCall of outputMessageToolCalls) {
|
|
303
262
|
const toolArgs = toolCall.args ?? toolCall.input
|
|
304
263
|
const toolCallArgs = typeof toolArgs === 'string' ? getJsonStringValue(toolArgs, {}) : toolArgs
|
|
305
|
-
const toolDescription = toolsForModel?.find(tool => toolCall.toolName === tool.name)?.description
|
|
306
|
-
const name = this.findToolName(toolCall.toolName, toolDescription)
|
|
307
|
-
this.#toolCallIdsToName[toolCall.toolCallId] = name
|
|
308
|
-
|
|
309
264
|
formattedToolCalls.push({
|
|
310
265
|
arguments: toolCallArgs,
|
|
311
|
-
name,
|
|
266
|
+
name: toolCall.toolName,
|
|
312
267
|
toolId: toolCall.toolCallId,
|
|
313
268
|
type: toolCall.toolCallType ?? 'function',
|
|
314
269
|
})
|
|
@@ -328,11 +283,10 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
328
283
|
* need to split into multiple messages.
|
|
329
284
|
*
|
|
330
285
|
* @param {AiSdkMessage} message
|
|
331
|
-
* @param {ToolForModel[] | null | undefined} toolsForModel
|
|
332
286
|
* @returns {Array<{role: string, content: string, toolId?: string,
|
|
333
287
|
* toolCalls?: Array<{arguments: string, name: string, toolId: string, type: string}>}>}
|
|
334
288
|
*/
|
|
335
|
-
formatMessage (message
|
|
289
|
+
formatMessage (message) {
|
|
336
290
|
const { role, content } = message
|
|
337
291
|
|
|
338
292
|
if (role === 'system') {
|
|
@@ -357,12 +311,9 @@ class DdTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
357
311
|
if (['text', 'reasoning', 'redacted-reasoning'].includes(type)) {
|
|
358
312
|
finalContent += part.text ?? part.data
|
|
359
313
|
} else if (type === 'tool-call') {
|
|
360
|
-
const toolDescription = toolsForModel?.find(tool => part.toolName === tool.name)?.description
|
|
361
|
-
const name = this.findToolName(part.toolName, toolDescription)
|
|
362
|
-
|
|
363
314
|
toolCalls.push({
|
|
364
315
|
arguments: part.args ?? part.input,
|
|
365
|
-
name,
|
|
316
|
+
name: part.toolName,
|
|
366
317
|
toolId: part.toolCallId,
|
|
367
318
|
type: 'function',
|
|
368
319
|
})
|
|
@@ -38,11 +38,15 @@ function formatLanguageModelInputMessages (instructions, messages) {
|
|
|
38
38
|
const inputMessages = []
|
|
39
39
|
|
|
40
40
|
if (instructions) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
let systemPrompt = instructions
|
|
42
|
+
if (typeof instructions !== 'string') {
|
|
43
|
+
if (Array.isArray(instructions)) {
|
|
44
|
+
systemPrompt = ''
|
|
45
|
+
for (const instruction of instructions) systemPrompt += instruction.content
|
|
46
|
+
} else {
|
|
47
|
+
systemPrompt = instructions.content
|
|
48
|
+
}
|
|
49
|
+
}
|
|
46
50
|
|
|
47
51
|
inputMessages.push({ role: 'system', content: systemPrompt })
|
|
48
52
|
}
|
|
@@ -53,13 +57,13 @@ function formatLanguageModelInputMessages (instructions, messages) {
|
|
|
53
57
|
if (role === 'system') {
|
|
54
58
|
inputMessages.push({ role, content })
|
|
55
59
|
} else if (role === 'user') {
|
|
56
|
-
|
|
57
|
-
typeof content
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
let userMessageContent = content
|
|
61
|
+
if (typeof content !== 'string') {
|
|
62
|
+
userMessageContent = ''
|
|
63
|
+
for (const part of content) {
|
|
64
|
+
if (part.type === 'text') userMessageContent += part.text
|
|
65
|
+
}
|
|
66
|
+
}
|
|
63
67
|
|
|
64
68
|
inputMessages.push({ role, content: userMessageContent })
|
|
65
69
|
} else if (role === 'assistant') {
|
|
@@ -292,7 +296,13 @@ class VercelAiTelemetryPlugin extends BaseLLMObsPlugin {
|
|
|
292
296
|
const { event, result } = ctx
|
|
293
297
|
|
|
294
298
|
const lastUserPrompt = event.messages.findLast(message => message.role === 'user')?.content
|
|
295
|
-
|
|
299
|
+
let input = lastUserPrompt
|
|
300
|
+
if (Array.isArray(lastUserPrompt)) {
|
|
301
|
+
input = ''
|
|
302
|
+
for (const part of lastUserPrompt) {
|
|
303
|
+
if (part.type === 'text') input += part.text
|
|
304
|
+
}
|
|
305
|
+
}
|
|
296
306
|
|
|
297
307
|
const output =
|
|
298
308
|
ctx.isStream
|
|
@@ -46,6 +46,13 @@ class BaseLangChainLLMObsPlugin extends LLMObsPlugin {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
error (ctx) {
|
|
50
|
+
// NodeInterrupt or GraphInterrupt "errors" for control flow, do not mark as real errors
|
|
51
|
+
if (ctx.error?.is_bubble_up) return
|
|
52
|
+
|
|
53
|
+
super.error(ctx)
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
getLLMObsSpanRegisterOptions (ctx) {
|
|
50
57
|
const span = ctx.currentStore?.span
|
|
51
58
|
const spanContext = span?.context()
|
|
@@ -337,37 +337,6 @@ function resolveAgentAttribution (tags, span) {
|
|
|
337
337
|
return { name: tags[PARENT_AGENT_NAME], spanId: tags[PARENT_AGENT_SPAN_ID] }
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
-
/**
|
|
341
|
-
* Removes all `key=value` entries for the given key from a comma-separated tagset string.
|
|
342
|
-
*
|
|
343
|
-
* @param {string} tags - Existing tagset string (may be empty).
|
|
344
|
-
* @param {string} key
|
|
345
|
-
* @returns {string}
|
|
346
|
-
*/
|
|
347
|
-
function stripTagsetEntry (tags, key) {
|
|
348
|
-
if (!tags.includes(key)) return tags
|
|
349
|
-
return tags.split(',').filter(entry => !entry.startsWith(`${key}=`)).join(',')
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Appends `key=value` to the tagset string with a comma separator, but only when `value` is
|
|
354
|
-
* truthy, passes the optional `safeguard` predicate, and fits within `maxTagSetLength`. Returns
|
|
355
|
-
* the original `tags` unchanged when the value is absent, unsafe, or would overflow the budget.
|
|
356
|
-
*
|
|
357
|
-
* @param {string} tags - Existing tagset string (may be empty).
|
|
358
|
-
* @param {string} key
|
|
359
|
-
* @param {string | undefined} value
|
|
360
|
-
* @param {((v: string) => boolean) | null} [safeguard]
|
|
361
|
-
* @param {number} [maxTagSetLength]
|
|
362
|
-
* @returns {string}
|
|
363
|
-
*/
|
|
364
|
-
function appendOptionalPropagatedTag (tags, key, value, safeguard, maxTagSetLength) {
|
|
365
|
-
if (!value || (safeguard && !safeguard(value))) return tags
|
|
366
|
-
const entry = `${tags ? ',' : ''}${key}=${value}`
|
|
367
|
-
if (maxTagSetLength != null && tags.length + entry.length > maxTagSetLength) return tags
|
|
368
|
-
return `${tags}${entry}`
|
|
369
|
-
}
|
|
370
|
-
|
|
371
340
|
function spanHasError (span) {
|
|
372
341
|
const spanContext = span.context()
|
|
373
342
|
return !!(spanContext.getTag('error') || spanContext.getTag('error.type'))
|
|
@@ -518,7 +487,6 @@ function formatAudioPart (data, mimeType) {
|
|
|
518
487
|
|
|
519
488
|
module.exports = {
|
|
520
489
|
agentNameWireSafe,
|
|
521
|
-
appendOptionalPropagatedTag,
|
|
522
490
|
audioMimeTypeFromFormat,
|
|
523
491
|
encodeUnicode,
|
|
524
492
|
findGenAIAncestorSpanId,
|
|
@@ -527,7 +495,6 @@ module.exports = {
|
|
|
527
495
|
normalizeLlmObsTraceId,
|
|
528
496
|
formatAudioPart,
|
|
529
497
|
resolveAgentAttribution,
|
|
530
|
-
stripTagsetEntry,
|
|
531
498
|
validateCostTags,
|
|
532
499
|
validateKind,
|
|
533
500
|
getFunctionArguments,
|