dd-trace 5.101.0 → 5.103.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/ext/exporters.js +1 -0
- package/package.json +20 -17
- package/packages/datadog-esbuild/src/utils.js +2 -2
- package/packages/datadog-instrumentations/src/aerospike.js +2 -2
- package/packages/datadog-instrumentations/src/ai.js +9 -9
- package/packages/datadog-instrumentations/src/amqplib.js +6 -7
- package/packages/datadog-instrumentations/src/anthropic.js +10 -10
- package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
- package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
- package/packages/datadog-instrumentations/src/avsc.js +6 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
- package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
- package/packages/datadog-instrumentations/src/bluebird.js +2 -2
- package/packages/datadog-instrumentations/src/body-parser.js +2 -2
- package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
- package/packages/datadog-instrumentations/src/child_process.js +12 -12
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +41 -24
- package/packages/datadog-instrumentations/src/connect.js +7 -7
- package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
- package/packages/datadog-instrumentations/src/cookie.js +2 -2
- package/packages/datadog-instrumentations/src/couchbase.js +73 -238
- package/packages/datadog-instrumentations/src/crypto.js +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +78 -17
- package/packages/datadog-instrumentations/src/dns.js +0 -3
- package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
- package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
- package/packages/datadog-instrumentations/src/electron.js +240 -0
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
- package/packages/datadog-instrumentations/src/express-session.js +4 -4
- package/packages/datadog-instrumentations/src/express.js +10 -11
- package/packages/datadog-instrumentations/src/fastify.js +2 -2
- package/packages/datadog-instrumentations/src/fetch.js +5 -5
- package/packages/datadog-instrumentations/src/fs.js +14 -14
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
- package/packages/datadog-instrumentations/src/google-genai.js +4 -4
- package/packages/datadog-instrumentations/src/graphql.js +13 -12
- package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
- package/packages/datadog-instrumentations/src/hapi.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +9 -9
- package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/kafka.js +41 -0
- package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
- package/packages/datadog-instrumentations/src/hono.js +2 -2
- package/packages/datadog-instrumentations/src/http/client.js +6 -6
- package/packages/datadog-instrumentations/src/http/server.js +9 -9
- package/packages/datadog-instrumentations/src/ioredis.js +16 -12
- package/packages/datadog-instrumentations/src/jest.js +382 -81
- package/packages/datadog-instrumentations/src/kafkajs.js +165 -174
- package/packages/datadog-instrumentations/src/knex.js +17 -17
- package/packages/datadog-instrumentations/src/koa.js +12 -12
- package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
- package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
- package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
- package/packages/datadog-instrumentations/src/lodash.js +4 -4
- package/packages/datadog-instrumentations/src/mariadb.js +13 -13
- package/packages/datadog-instrumentations/src/memcached.js +2 -2
- package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/common.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +85 -11
- package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
- package/packages/datadog-instrumentations/src/mongodb-core.js +42 -30
- package/packages/datadog-instrumentations/src/mongodb.js +5 -5
- package/packages/datadog-instrumentations/src/mongoose.js +21 -21
- package/packages/datadog-instrumentations/src/mquery.js +5 -5
- package/packages/datadog-instrumentations/src/multer.js +4 -4
- package/packages/datadog-instrumentations/src/mysql.js +16 -16
- package/packages/datadog-instrumentations/src/mysql2.js +4 -4
- package/packages/datadog-instrumentations/src/net.js +14 -8
- package/packages/datadog-instrumentations/src/nyc.js +5 -5
- package/packages/datadog-instrumentations/src/openai.js +19 -19
- package/packages/datadog-instrumentations/src/oracledb.js +6 -6
- package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
- package/packages/datadog-instrumentations/src/pg.js +39 -25
- package/packages/datadog-instrumentations/src/pino.js +6 -10
- package/packages/datadog-instrumentations/src/playwright.js +445 -68
- package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
- package/packages/datadog-instrumentations/src/redis.js +20 -12
- package/packages/datadog-instrumentations/src/restify.js +2 -2
- package/packages/datadog-instrumentations/src/router.js +12 -12
- package/packages/datadog-instrumentations/src/stripe.js +12 -12
- package/packages/datadog-instrumentations/src/vitest.js +107 -26
- package/packages/datadog-instrumentations/src/winston.js +4 -4
- package/packages/datadog-instrumentations/src/ws.js +7 -7
- package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
- package/packages/datadog-plugin-aws-sdk/src/base.js +70 -28
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +20 -13
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +46 -36
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +34 -23
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +14 -15
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +74 -55
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +20 -18
- package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
- package/packages/datadog-plugin-couchbase/src/index.js +58 -52
- package/packages/datadog-plugin-cucumber/src/index.js +5 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +215 -26
- package/packages/datadog-plugin-cypress/src/support.js +13 -1
- package/packages/datadog-plugin-electron/src/index.js +17 -0
- package/packages/datadog-plugin-electron/src/ipc.js +143 -0
- package/packages/datadog-plugin-electron/src/net.js +82 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
- package/packages/datadog-plugin-graphql/src/execute.js +6 -28
- package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
- package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
- package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
- package/packages/datadog-plugin-graphql/src/utils.js +29 -0
- package/packages/datadog-plugin-grpc/src/client.js +6 -7
- package/packages/datadog-plugin-grpc/src/util.js +57 -22
- package/packages/datadog-plugin-http/src/client.js +3 -7
- package/packages/datadog-plugin-jest/src/index.js +92 -50
- package/packages/datadog-plugin-jest/src/util.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +5 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +36 -69
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/services.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +12 -23
- package/packages/datadog-plugin-pg/src/index.js +3 -3
- package/packages/datadog-plugin-playwright/src/index.js +5 -1
- package/packages/datadog-plugin-redis/src/index.js +18 -23
- package/packages/datadog-plugin-vitest/src/index.js +8 -1
- package/packages/datadog-shimmer/src/shimmer.js +7 -1
- package/packages/dd-trace/src/aiguard/index.js +3 -1
- package/packages/dd-trace/src/aiguard/sdk.js +36 -30
- package/packages/dd-trace/src/aiguard/tags.js +20 -11
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +4 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +21 -24
- package/packages/dd-trace/src/appsec/reporter.js +3 -1
- package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
- package/packages/dd-trace/src/azure_metadata.js +17 -6
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
- package/packages/dd-trace/src/config/defaults.js +3 -14
- package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -1
- package/packages/dd-trace/src/config/git_properties.js +2 -2
- package/packages/dd-trace/src/config/helper.js +4 -0
- package/packages/dd-trace/src/config/index.js +2 -2
- package/packages/dd-trace/src/config/major-overrides.js +98 -0
- package/packages/dd-trace/src/config/parsers.js +7 -1
- package/packages/dd-trace/src/config/supported-configurations.json +51 -38
- package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
- package/packages/dd-trace/src/datastreams/index.js +2 -1
- package/packages/dd-trace/src/datastreams/manager.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
- package/packages/dd-trace/src/debugger/index.js +7 -7
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +748 -232
- package/packages/dd-trace/src/encode/0.5.js +47 -10
- package/packages/dd-trace/src/encode/agentless-json.js +1 -1
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/agent/index.js +2 -1
- package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
- package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/exporters/electron/index.js +49 -0
- package/packages/dd-trace/src/external-logger/src/index.js +2 -1
- package/packages/dd-trace/src/git_metadata.js +10 -8
- package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
- package/packages/dd-trace/src/lambda/index.js +62 -14
- package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
- package/packages/dd-trace/src/llmobs/index.js +13 -2
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +6 -3
- package/packages/dd-trace/src/llmobs/sdk.js +24 -26
- package/packages/dd-trace/src/llmobs/span_processor.js +25 -5
- package/packages/dd-trace/src/llmobs/util.js +1 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
- package/packages/dd-trace/src/msgpack/chunk.js +6 -3
- package/packages/dd-trace/src/openfeature/noop.js +40 -36
- package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
- package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
- package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +49 -4
- package/packages/dd-trace/src/plugins/database.js +54 -12
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/plugin.js +2 -4
- package/packages/dd-trace/src/plugins/util/ci.js +9 -9
- package/packages/dd-trace/src/plugins/util/git-cache.js +23 -23
- package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
- package/packages/dd-trace/src/plugins/util/test.js +56 -12
- package/packages/dd-trace/src/plugins/util/url.js +1 -3
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +18 -16
- package/packages/dd-trace/src/plugins/util/web.js +5 -7
- package/packages/dd-trace/src/priority_sampler.js +1 -1
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
- package/packages/dd-trace/src/profiling/profilers/wall.js +5 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
- package/packages/dd-trace/src/rate_limiter.js +1 -1
- package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
- package/packages/dd-trace/src/ritm.js +2 -1
- package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
- package/packages/dd-trace/src/scope.js +3 -10
- package/packages/dd-trace/src/serverless.js +6 -6
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +27 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +24 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
- package/packages/dd-trace/src/span_stats.js +1 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
- package/packages/dd-trace/src/tracer.js +7 -7
- package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { normalizeSpan } = require('./tags-processors')
|
|
4
|
-
const { AgentEncoder: BaseEncoder } = require('./0.4')
|
|
4
|
+
const { AgentEncoder: BaseEncoder, stringifySpanEvents } = require('./0.4')
|
|
5
5
|
|
|
6
6
|
const ARRAY_OF_TWO = 0x92
|
|
7
7
|
const ARRAY_OF_TWELVE = 0x9C
|
|
8
8
|
|
|
9
9
|
function formatSpan (span) {
|
|
10
10
|
span = normalizeSpan(span)
|
|
11
|
-
//
|
|
11
|
+
// v0.5 has no native span_events slot; always serialize as a meta tag.
|
|
12
12
|
if (span.span_events) {
|
|
13
|
-
span.meta.events =
|
|
14
|
-
delete span.
|
|
13
|
+
span.meta.events = stringifySpanEvents(span.span_events)
|
|
14
|
+
// `= undefined` over `delete` to keep the span's hidden class.
|
|
15
|
+
span.span_events = undefined
|
|
15
16
|
}
|
|
16
17
|
return span
|
|
17
18
|
}
|
|
@@ -45,22 +46,58 @@ class AgentEncoder extends BaseEncoder {
|
|
|
45
46
|
this._encodeId(bytes, span.trace_id)
|
|
46
47
|
this._encodeId(bytes, span.span_id)
|
|
47
48
|
this._encodeId(bytes, span.parent_id)
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
49
|
+
this._encodeIntOrFloat(bytes, span.start || 0)
|
|
50
|
+
this._encodeIntOrFloat(bytes, span.duration || 0)
|
|
51
|
+
this._encodeIntOrFloat(bytes, span.error)
|
|
51
52
|
this._encodeMap(bytes, span.meta || {})
|
|
52
53
|
this._encodeMap(bytes, span.metrics || {})
|
|
53
54
|
this._encodeString(bytes, span.type)
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
// Override the inherited 0.4 `_encodeMap` so the v0.5 wire emits each numeric
|
|
59
|
+
// value via `_encodeIntOrFloat` (compact unsigned/signed int when integer,
|
|
60
|
+
// float64 otherwise) instead of always float64. The 0.4 base method stays on
|
|
61
|
+
// float64 because the CI-visibility encoders inherit it and target a
|
|
62
|
+
// different intake.
|
|
63
|
+
_encodeMap (bytes, value) {
|
|
64
|
+
const offset = bytes.length
|
|
65
|
+
bytes.reserve(5)
|
|
66
|
+
bytes.buffer[offset] = 0xDF
|
|
67
|
+
|
|
68
|
+
let count = 0
|
|
69
|
+
for (const key of Object.keys(value)) {
|
|
70
|
+
const entryValue = value[key]
|
|
71
|
+
if (typeof entryValue === 'string') {
|
|
72
|
+
this._encodeString(bytes, key)
|
|
73
|
+
this._encodeString(bytes, entryValue)
|
|
74
|
+
count++
|
|
75
|
+
} else if (typeof entryValue === 'number') {
|
|
76
|
+
this._encodeString(bytes, key)
|
|
77
|
+
this._encodeIntOrFloat(bytes, entryValue)
|
|
78
|
+
count++
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const target = bytes.buffer
|
|
83
|
+
target[offset + 1] = count >>> 24
|
|
84
|
+
target[offset + 2] = count >>> 16
|
|
85
|
+
target[offset + 3] = count >>> 8
|
|
86
|
+
target[offset + 4] = count
|
|
87
|
+
}
|
|
88
|
+
|
|
57
89
|
_encodeString (bytes, value = '') {
|
|
58
|
-
this.
|
|
59
|
-
|
|
90
|
+
let index = this._stringMap[value]
|
|
91
|
+
if (index === undefined) {
|
|
92
|
+
index = this._stringCount++
|
|
93
|
+
this._stringMap[value] = index
|
|
94
|
+
this._stringBytes.write(value)
|
|
95
|
+
}
|
|
96
|
+
this._encodeInteger(bytes, index)
|
|
60
97
|
}
|
|
61
98
|
|
|
62
99
|
_cacheString (value) {
|
|
63
|
-
if (
|
|
100
|
+
if (this._stringMap[value] === undefined) {
|
|
64
101
|
this._stringMap[value] = this._stringCount++
|
|
65
102
|
this._stringBytes.write(value)
|
|
66
103
|
}
|
|
@@ -85,7 +85,7 @@ function spanToJSON (span) {
|
|
|
85
85
|
class AgentlessJSONEncoder {
|
|
86
86
|
/**
|
|
87
87
|
* @param {object} writer - Writer instance with a flush() method, called when the buffer exceeds the soft limit
|
|
88
|
-
* @param {object} [metadata
|
|
88
|
+
* @param {object} [metadata] - Shared metadata spread into each trace object (hostname, env, tracerVersion, etc.)
|
|
89
89
|
*/
|
|
90
90
|
constructor (writer, metadata = {}) {
|
|
91
91
|
this._writer = writer
|
|
@@ -18,7 +18,7 @@ class AgentlessExporter {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {object} config - Configuration object
|
|
21
|
-
* @param {string} [config.site
|
|
21
|
+
* @param {string} [config.site] - The Datadog site. Defaults to 'datadoghq.com'.
|
|
22
22
|
* @param {string} [config.url] - Override intake URL
|
|
23
23
|
* @param {number} [config.flushInterval] - Batch flush interval in ms
|
|
24
24
|
* @param {string} [config.env] - Environment name
|
|
@@ -109,7 +109,8 @@ class AgentlessExporter {
|
|
|
109
109
|
log.error('Failed to flush traces on timer: %s', err.message)
|
|
110
110
|
}
|
|
111
111
|
this.#timer = undefined
|
|
112
|
-
}, flushInterval)
|
|
112
|
+
}, flushInterval)
|
|
113
|
+
this.#timer.unref?.()
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
|
|
@@ -19,8 +19,8 @@ class AgentlessWriter extends BaseWriter {
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {object} options - Writer options
|
|
21
21
|
* @param {URL} [options.url] - The intake URL. If not provided, constructed from site.
|
|
22
|
-
* @param {string} [options.site
|
|
23
|
-
* @param {object} [options.metadata
|
|
22
|
+
* @param {string} [options.site] - The Datadog site
|
|
23
|
+
* @param {object} [options.metadata] - Metadata to pass to the encoder (hostname, env, etc.)
|
|
24
24
|
*/
|
|
25
25
|
constructor ({ url, site = 'datadoghq.com', metadata = {} }) {
|
|
26
26
|
super({ url })
|
|
@@ -180,7 +180,7 @@ function request (data, options, callback) {
|
|
|
180
180
|
// Unref so a pending retry never keeps the host process alive past
|
|
181
181
|
// its natural exit point; long-running apps still retry because the
|
|
182
182
|
// event loop is held open by their own work.
|
|
183
|
-
setTimeout(attempt, getRetryDelay(options, attemptIndex), attemptIndex + 1).unref()
|
|
183
|
+
setTimeout(attempt, getRetryDelay(options, attemptIndex), attemptIndex + 1).unref?.()
|
|
184
184
|
} else {
|
|
185
185
|
callback(error)
|
|
186
186
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { channel } = require('dc-polyfill')
|
|
4
|
+
const { truncateSpan, normalizeSpan } = require('../../encode/tags-processors')
|
|
5
|
+
|
|
6
|
+
const traceChannel = channel('datadog:apm:electron:export')
|
|
7
|
+
|
|
8
|
+
class ElectronExporter {
|
|
9
|
+
#timer
|
|
10
|
+
#traces = []
|
|
11
|
+
|
|
12
|
+
constructor (config) {
|
|
13
|
+
this._config = config
|
|
14
|
+
|
|
15
|
+
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(this.flush.bind(this))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export (spans) {
|
|
19
|
+
this.#traces.push(spans)
|
|
20
|
+
|
|
21
|
+
const { flushInterval } = this._config
|
|
22
|
+
|
|
23
|
+
if (flushInterval === 0) {
|
|
24
|
+
this.flush()
|
|
25
|
+
} else if (this.#timer === undefined) {
|
|
26
|
+
this.#timer = setTimeout(() => {
|
|
27
|
+
this.flush()
|
|
28
|
+
this.#timer = undefined
|
|
29
|
+
}, flushInterval)
|
|
30
|
+
this.#timer.unref?.()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
flush (done = () => {}) {
|
|
35
|
+
clearTimeout(this.#timer)
|
|
36
|
+
this.#timer = undefined
|
|
37
|
+
|
|
38
|
+
const traces = this.#traces.splice(0)
|
|
39
|
+
|
|
40
|
+
if (traces.length > 0 && traceChannel.hasSubscribers) {
|
|
41
|
+
const formattedTraces = traces.map(spans => spans.map(span => normalizeSpan(truncateSpan(span))))
|
|
42
|
+
traceChannel.publish(formattedTraces)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
done()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = ElectronExporter
|
|
@@ -12,19 +12,21 @@ const {
|
|
|
12
12
|
resolveGitHeadSHA,
|
|
13
13
|
} = require('./config/git_properties')
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {{ commitSHA: string | undefined, repositoryUrl: string | undefined }} GitMetadata
|
|
17
|
+
* @type {{ enabled?: GitMetadata, disabled?: GitMetadata }}
|
|
18
|
+
*/
|
|
19
|
+
const cache = {}
|
|
17
20
|
|
|
18
21
|
/**
|
|
19
22
|
* @param {import('./config/config-types').ConfigProperties} config
|
|
20
23
|
*/
|
|
21
24
|
function getGitMetadata (config) {
|
|
22
|
-
if (cached) return cached
|
|
23
|
-
|
|
24
25
|
if (!config.DD_TRACE_GIT_METADATA_ENABLED) {
|
|
25
|
-
|
|
26
|
-
return
|
|
26
|
+
cache.disabled ??= { commitSHA: undefined, repositoryUrl: undefined }
|
|
27
|
+
return cache.disabled
|
|
27
28
|
}
|
|
29
|
+
if (cache.enabled) return cache.enabled
|
|
28
30
|
|
|
29
31
|
let repositoryUrl = removeUserSensitiveInfo(config.DD_GIT_REPOSITORY_URL ?? config.tags[GIT_REPOSITORY_URL])
|
|
30
32
|
let commitSHA = config.DD_GIT_COMMIT_SHA ?? config.tags[GIT_COMMIT_SHA]
|
|
@@ -59,8 +61,8 @@ function getGitMetadata (config) {
|
|
|
59
61
|
|
|
60
62
|
commitSHA ??= resolveGitHeadSHA(gitFolderPath)
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
return
|
|
64
|
+
cache.enabled = { commitSHA, repositoryUrl }
|
|
65
|
+
return cache.enabled
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
module.exports = getGitMetadata
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* Modifications copyright 2022 Datadog, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Some functions are part of aws-lambda-nodejs-runtime-interface-client
|
|
6
|
+
* https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/v2.1.0/src/utils/UserFunction.ts
|
|
7
|
+
*/
|
|
8
|
+
'use strict'
|
|
9
|
+
|
|
10
|
+
const path = require('path')
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Example: `'./api/src/index.nested.handler'` → `['./api/src/', 'index.nested.handler']`.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} fullHandler
|
|
16
|
+
*/
|
|
17
|
+
function extractModuleRootAndHandler (fullHandler) {
|
|
18
|
+
const handlerString = path.basename(fullHandler)
|
|
19
|
+
const moduleRoot = fullHandler.slice(0, Math.max(0, fullHandler.indexOf(handlerString)))
|
|
20
|
+
return [moduleRoot, handlerString]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Example: `'index.nested.handler'` → `['index', 'nested.handler']`.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} handler
|
|
27
|
+
* @throws {Error} When the handler is not of the form `<module>.<path>`.
|
|
28
|
+
*/
|
|
29
|
+
function extractModuleNameAndHandlerPath (handler) {
|
|
30
|
+
const match = handler.match(/^([^.]*)\.(.*)$/)
|
|
31
|
+
if (!match || match.length !== 3) {
|
|
32
|
+
throw new Error(`Malformed handler name: ${handler}`)
|
|
33
|
+
}
|
|
34
|
+
return [match[1], match[2]]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} lambdaStylePath `LAMBDA_TASK_ROOT` joined with the module root and module name.
|
|
39
|
+
*/
|
|
40
|
+
function getLambdaFilePaths (lambdaStylePath) {
|
|
41
|
+
return [
|
|
42
|
+
`${lambdaStylePath}.js`,
|
|
43
|
+
`${lambdaStylePath}.mjs`,
|
|
44
|
+
`${lambdaStylePath}.cjs`,
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
extractModuleRootAndHandler,
|
|
50
|
+
extractModuleNameAndHandlerPath,
|
|
51
|
+
getLambdaFilePaths,
|
|
52
|
+
}
|
|
@@ -1,17 +1,65 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
const log = require('../log')
|
|
6
|
+
const { getEnvironmentVariable, getValueFromEnvSources } = require('../config/helper')
|
|
7
|
+
const Hook = require('../../../datadog-instrumentations/src/helpers/hook')
|
|
8
|
+
const instrumentations = require('../../../datadog-instrumentations/src/helpers/instrumentations')
|
|
9
|
+
const {
|
|
10
|
+
filename,
|
|
11
|
+
pathSepExpr,
|
|
12
|
+
} = require('../../../datadog-instrumentations/src/helpers/register')
|
|
13
|
+
const {
|
|
14
|
+
extractModuleNameAndHandlerPath,
|
|
15
|
+
extractModuleRootAndHandler,
|
|
16
|
+
getLambdaFilePaths,
|
|
17
|
+
} = require('./handler-paths')
|
|
18
|
+
|
|
19
|
+
if (!getValueFromEnvSources('DD_TRACE_DISABLED_INSTRUMENTATIONS')?.split(',').includes('lambda')) {
|
|
20
|
+
const lambdaTaskRoot = getEnvironmentVariable('LAMBDA_TASK_ROOT')
|
|
21
|
+
const originalLambdaHandler = getValueFromEnvSources('DD_LAMBDA_HANDLER')
|
|
22
|
+
|
|
23
|
+
if (originalLambdaHandler !== undefined && lambdaTaskRoot !== undefined) {
|
|
24
|
+
const [moduleRoot, moduleAndHandler] = extractModuleRootAndHandler(originalLambdaHandler)
|
|
25
|
+
const [moduleName] = extractModuleNameAndHandlerPath(moduleAndHandler)
|
|
26
|
+
|
|
27
|
+
const lambdaStylePath = path.resolve(lambdaTaskRoot, moduleRoot, moduleName)
|
|
28
|
+
const lambdaFilePaths = getLambdaFilePaths(lambdaStylePath)
|
|
29
|
+
|
|
30
|
+
// TODO: Redo this like any other instrumentation.
|
|
31
|
+
Hook(lambdaFilePaths, (moduleExports, name, _, moduleVersion) => {
|
|
32
|
+
require('./runtime/patch')
|
|
33
|
+
|
|
34
|
+
for (const { hook } of instrumentations[name]) {
|
|
35
|
+
try {
|
|
36
|
+
moduleExports = hook(moduleExports, moduleVersion) ?? moduleExports
|
|
37
|
+
} catch (error) {
|
|
38
|
+
log.error('Error executing lambda hook', error)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return moduleExports
|
|
43
|
+
})
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const moduleToPatch = 'datadog-lambda-js'
|
|
48
|
+
Hook([moduleToPatch], (moduleExports, moduleName, _, moduleVersion) => {
|
|
49
|
+
moduleName = moduleName.replace(pathSepExpr, '/')
|
|
50
|
+
require('./runtime/patch')
|
|
51
|
+
|
|
52
|
+
for (const { file, hook } of instrumentations[moduleToPatch]) {
|
|
53
|
+
const fullFilename = filename(moduleToPatch, file)
|
|
54
|
+
if (moduleName === fullFilename) {
|
|
55
|
+
try {
|
|
56
|
+
moduleExports = hook(moduleExports, moduleVersion) ?? moduleExports
|
|
57
|
+
} catch (error) {
|
|
58
|
+
log.error('Error executing lambda hook for datadog-lambda-js', error)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return moduleExports
|
|
64
|
+
})
|
|
17
65
|
}
|
|
@@ -6,54 +6,32 @@ const { datadog } = require('../handler')
|
|
|
6
6
|
const { addHook } = require('../../../../datadog-instrumentations/src/helpers/instrument')
|
|
7
7
|
const shimmer = require('../../../../datadog-shimmer')
|
|
8
8
|
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../config/helper')
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* `datadog-lambda-js` patched.
|
|
18
|
-
*/
|
|
19
|
-
const patchDatadogLambdaModule = (datadogLambdaModule) => {
|
|
9
|
+
const {
|
|
10
|
+
extractModuleNameAndHandlerPath,
|
|
11
|
+
extractModuleRootAndHandler,
|
|
12
|
+
getLambdaFilePaths,
|
|
13
|
+
} = require('../handler-paths')
|
|
14
|
+
|
|
15
|
+
/** @param {object} datadogLambdaModule */
|
|
16
|
+
function patchDatadogLambdaModule (datadogLambdaModule) {
|
|
20
17
|
shimmer.wrap(datadogLambdaModule, 'datadog', patchDatadogLambdaHandler)
|
|
21
|
-
|
|
22
18
|
return datadogLambdaModule
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
/**
|
|
26
|
-
* Patches a Datadog Lambda handler in order to do
|
|
27
|
-
* Datadog instrumentation by getting the Lambda handler from its
|
|
28
|
-
* arguments.
|
|
29
|
-
*
|
|
30
|
-
* @param {Function} datadogHandler the Datadog Lambda handler to destructure.
|
|
31
|
-
* @returns the datadogHandler with its arguments patched.
|
|
32
|
-
*/
|
|
21
|
+
/** @param {Function} datadogHandler */
|
|
33
22
|
function patchDatadogLambdaHandler (datadogHandler) {
|
|
34
|
-
return
|
|
35
|
-
return datadogHandler(datadog(userHandler))
|
|
36
|
-
}
|
|
23
|
+
return userHandler => datadogHandler(datadog(userHandler))
|
|
37
24
|
}
|
|
38
25
|
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const patchLambdaModule = (handlerPath) => (lambdaModule) => {
|
|
46
|
-
shimmer.wrap(lambdaModule, handlerPath, patchLambdaHandler)
|
|
47
|
-
|
|
48
|
-
return lambdaModule
|
|
26
|
+
/** @param {string} handlerPath */
|
|
27
|
+
function patchLambdaModule (handlerPath) {
|
|
28
|
+
return lambdaModule => {
|
|
29
|
+
shimmer.wrap(lambdaModule, handlerPath, patchLambdaHandler)
|
|
30
|
+
return lambdaModule
|
|
31
|
+
}
|
|
49
32
|
}
|
|
50
33
|
|
|
51
|
-
/**
|
|
52
|
-
* Patches a Lambda handler in order to do Datadog instrumentation.
|
|
53
|
-
*
|
|
54
|
-
* @param {Function} lambdaHandler the Lambda handler to be patched.
|
|
55
|
-
* @returns a function which patches the given Lambda handler.
|
|
56
|
-
*/
|
|
34
|
+
/** @param {Function} lambdaHandler */
|
|
57
35
|
function patchLambdaHandler (lambdaHandler) {
|
|
58
36
|
return datadog(lambdaHandler)
|
|
59
37
|
}
|
|
@@ -62,16 +40,13 @@ const lambdaTaskRoot = getEnvironmentVariable('LAMBDA_TASK_ROOT')
|
|
|
62
40
|
const originalLambdaHandler = getValueFromEnvSources('DD_LAMBDA_HANDLER')
|
|
63
41
|
|
|
64
42
|
if (originalLambdaHandler === undefined) {
|
|
65
|
-
// Instrumentation is done manually.
|
|
66
43
|
addHook({ name: 'datadog-lambda-js' }, patchDatadogLambdaModule)
|
|
67
44
|
} else {
|
|
68
|
-
const [moduleRoot, moduleAndHandler] =
|
|
69
|
-
const [
|
|
70
|
-
|
|
71
|
-
const lambdaStylePath = path.resolve(lambdaTaskRoot, moduleRoot, _module)
|
|
72
|
-
const lambdaFilePaths = _getLambdaFilePaths(lambdaStylePath)
|
|
45
|
+
const [moduleRoot, moduleAndHandler] = extractModuleRootAndHandler(originalLambdaHandler)
|
|
46
|
+
const [moduleName, handlerPath] = extractModuleNameAndHandlerPath(moduleAndHandler)
|
|
73
47
|
|
|
74
|
-
|
|
48
|
+
const lambdaStylePath = path.resolve(lambdaTaskRoot, moduleRoot, moduleName)
|
|
49
|
+
for (const lambdaFilePath of getLambdaFilePaths(lambdaStylePath)) {
|
|
75
50
|
addHook({ name: lambdaFilePath }, patchLambdaModule(handlerPath))
|
|
76
51
|
}
|
|
77
52
|
}
|
|
@@ -108,6 +108,10 @@ function disable () {
|
|
|
108
108
|
// since LLMObs traces can extend between services and be the same trace,
|
|
109
109
|
// we need to propagate the parent id and mlApp.
|
|
110
110
|
function handleLLMObsParentIdInjection ({ carrier }) {
|
|
111
|
+
// Respect the standard propagator's gate: when trace tag propagation is
|
|
112
|
+
// disabled, don't write `x-datadog-tags` for LLMObs either.
|
|
113
|
+
if (globalTracerConfig.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) return
|
|
114
|
+
|
|
111
115
|
const parent = storage.getStore()?.span
|
|
112
116
|
const mlObsSpanTags = LLMObsTagger.tagMap.get(parent)
|
|
113
117
|
|
|
@@ -118,8 +122,15 @@ function handleLLMObsParentIdInjection ({ carrier }) {
|
|
|
118
122
|
parentContext?._trace?.tags?.[PROPAGATED_ML_APP_KEY] ||
|
|
119
123
|
globalTracerConfig.llmobs.mlApp
|
|
120
124
|
|
|
121
|
-
if (parentId
|
|
122
|
-
|
|
125
|
+
if (!parentId && !mlApp) return
|
|
126
|
+
|
|
127
|
+
// `_injectTags` only writes `x-datadog-tags` when the trace has `_dd.p.*`
|
|
128
|
+
// tags, so it may be undefined here — coalesce before appending.
|
|
129
|
+
const existing = carrier['x-datadog-tags']
|
|
130
|
+
let tags = existing || ''
|
|
131
|
+
if (parentId) tags += `${tags ? ',' : ''}${PROPAGATED_PARENT_ID_KEY}=${parentId}`
|
|
132
|
+
if (mlApp) tags += `${tags ? ',' : ''}${PROPAGATED_ML_APP_KEY}=${mlApp}`
|
|
133
|
+
if (tags !== existing) carrier['x-datadog-tags'] = tags
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
function handleFlush () {
|
|
@@ -41,8 +41,7 @@ const VERCEL_AI_GENERATION_METADATA_PREFIX = 'ai.settings.'
|
|
|
41
41
|
*/
|
|
42
42
|
function getSpanTags (ctx) {
|
|
43
43
|
const span = ctx.currentStore?.span
|
|
44
|
-
|
|
45
|
-
return /** @type {SpanTags} */ (carrier)
|
|
44
|
+
return /** @type {SpanTags} */ (ctx.attributes ?? span?.context()._tags ?? {})
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
/**
|
|
@@ -14,7 +14,17 @@ const llmobsStore = storage('llmobs')
|
|
|
14
14
|
|
|
15
15
|
const ENABLED_OPERATIONS = new Set(['invokeModel', 'invokeModelWithResponseStream'])
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {{
|
|
19
|
+
* inputTokensFromHeaders?: number,
|
|
20
|
+
* outputTokensFromHeaders?: number,
|
|
21
|
+
* cacheReadTokensFromHeaders?: number,
|
|
22
|
+
* cacheWriteTokensFromHeaders?: number,
|
|
23
|
+
* }} HeaderTokens
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** @type {Map<string, HeaderTokens>} */
|
|
27
|
+
const pendingTokenHeaders = new Map()
|
|
18
28
|
|
|
19
29
|
class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
20
30
|
constructor () {
|
|
@@ -24,33 +34,39 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
|
24
34
|
const { response } = ctx
|
|
25
35
|
const request = response.request
|
|
26
36
|
const operation = request.operation
|
|
37
|
+
|
|
38
|
+
// Release the cached headers even for operations the plugin does not tag,
|
|
39
|
+
// so non-LLM Bedrock calls do not leak entries into pendingTokenHeaders.
|
|
40
|
+
const tokensFromHeaders = consumeTokenHeaders(response.$metadata?.requestId)
|
|
41
|
+
|
|
27
42
|
// avoids instrumenting other non supported runtime operations
|
|
28
|
-
if (!ENABLED_OPERATIONS.has(operation))
|
|
29
|
-
|
|
30
|
-
}
|
|
43
|
+
if (!ENABLED_OPERATIONS.has(operation)) return
|
|
44
|
+
|
|
31
45
|
const { modelProvider, modelName } = parseModelId(request.params.modelId)
|
|
32
46
|
|
|
33
47
|
// avoids instrumenting non llm type
|
|
34
|
-
if (modelName.includes('embed'))
|
|
35
|
-
|
|
36
|
-
}
|
|
48
|
+
if (modelName.includes('embed')) return
|
|
49
|
+
|
|
37
50
|
const span = ctx.currentStore?.span
|
|
38
|
-
this.setLLMObsTags({ ctx, request, span, response, modelProvider, modelName })
|
|
51
|
+
this.setLLMObsTags({ ctx, request, span, response, modelProvider, modelName, tokensFromHeaders })
|
|
39
52
|
})
|
|
40
53
|
|
|
41
54
|
this.addSub('apm:aws:response:deserialize:bedrockruntime', ({ headers }) => {
|
|
42
55
|
const requestId = headers['x-amzn-requestid']
|
|
56
|
+
// No request id means no way to correlate with the :complete: event.
|
|
57
|
+
if (!requestId) return
|
|
58
|
+
|
|
43
59
|
const inputTokenCount = headers['x-amzn-bedrock-input-token-count']
|
|
44
60
|
const outputTokenCount = headers['x-amzn-bedrock-output-token-count']
|
|
45
61
|
const cacheReadTokenCount = headers['x-amzn-bedrock-cache-read-input-token-count']
|
|
46
62
|
const cacheWriteTokenCount = headers['x-amzn-bedrock-cache-write-input-token-count']
|
|
47
63
|
|
|
48
|
-
|
|
64
|
+
pendingTokenHeaders.set(requestId, {
|
|
49
65
|
inputTokensFromHeaders: inputTokenCount && Number.parseInt(inputTokenCount),
|
|
50
66
|
outputTokensFromHeaders: outputTokenCount && Number.parseInt(outputTokenCount),
|
|
51
67
|
cacheReadTokensFromHeaders: cacheReadTokenCount && Number.parseInt(cacheReadTokenCount),
|
|
52
68
|
cacheWriteTokensFromHeaders: cacheWriteTokenCount && Number.parseInt(cacheWriteTokenCount),
|
|
53
|
-
}
|
|
69
|
+
})
|
|
54
70
|
})
|
|
55
71
|
|
|
56
72
|
this.addSub('apm:aws:response:streamed-chunk:bedrockruntime', ({ ctx, chunk }) => {
|
|
@@ -60,7 +76,7 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
|
60
76
|
})
|
|
61
77
|
}
|
|
62
78
|
|
|
63
|
-
setLLMObsTags ({ ctx, request, span, response, modelProvider, modelName }) {
|
|
79
|
+
setLLMObsTags ({ ctx, request, span, response, modelProvider, modelName, tokensFromHeaders }) {
|
|
64
80
|
const isStream = request?.operation?.toLowerCase().includes('stream')
|
|
65
81
|
telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: true, integration: 'bedrock' })
|
|
66
82
|
|
|
@@ -97,7 +113,7 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
|
97
113
|
|
|
98
114
|
// add token metrics
|
|
99
115
|
const { inputTokens, outputTokens, totalTokens, cacheReadTokens, cacheWriteTokens } = extractTokens({
|
|
100
|
-
|
|
116
|
+
tokensFromHeaders,
|
|
101
117
|
usage: textAndResponseReason.usage,
|
|
102
118
|
})
|
|
103
119
|
this._tagger.tagMetrics(span, {
|
|
@@ -110,14 +126,28 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
|
110
126
|
}
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
|
|
129
|
+
/**
|
|
130
|
+
* @param {string | undefined} requestId
|
|
131
|
+
* @returns {HeaderTokens | undefined}
|
|
132
|
+
*/
|
|
133
|
+
function consumeTokenHeaders (requestId) {
|
|
134
|
+
const tokens = pendingTokenHeaders.get(requestId)
|
|
135
|
+
pendingTokenHeaders.delete(requestId)
|
|
136
|
+
return tokens
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Combine response-body usage with header-derived counts, preferring the body.
|
|
141
|
+
*
|
|
142
|
+
* @param {{ tokensFromHeaders: HeaderTokens | undefined, usage: Record<string, number | undefined> }} options
|
|
143
|
+
*/
|
|
144
|
+
function extractTokens ({ tokensFromHeaders, usage }) {
|
|
114
145
|
const {
|
|
115
146
|
inputTokensFromHeaders,
|
|
116
147
|
outputTokensFromHeaders,
|
|
117
148
|
cacheReadTokensFromHeaders,
|
|
118
149
|
cacheWriteTokensFromHeaders,
|
|
119
|
-
} =
|
|
120
|
-
delete requestIdsToTokens[requestId]
|
|
150
|
+
} = tokensFromHeaders ?? {}
|
|
121
151
|
|
|
122
152
|
const inputTokens = usage.inputTokens || inputTokensFromHeaders || 0
|
|
123
153
|
const outputTokens = usage.outputTokens || outputTokensFromHeaders || 0
|