dd-trace 5.102.0 → 5.104.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/index.d.ts +25 -3
- package/package.json +15 -13
- package/packages/datadog-esbuild/src/utils.js +2 -2
- package/packages/datadog-instrumentations/src/ai.js +1 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +2 -2
- package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -2
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +32 -15
- package/packages/datadog-instrumentations/src/couchbase.js +69 -220
- package/packages/datadog-instrumentations/src/cucumber.js +104 -31
- package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
- package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
- package/packages/datadog-instrumentations/src/electron.js +240 -0
- package/packages/datadog-instrumentations/src/fetch.js +5 -5
- package/packages/datadog-instrumentations/src/graphql.js +13 -17
- package/packages/datadog-instrumentations/src/grpc/client.js +48 -32
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +2 -2
- 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 +58 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +3 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +19 -5
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +14 -13
- package/packages/datadog-instrumentations/src/http/client.js +2 -2
- package/packages/datadog-instrumentations/src/ioredis.js +18 -14
- package/packages/datadog-instrumentations/src/jest.js +382 -84
- package/packages/datadog-instrumentations/src/kafkajs.js +184 -174
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/memcached.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +309 -56
- package/packages/datadog-instrumentations/src/mocha/utils.js +48 -8
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -9
- package/packages/datadog-instrumentations/src/mongoose.js +10 -12
- package/packages/datadog-instrumentations/src/mysql.js +2 -2
- package/packages/datadog-instrumentations/src/mysql2.js +1 -1
- package/packages/datadog-instrumentations/src/pg.js +25 -11
- package/packages/datadog-instrumentations/src/playwright.js +449 -60
- package/packages/datadog-instrumentations/src/redis.js +19 -10
- package/packages/datadog-instrumentations/src/router.js +4 -2
- package/packages/datadog-instrumentations/src/vitest.js +246 -149
- package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
- package/packages/datadog-plugin-aws-sdk/src/base.js +18 -24
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
- 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 +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
- package/packages/datadog-plugin-couchbase/src/index.js +58 -52
- package/packages/datadog-plugin-cucumber/src/index.js +1 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +239 -40
- package/packages/datadog-plugin-cypress/src/support.js +13 -1
- package/packages/datadog-plugin-elasticsearch/src/index.js +28 -8
- 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/producer.js +27 -18
- 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 +33 -1
- 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 +2 -2
- package/packages/datadog-plugin-jest/src/index.js +92 -50
- package/packages/datadog-plugin-kafkajs/src/producer.js +32 -0
- package/packages/datadog-plugin-mocha/src/index.js +1 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +70 -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-pg/src/index.js +3 -3
- package/packages/datadog-plugin-playwright/src/index.js +4 -0
- package/packages/datadog-plugin-redis/src/index.js +54 -24
- package/packages/datadog-plugin-undici/src/index.js +19 -0
- package/packages/datadog-plugin-vitest/src/index.js +19 -7
- package/packages/datadog-shimmer/src/shimmer.js +35 -0
- 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/blocking.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +10 -3
- package/packages/dd-trace/src/appsec/reporter.js +19 -5
- 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/ci-visibility/requests/request.js +3 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +5 -3
- package/packages/dd-trace/src/config/defaults.js +3 -14
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
- 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 +60 -38
- package/packages/dd-trace/src/crashtracking/crashtracker.js +15 -3
- package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
- package/packages/dd-trace/src/datastreams/context.js +4 -2
- package/packages/dd-trace/src/datastreams/manager.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
- 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 +45 -54
- package/packages/dd-trace/src/encode/0.5.js +34 -3
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +26 -19
- 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/agents.js +3 -1
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
- package/packages/dd-trace/src/exporters/common/request.js +4 -2
- 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/id.js +17 -4
- package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
- package/packages/dd-trace/src/lambda/handler.js +2 -4
- 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/bedrockruntime.js +45 -15
- package/packages/dd-trace/src/llmobs/sdk.js +10 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
- package/packages/dd-trace/src/log/writer.js +3 -1
- package/packages/dd-trace/src/noop/span.js +3 -1
- package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
- package/packages/dd-trace/src/openfeature/writers/exposures.js +51 -20
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
- package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
- package/packages/dd-trace/src/plugins/apollo.js +3 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +52 -17
- 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/log_plugin.js +3 -1
- package/packages/dd-trace/src/plugins/plugin.js +2 -4
- package/packages/dd-trace/src/plugins/tracing.js +5 -3
- package/packages/dd-trace/src/plugins/util/ci.js +8 -8
- package/packages/dd-trace/src/plugins/util/git-cache.js +20 -18
- package/packages/dd-trace/src/plugins/util/git.js +3 -1
- package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
- package/packages/dd-trace/src/plugins/util/test.js +119 -5
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +17 -15
- package/packages/dd-trace/src/plugins/util/web.js +11 -0
- 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/wall.js +1 -1
- 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/runtime_metrics.js +5 -8
- package/packages/dd-trace/src/scope.js +7 -5
- package/packages/dd-trace/src/serverless.js +5 -2
- package/packages/dd-trace/src/service-naming/extra-services.js +14 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +20 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +20 -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/lambda/runtime/ritm.js +0 -133
- package/vendor/dist/opentracing/LICENSE +0 -201
- package/vendor/dist/opentracing/binary_carrier.d.ts +0 -11
- package/vendor/dist/opentracing/constants.d.ts +0 -61
- package/vendor/dist/opentracing/examples/demo/demo.d.ts +0 -2
- package/vendor/dist/opentracing/ext/tags.d.ts +0 -90
- package/vendor/dist/opentracing/functions.d.ts +0 -20
- package/vendor/dist/opentracing/global_tracer.d.ts +0 -14
- package/vendor/dist/opentracing/index.d.ts +0 -12
- package/vendor/dist/opentracing/index.js +0 -1
- package/vendor/dist/opentracing/mock_tracer/index.d.ts +0 -5
- package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +0 -13
- package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +0 -16
- package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +0 -50
- package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +0 -26
- package/vendor/dist/opentracing/noop.d.ts +0 -8
- package/vendor/dist/opentracing/reference.d.ts +0 -33
- package/vendor/dist/opentracing/span.d.ts +0 -147
- package/vendor/dist/opentracing/span_context.d.ts +0 -26
- package/vendor/dist/opentracing/test/api_compatibility.d.ts +0 -16
- package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +0 -3
- package/vendor/dist/opentracing/test/noop_implementation.d.ts +0 -4
- package/vendor/dist/opentracing/test/opentracing_api.d.ts +0 -3
- package/vendor/dist/opentracing/test/unittest.d.ts +0 -2
- package/vendor/dist/opentracing/tracer.d.ts +0 -127
|
@@ -14,11 +14,14 @@ const finishChannel = channel('apm:grpc:client:request:finish')
|
|
|
14
14
|
const emitChannel = channel('apm:grpc:client:request:emit')
|
|
15
15
|
|
|
16
16
|
function createWrapMakeRequest (type, hasPeer = false) {
|
|
17
|
+
const metadataIndex = type === types.client_stream || type === types.bidi ? 3 : 4
|
|
18
|
+
|
|
17
19
|
return function wrapMakeRequest (makeRequest) {
|
|
18
20
|
return function (path) {
|
|
19
|
-
|
|
21
|
+
if (!startChannel.hasSubscribers) return makeRequest.apply(this, arguments)
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
const { metadata, args } = resolveMetadata(this, arguments, metadataIndex)
|
|
24
|
+
return callMethod(this, makeRequest, args, path, metadata, type, hasPeer)
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
}
|
|
@@ -82,9 +85,13 @@ function wrapMethod (method, path, type, hasPeer) {
|
|
|
82
85
|
return method
|
|
83
86
|
}
|
|
84
87
|
|
|
88
|
+
const metadataIndex = type === types.client_stream || type === types.bidi ? 0 : 1
|
|
89
|
+
|
|
85
90
|
const wrapped = shimmer.wrapFunction(method, method => function () {
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
if (!startChannel.hasSubscribers) return method.apply(this, arguments)
|
|
92
|
+
|
|
93
|
+
const { metadata, args } = resolveMetadata(this, arguments, metadataIndex)
|
|
94
|
+
return callMethod(this, method, args, path, metadata, type, hasPeer)
|
|
88
95
|
})
|
|
89
96
|
|
|
90
97
|
patched.add(wrapped)
|
|
@@ -140,24 +147,25 @@ function createWrapEmit (ctx, hasPeer = false) {
|
|
|
140
147
|
}
|
|
141
148
|
|
|
142
149
|
function callMethod (client, method, args, path, metadata, type, hasPeer = false) {
|
|
143
|
-
if (!startChannel.hasSubscribers) return method.apply(client, args)
|
|
144
|
-
|
|
145
|
-
const length = args.length
|
|
146
|
-
const callback = args[length - 1]
|
|
147
|
-
|
|
148
150
|
const ctx = { metadata, path, type }
|
|
149
151
|
|
|
150
152
|
return startChannel.runStores(ctx, () => {
|
|
151
153
|
try {
|
|
154
|
+
let callArgs = args
|
|
155
|
+
|
|
152
156
|
if (type === types.unary || type === types.client_stream) {
|
|
157
|
+
if (!Array.isArray(callArgs)) callArgs = [...callArgs]
|
|
158
|
+
|
|
159
|
+
const length = callArgs.length
|
|
160
|
+
const callback = callArgs[length - 1]
|
|
153
161
|
if (typeof callback === 'function') {
|
|
154
|
-
|
|
162
|
+
callArgs[length - 1] = wrapCallback(ctx, callback)
|
|
155
163
|
} else {
|
|
156
|
-
|
|
164
|
+
callArgs[length] = wrapCallback(ctx)
|
|
157
165
|
}
|
|
158
166
|
}
|
|
159
167
|
|
|
160
|
-
const call = method.apply(client,
|
|
168
|
+
const call = method.apply(client, callArgs)
|
|
161
169
|
|
|
162
170
|
if (call && typeof call.emit === 'function') {
|
|
163
171
|
shimmer.wrap(call, 'emit', createWrapEmit(ctx, hasPeer))
|
|
@@ -167,36 +175,44 @@ function callMethod (client, method, args, path, metadata, type, hasPeer = false
|
|
|
167
175
|
} catch (e) {
|
|
168
176
|
ctx.error = e
|
|
169
177
|
errorChannel.publish(ctx)
|
|
178
|
+
throw e
|
|
170
179
|
}
|
|
171
180
|
// No end channel needed
|
|
172
181
|
})
|
|
173
182
|
}
|
|
174
183
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Returns the `Metadata` for a gRPC client invocation, splicing or replacing
|
|
186
|
+
* one at `index` when the user did not pass their own.
|
|
187
|
+
*
|
|
188
|
+
* @param {object} client
|
|
189
|
+
* @param {ArrayLike<unknown>} args
|
|
190
|
+
* @param {number} index
|
|
191
|
+
* @returns {{ metadata: object | undefined, args: ArrayLike<unknown> }}
|
|
192
|
+
*/
|
|
193
|
+
function resolveMetadata (client, args, index) {
|
|
194
|
+
const grpc = client && getGrpc(client)
|
|
195
|
+
if (!grpc) return { metadata: undefined, args }
|
|
196
|
+
|
|
197
|
+
const slot = args[index]
|
|
198
|
+
|
|
199
|
+
if (slot instanceof grpc.Metadata || slot?.constructor?.name === 'Metadata') {
|
|
200
|
+
return { metadata: slot, args }
|
|
185
201
|
}
|
|
186
202
|
|
|
187
|
-
|
|
188
|
-
normalized.push(new grpc.Metadata())
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (meta) {
|
|
192
|
-
normalized.push(meta)
|
|
193
|
-
}
|
|
203
|
+
const metadata = new grpc.Metadata()
|
|
194
204
|
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
if (slot == null) {
|
|
206
|
+
const out = [...args]
|
|
207
|
+
out[index] = metadata
|
|
208
|
+
return { metadata, args: out }
|
|
197
209
|
}
|
|
198
210
|
|
|
199
|
-
|
|
211
|
+
const out = new Array(args.length + 1)
|
|
212
|
+
for (let i = 0; i < index; i++) out[i] = args[i]
|
|
213
|
+
out[index] = metadata
|
|
214
|
+
for (let i = index; i < args.length; i++) out[i + 1] = args[i]
|
|
215
|
+
return { metadata, args: out }
|
|
200
216
|
}
|
|
201
217
|
|
|
202
218
|
function getType (definition) {
|
|
@@ -19,7 +19,7 @@ const { channel } = require('./instrument')
|
|
|
19
19
|
*
|
|
20
20
|
* @param {string} prefix
|
|
21
21
|
* @param {object} [options]
|
|
22
|
-
* @param {boolean} [options.captureResult
|
|
22
|
+
* @param {boolean} [options.captureResult] set `ctx.result` to the callback's first
|
|
23
23
|
* non-error argument before publishing `:finish`. Plugins that tag spans from the call's
|
|
24
24
|
* return value (e.g. the DNS lookup plugin) rely on this.
|
|
25
25
|
* @returns {(buildContext: (thisArg: unknown, args: IArguments) => object | undefined) =>
|
|
@@ -45,7 +45,7 @@ function createCallbackInstrumentor (prefix, { captureResult = false } = {}) {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
return startCh.runStores(ctx, () => {
|
|
48
|
-
args[lastIndex] = shimmer.
|
|
48
|
+
args[lastIndex] = shimmer.wrapCallback(cb, cb => function (error, ...rest) {
|
|
49
49
|
if (error) {
|
|
50
50
|
ctx.error = error
|
|
51
51
|
errorCh.publish(ctx)
|
|
@@ -16,7 +16,10 @@ function getVersion (moduleBaseDir) {
|
|
|
16
16
|
return requirePackageJson(moduleBaseDir, /** @type {import('module').Module} */ (module)).version
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// In a packaged Electron binary, built-in modules (like 'electron', 'electron/main') have no
|
|
20
|
+
// moduleBaseDir. Use the Electron version for version checks when available, otherwise fall back
|
|
21
|
+
// to the Node.js version.
|
|
22
|
+
return process.versions?.electron ?? process.version
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
/**
|
|
@@ -68,6 +68,7 @@ module.exports = {
|
|
|
68
68
|
cypress: () => require('../cypress'),
|
|
69
69
|
'dd-trace-api': () => require('../dd-trace-api'),
|
|
70
70
|
elasticsearch: () => require('../elasticsearch'),
|
|
71
|
+
electron: () => require('../electron'),
|
|
71
72
|
express: () => require('../express'),
|
|
72
73
|
'express-mongo-sanitize': () => require('../express-mongo-sanitize'),
|
|
73
74
|
'express-session': () => require('../express-session'),
|
|
@@ -55,9 +55,9 @@ exports.getHooks = function getHooks (names) {
|
|
|
55
55
|
* @param {object} args
|
|
56
56
|
* @param {string} args.name module name
|
|
57
57
|
* @param {string[]} [args.versions] array of semver range strings
|
|
58
|
-
* @param {string} [args.file
|
|
58
|
+
* @param {string} [args.file] path to file within package to instrument. Defaults to 'index.js'.
|
|
59
59
|
* @param {string} [args.filePattern] pattern to match files within package to instrument
|
|
60
|
-
* @param {boolean} [args.patchDefault
|
|
60
|
+
* @param {boolean} [args.patchDefault] whether to patch the default export. Defaults to true.
|
|
61
61
|
* @param {(moduleExports: unknown, version: string, isIitm?: boolean) => unknown} [hook] Patches module exports
|
|
62
62
|
*/
|
|
63
63
|
exports.addHook = function addHook ({ name, versions, file, filePattern, patchDefault }, hook) {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Produce API key 0; v0–v2 use the legacy MessageSet format with no header
|
|
4
|
+
// field, so trace headers can only be carried on v3+ (Kafka >=0.11).
|
|
5
|
+
const PRODUCE_API_KEY = 0
|
|
6
|
+
const PRODUCE_VERSION_WITH_HEADERS = 3
|
|
7
|
+
|
|
8
|
+
// Side-table mapping a kafkajs producer/consumer to the cluster captured at
|
|
9
|
+
// creation time. The boundary uses it to read `cluster.brokerPool` lazily on
|
|
10
|
+
// first send/consume instead of opening a parallel admin connection. A
|
|
11
|
+
// WeakMap keeps the kafkajs object itself untouched: no Symbol-keyed
|
|
12
|
+
// property to leak through `Reflect.ownKeys`, no string-keyed underscore for
|
|
13
|
+
// user serializers to pick up, and the entry drops as soon as the producer
|
|
14
|
+
// is GC'd.
|
|
15
|
+
const clientToCluster = new WeakMap()
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Shallow-clone each message and its headers so the boundary, kafkajs, and
|
|
19
|
+
* the user never share the same nested objects. With `ensureHeaders` true
|
|
20
|
+
* (header injection enabled) messages without `headers` get an empty object
|
|
21
|
+
* the producer plugin can inject into; with it false (broker rejected
|
|
22
|
+
* headers) the absence of `headers` is preserved so brokers that fail on any
|
|
23
|
+
* header field can recover.
|
|
24
|
+
*
|
|
25
|
+
* @param {Array<unknown>} messages
|
|
26
|
+
* @param {boolean} ensureHeaders
|
|
27
|
+
*/
|
|
28
|
+
function cloneMessages (messages, ensureHeaders) {
|
|
29
|
+
const result = new Array(messages.length)
|
|
30
|
+
for (let i = 0; i < messages.length; i++) {
|
|
31
|
+
const message = messages[i]
|
|
32
|
+
if (message === null || typeof message !== 'object') {
|
|
33
|
+
result[i] = message
|
|
34
|
+
} else if (message.headers) {
|
|
35
|
+
result[i] = { ...message, headers: { ...message.headers } }
|
|
36
|
+
} else {
|
|
37
|
+
result[i] = ensureHeaders ? { ...message, headers: {} } : { ...message }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {{ versions?: Record<number, { minVersion: number, maxVersion: number }> } | undefined} brokerPool
|
|
45
|
+
* kafkajs's `cluster.brokerPool`. `versions` is populated once the seed
|
|
46
|
+
* broker handshakes; before that, the answer is unknown and we return
|
|
47
|
+
* `true` so the caller defaults to injection.
|
|
48
|
+
*/
|
|
49
|
+
function brokerSupportsMessageHeaders (brokerPool) {
|
|
50
|
+
const produce = brokerPool?.versions?.[PRODUCE_API_KEY]
|
|
51
|
+
return !produce || produce.maxVersion >= PRODUCE_VERSION_WITH_HEADERS
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
brokerSupportsMessageHeaders,
|
|
56
|
+
clientToCluster,
|
|
57
|
+
cloneMessages,
|
|
58
|
+
}
|
|
@@ -19,9 +19,10 @@ const compiler = {
|
|
|
19
19
|
// TODO: Figure out ESBuild `createRequire` issue and remove this hack.
|
|
20
20
|
const oxc = runtimeRequire(['oxc', 'parser'].join('-'))
|
|
21
21
|
|
|
22
|
-
compiler.parse = (sourceText,
|
|
22
|
+
compiler.parse = (sourceText, { range, isModule } = {}) => {
|
|
23
23
|
const { program, errors } = oxc.parseSync('index.js', sourceText, {
|
|
24
|
-
|
|
24
|
+
range,
|
|
25
|
+
sourceType: isModule ? 'module' : 'script',
|
|
25
26
|
preserveParens: false,
|
|
26
27
|
})
|
|
27
28
|
|
|
@@ -2,15 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
const { readFileSync } = require('fs')
|
|
4
4
|
const { join } = require('path')
|
|
5
|
+
const { pathToFileURL } = require('url')
|
|
5
6
|
const log = require('../../../../dd-trace/src/log')
|
|
6
7
|
const { create } = require('../../../../../vendor/dist/@apm-js-collab/code-transformer')
|
|
7
8
|
const { traceAsyncIterator, traceIterator } = require('./transforms')
|
|
8
9
|
const instrumentations = require('./instrumentations')
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
// `dc-polyfill` is referenced from injected `require()` (CJS) and `import`
|
|
12
|
+
// (ESM) statements that the transformer splices into the rewritten module.
|
|
13
|
+
// `require()` accepts an absolute filesystem path; the ESM resolver rejects it
|
|
14
|
+
// with `ERR_INVALID_MODULE_SPECIFIER` and needs a `file://` URL instead. We
|
|
15
|
+
// pre-compute both forms here so each matcher hands the transformer a
|
|
16
|
+
// specifier that is valid for the module type it is rewriting.
|
|
17
|
+
let dcPolyfillCjs
|
|
18
|
+
let dcPolyfillEsm
|
|
11
19
|
|
|
12
20
|
try {
|
|
13
|
-
|
|
21
|
+
const resolved = require.resolve('dc-polyfill')
|
|
22
|
+
dcPolyfillCjs = resolved.replaceAll('\\', '/')
|
|
23
|
+
dcPolyfillEsm = pathToFileURL(resolved).href
|
|
14
24
|
} catch {
|
|
15
25
|
// The `dc-polyfill` module is unavailable for some reason (like bundling).
|
|
16
26
|
// Let's just keep the default of using `diagnostics-channel` as a fallback
|
|
@@ -20,10 +30,13 @@ try {
|
|
|
20
30
|
/** @type {Record<string, string>} map of module base name to version */
|
|
21
31
|
const moduleVersions = {}
|
|
22
32
|
const disabled = new Set()
|
|
23
|
-
const
|
|
33
|
+
const matcherCjs = create(instrumentations, dcPolyfillCjs)
|
|
34
|
+
const matcherEsm = create(instrumentations, dcPolyfillEsm)
|
|
24
35
|
|
|
25
|
-
matcher
|
|
26
|
-
matcher.addTransform('
|
|
36
|
+
for (const matcher of [matcherCjs, matcherEsm]) {
|
|
37
|
+
matcher.addTransform('traceIterator', traceIterator)
|
|
38
|
+
matcher.addTransform('traceAsyncIterator', traceAsyncIterator)
|
|
39
|
+
}
|
|
27
40
|
|
|
28
41
|
function rewrite (content, filename, format) {
|
|
29
42
|
if (!content) return content
|
|
@@ -41,6 +54,7 @@ function rewrite (content, filename, format) {
|
|
|
41
54
|
|
|
42
55
|
if (disabled.has(moduleName)) return content
|
|
43
56
|
|
|
57
|
+
const matcher = moduleType === 'esm' ? matcherEsm : matcherCjs
|
|
44
58
|
const transformer = matcher.getTransformer(moduleName, version, filePath)
|
|
45
59
|
|
|
46
60
|
if (!transformer) return content
|
|
@@ -10,17 +10,25 @@ const tracingChannelPredicate = (node) => (
|
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
const transforms = module.exports = {
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @param {{ dcModule: string, moduleType: 'esm' | 'cjs' }} state
|
|
15
|
+
* @param {import('estree').Program} node
|
|
16
|
+
*/
|
|
17
|
+
tracingChannelImport ({ dcModule, moduleType }, node) {
|
|
14
18
|
if (node.body.some(tracingChannelPredicate)) return
|
|
15
19
|
|
|
20
|
+
// The vendored matcher state exposes `moduleType` (`esm` / `cjs`), so we
|
|
21
|
+
// read that field directly. Naming it `sourceType` here used to silently
|
|
22
|
+
// pick the CJS branch for every ESM file, leaving `require()` baked into
|
|
23
|
+
// pure ESM modules like `@langchain/langgraph/dist/pregel/index.js`.
|
|
24
|
+
const isModule = moduleType === 'esm'
|
|
25
|
+
|
|
16
26
|
const index = node.body.findIndex(child => child.directive === 'use strict')
|
|
17
|
-
const code =
|
|
18
|
-
? `import
|
|
27
|
+
const code = isModule
|
|
28
|
+
? `import tr_ch_apm_dc from "${dcModule}"; const {tracingChannel: tr_ch_apm_tracingChannel} = tr_ch_apm_dc`
|
|
19
29
|
: `const {tracingChannel: tr_ch_apm_tracingChannel} = require("${dcModule}")`
|
|
20
30
|
|
|
21
|
-
node.body.splice(index + 1, 0, parse(code, {
|
|
22
|
-
isModule: isModuleSourceType(sourceType),
|
|
23
|
-
}).body[0])
|
|
31
|
+
node.body.splice(index + 1, 0, ...parse(code, { isModule }).body)
|
|
24
32
|
},
|
|
25
33
|
|
|
26
34
|
tracingChannelDeclaration (state, node) {
|
|
@@ -53,13 +61,6 @@ function traceAny (state, node, _parent, ancestry) {
|
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
/**
|
|
57
|
-
* @param {string} sourceType
|
|
58
|
-
*/
|
|
59
|
-
function isModuleSourceType (sourceType) {
|
|
60
|
-
return sourceType === 'module' || sourceType === 'esm'
|
|
61
|
-
}
|
|
62
|
-
|
|
63
64
|
function traceFunction (state, node, program) {
|
|
64
65
|
transforms.tracingChannelDeclaration(state, program)
|
|
65
66
|
|
|
@@ -188,8 +188,8 @@ function patch (http, methodName) {
|
|
|
188
188
|
let finished = false
|
|
189
189
|
let callback = args.callback
|
|
190
190
|
|
|
191
|
-
if (callback) {
|
|
192
|
-
callback = shimmer.
|
|
191
|
+
if (typeof callback === 'function') {
|
|
192
|
+
callback = shimmer.wrapCallback(args.callback, cb => function (...args) {
|
|
193
193
|
return asyncStartChannel.runStores(ctx, () => {
|
|
194
194
|
return cb.apply(this, args)
|
|
195
195
|
})
|
|
@@ -10,28 +10,32 @@ const startCh = channel('apm:ioredis:command:start')
|
|
|
10
10
|
const finishCh = channel('apm:ioredis:command:finish')
|
|
11
11
|
const errorCh = channel('apm:ioredis:command:error')
|
|
12
12
|
|
|
13
|
+
const connectionOptionsCache = new WeakMap()
|
|
14
|
+
|
|
13
15
|
function wrapRedis (Redis) {
|
|
14
16
|
shimmer.wrap(Redis.prototype, 'sendCommand', sendCommand => function (command, stream) {
|
|
15
|
-
if (!startCh.hasSubscribers) return sendCommand.
|
|
17
|
+
if (!startCh.hasSubscribers) return sendCommand.call(this, command, stream)
|
|
16
18
|
|
|
17
|
-
if (!command
|
|
19
|
+
if (!command?.promise) return sendCommand.call(this, command, stream)
|
|
18
20
|
|
|
19
21
|
const options = this.options || {}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
let connectionOptions = connectionOptionsCache.get(this)
|
|
23
|
+
if (connectionOptions === undefined) {
|
|
24
|
+
connectionOptions = { host: options.host, port: options.port }
|
|
25
|
+
connectionOptionsCache.set(this, connectionOptions)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const ctx = {
|
|
29
|
+
db: options.db,
|
|
30
|
+
command: command.name,
|
|
31
|
+
args: command.args,
|
|
32
|
+
connectionOptions,
|
|
33
|
+
connectionName: options.connectionName,
|
|
34
|
+
}
|
|
25
35
|
return startCh.runStores(ctx, () => {
|
|
26
36
|
command.promise.then(() => finish(finishCh, errorCh, ctx), err => finish(finishCh, errorCh, ctx, err))
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
return sendCommand.apply(this, arguments)
|
|
30
|
-
} catch (err) {
|
|
31
|
-
errorCh.publish(err)
|
|
32
|
-
|
|
33
|
-
throw err
|
|
34
|
-
}
|
|
38
|
+
return sendCommand.call(this, command, stream)
|
|
35
39
|
})
|
|
36
40
|
})
|
|
37
41
|
return Redis
|