dd-trace 5.104.0 → 5.105.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 +90 -102
- package/index.d.ts +82 -3
- package/package.json +15 -15
- package/packages/datadog-core/src/storage.js +1 -1
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/ai.js +8 -7
- package/packages/datadog-instrumentations/src/aws-sdk.js +13 -0
- package/packages/datadog-instrumentations/src/azure-cosmos.js +7 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +3 -0
- package/packages/datadog-instrumentations/src/cucumber.js +78 -5
- package/packages/datadog-instrumentations/src/dns.js +54 -18
- package/packages/datadog-instrumentations/src/fastify.js +142 -82
- package/packages/datadog-instrumentations/src/graphql.js +188 -62
- package/packages/datadog-instrumentations/src/helpers/ai-messages.js +322 -14
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +269 -0
- package/packages/datadog-instrumentations/src/helpers/promise-instrumentor.js +42 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-cosmos.js +50 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +85 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +37 -236
- package/packages/datadog-instrumentations/src/hono.js +54 -3
- package/packages/datadog-instrumentations/src/http/server.js +9 -4
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +163 -0
- package/packages/datadog-instrumentations/src/jest.js +360 -150
- package/packages/datadog-instrumentations/src/kafkajs.js +120 -16
- package/packages/datadog-instrumentations/src/mocha/main.js +128 -17
- package/packages/datadog-instrumentations/src/nats.js +182 -0
- package/packages/datadog-instrumentations/src/nyc.js +38 -1
- package/packages/datadog-instrumentations/src/openai.js +33 -18
- package/packages/datadog-instrumentations/src/oracledb.js +6 -1
- package/packages/datadog-instrumentations/src/pino.js +17 -5
- package/packages/datadog-instrumentations/src/playwright.js +515 -292
- package/packages/datadog-instrumentations/src/router.js +76 -32
- package/packages/datadog-instrumentations/src/stripe.js +1 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-azure-cosmos/src/index.js +144 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +1 -1
- package/packages/datadog-plugin-bunyan/src/index.js +28 -0
- package/packages/datadog-plugin-cucumber/src/index.js +17 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +199 -28
- package/packages/datadog-plugin-cypress/src/support.js +69 -1
- package/packages/datadog-plugin-dns/src/lookup.js +8 -6
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +2 -0
- package/packages/datadog-plugin-graphql/src/resolve.js +64 -67
- package/packages/datadog-plugin-http/src/server.js +40 -15
- package/packages/datadog-plugin-jest/src/index.js +11 -3
- package/packages/datadog-plugin-jest/src/util.js +15 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -0
- package/packages/datadog-plugin-langgraph/src/stream.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +19 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +281 -40
- package/packages/datadog-plugin-nats/src/consumer.js +43 -0
- package/packages/datadog-plugin-nats/src/index.js +20 -0
- package/packages/datadog-plugin-nats/src/producer.js +62 -0
- package/packages/datadog-plugin-nats/src/util.js +33 -0
- package/packages/datadog-plugin-next/src/index.js +5 -3
- package/packages/datadog-plugin-openai/src/tracing.js +15 -2
- package/packages/datadog-plugin-oracledb/src/index.js +13 -2
- package/packages/datadog-plugin-pino/src/index.js +42 -0
- package/packages/datadog-plugin-playwright/src/index.js +4 -4
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +33 -44
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +5 -13
- package/packages/datadog-plugin-winston/src/index.js +30 -0
- package/packages/datadog-shimmer/src/shimmer.js +33 -40
- package/packages/dd-trace/src/aiguard/index.js +1 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +5 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/utils.js +1 -1
- package/packages/dd-trace/src/appsec/user_tracking.js +5 -4
- package/packages/dd-trace/src/baggage.js +7 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +0 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +25 -13
- package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +70 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +6 -2
- package/packages/dd-trace/src/config/supported-configurations.json +27 -8
- package/packages/dd-trace/src/datastreams/writer.js +2 -4
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -8
- package/packages/dd-trace/src/encode/0.4.js +124 -108
- package/packages/dd-trace/src/encode/0.5.js +114 -26
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +31 -23
- package/packages/dd-trace/src/encode/agentless-json.js +4 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +32 -13
- package/packages/dd-trace/src/encode/span-stats.js +16 -16
- package/packages/dd-trace/src/encode/tags-processors.js +16 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +9 -7
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +0 -16
- package/packages/dd-trace/src/llmobs/span_processor.js +3 -3
- package/packages/dd-trace/src/llmobs/tagger.js +9 -1
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/util.js +66 -3
- package/packages/dd-trace/src/log/index.js +1 -1
- package/packages/dd-trace/src/msgpack/chunk.js +394 -10
- package/packages/dd-trace/src/msgpack/index.js +96 -2
- package/packages/dd-trace/src/openfeature/encoding.js +70 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +20 -0
- package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +143 -0
- package/packages/dd-trace/src/openfeature/span-enrichment.js +149 -0
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +4 -3
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +18 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +62 -67
- package/packages/dd-trace/src/opentracing/span.js +59 -19
- package/packages/dd-trace/src/opentracing/span_context.js +49 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -20
- package/packages/dd-trace/src/plugins/database.js +7 -6
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_injection.js +56 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -48
- package/packages/dd-trace/src/plugins/outbound.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +15 -17
- package/packages/dd-trace/src/plugins/tracing.js +43 -5
- package/packages/dd-trace/src/plugins/util/test.js +236 -13
- package/packages/dd-trace/src/plugins/util/web.js +79 -65
- package/packages/dd-trace/src/priority_sampler.js +2 -2
- package/packages/dd-trace/src/profiling/profiler.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +10 -4
- package/packages/dd-trace/src/sampling_rule.js +7 -7
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +10 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/source-resolver.js +46 -0
- package/packages/dd-trace/src/span_format.js +190 -58
- package/packages/dd-trace/src/spanleak.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -3
- package/packages/dd-trace/src/tagger.js +0 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +70 -39
- package/vendor/dist/@datadog/sketches-js/LICENSE +10 -36
- 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/dd-trace/src/msgpack/encoder.js +0 -308
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +0 -9
|
@@ -8,7 +8,6 @@ const { getCompileToRegexp } = require('./path-to-regexp')
|
|
|
8
8
|
const {
|
|
9
9
|
getRouterMountPaths,
|
|
10
10
|
joinPath,
|
|
11
|
-
getLayerMatchers,
|
|
12
11
|
setLayerMatchers,
|
|
13
12
|
isAppMounted,
|
|
14
13
|
setRouterMountPath,
|
|
@@ -42,34 +41,47 @@ function createWrapRouterMethod (name, compile) {
|
|
|
42
41
|
const nextChannel = channel(`apm:${name}:middleware:next`)
|
|
43
42
|
const routeAddedChannel = channel(`apm:${name}:route:added`)
|
|
44
43
|
|
|
45
|
-
function wrapLayerHandle (layer, original) {
|
|
46
|
-
|
|
44
|
+
function wrapLayerHandle (layer, original, matchers) {
|
|
45
|
+
// Resolve `name` once at wrap time: cached on the original for any code
|
|
46
|
+
// that reads `_name`, captured in the closure so the per-call body avoids
|
|
47
|
+
// the property-lookup / `||` fallback.
|
|
48
|
+
const name = original._name || layer.name || original.name
|
|
49
|
+
original._name = name
|
|
50
|
+
|
|
51
|
+
// Wrap-time matcher analysis. The single-pattern case yields a constant
|
|
52
|
+
// route; only multi-pattern stacks need a per-request layer.path match.
|
|
53
|
+
let captureRoute
|
|
54
|
+
let needMultiMatch = false
|
|
55
|
+
if (matchers.length !== 0 && !isFastStar(layer, matchers) && !isFastSlash(layer, matchers)) {
|
|
56
|
+
if (matchers.length === 1) {
|
|
57
|
+
captureRoute = matchers[0].path
|
|
58
|
+
} else {
|
|
59
|
+
needMultiMatch = true
|
|
60
|
+
}
|
|
61
|
+
}
|
|
47
62
|
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
// Split by arity: router only ever dispatches 3-arg request handlers
|
|
64
|
+
// through `Layer.handleRequest` and 4-arg error handlers through
|
|
65
|
+
// `Layer.handleError`. Specialising lets the per-call body use named
|
|
66
|
+
// parameters and `.call`, avoiding the rest-spread Array allocation that
|
|
67
|
+
// the unified shape forced on every middleware invocation.
|
|
68
|
+
return original.length === 4
|
|
69
|
+
? shimmer.wrapFunction(original, errorHandlerLayerWrap(layer, name, captureRoute, needMultiMatch, matchers))
|
|
70
|
+
: shimmer.wrapFunction(original, requestHandlerLayerWrap(layer, name, captureRoute, needMultiMatch, matchers))
|
|
71
|
+
}
|
|
50
72
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const req = args[args.length > 3 ? 1 : 0]
|
|
55
|
-
const next = args[lastIndex]
|
|
73
|
+
function requestHandlerLayerWrap (layer, name, captureRoute, needMultiMatch, matchers) {
|
|
74
|
+
return original => function (req, res, next) {
|
|
75
|
+
if (!enterChannel.hasSubscribers) return original.call(this, req, res, next)
|
|
56
76
|
|
|
57
|
-
|
|
58
|
-
args[lastIndex] = wrapNext(req, next)
|
|
59
|
-
}
|
|
77
|
+
const wrappedNext = typeof next === 'function' ? wrapNext(req, next) : next
|
|
60
78
|
|
|
61
|
-
let route
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} else {
|
|
68
|
-
for (const matcher of matchers) {
|
|
69
|
-
if (matcher.regex?.test(layer.path)) {
|
|
70
|
-
route = matcher.path
|
|
71
|
-
break
|
|
72
|
-
}
|
|
79
|
+
let route = captureRoute
|
|
80
|
+
if (needMultiMatch) {
|
|
81
|
+
for (const matcher of matchers) {
|
|
82
|
+
if (matcher.regex?.test(layer.path)) {
|
|
83
|
+
route = matcher.path
|
|
84
|
+
break
|
|
73
85
|
}
|
|
74
86
|
}
|
|
75
87
|
}
|
|
@@ -77,7 +89,7 @@ function createWrapRouterMethod (name, compile) {
|
|
|
77
89
|
enterChannel.publish({ name, req, route, layer })
|
|
78
90
|
|
|
79
91
|
try {
|
|
80
|
-
return original.
|
|
92
|
+
return original.call(this, req, res, wrappedNext)
|
|
81
93
|
} catch (error) {
|
|
82
94
|
errorChannel.publish({ req, error })
|
|
83
95
|
nextChannel.publish({ req })
|
|
@@ -87,15 +99,47 @@ function createWrapRouterMethod (name, compile) {
|
|
|
87
99
|
} finally {
|
|
88
100
|
exitChannel.publish({ req })
|
|
89
101
|
}
|
|
90
|
-
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function errorHandlerLayerWrap (layer, name, captureRoute, needMultiMatch, matchers) {
|
|
106
|
+
return original => function (error, req, res, next) {
|
|
107
|
+
if (!enterChannel.hasSubscribers) return original.call(this, error, req, res, next)
|
|
108
|
+
|
|
109
|
+
const wrappedNext = typeof next === 'function' ? wrapNext(req, next) : next
|
|
110
|
+
|
|
111
|
+
let route = captureRoute
|
|
112
|
+
if (needMultiMatch) {
|
|
113
|
+
for (const matcher of matchers) {
|
|
114
|
+
if (matcher.regex?.test(layer.path)) {
|
|
115
|
+
route = matcher.path
|
|
116
|
+
break
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
enterChannel.publish({ name, req, route, layer })
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
return original.call(this, error, req, res, wrappedNext)
|
|
125
|
+
} catch (caught) {
|
|
126
|
+
errorChannel.publish({ req, error: caught })
|
|
127
|
+
nextChannel.publish({ req })
|
|
128
|
+
finishChannel.publish({ req })
|
|
129
|
+
|
|
130
|
+
throw caught
|
|
131
|
+
} finally {
|
|
132
|
+
exitChannel.publish({ req })
|
|
133
|
+
}
|
|
134
|
+
}
|
|
91
135
|
}
|
|
92
136
|
|
|
93
137
|
function wrapStack (layers, matchers) {
|
|
94
138
|
for (const layer of layers) {
|
|
95
139
|
if (layer.__handle) { // express-async-errors
|
|
96
|
-
layer.__handle = wrapLayerHandle(layer, layer.__handle)
|
|
140
|
+
layer.__handle = wrapLayerHandle(layer, layer.__handle, matchers)
|
|
97
141
|
} else {
|
|
98
|
-
layer.handle = wrapLayerHandle(layer, layer.handle)
|
|
142
|
+
layer.handle = wrapLayerHandle(layer, layer.handle, matchers)
|
|
99
143
|
}
|
|
100
144
|
|
|
101
145
|
setLayerMatchers(layer, matchers)
|
|
@@ -258,15 +302,15 @@ addHook({ name: 'router', versions: ['>=2'] }, Router => {
|
|
|
258
302
|
|
|
259
303
|
shimmer.wrap(router, 'handle', function wrapHandle (originalHandle) {
|
|
260
304
|
return function wrappedHandle (req, res, next) {
|
|
261
|
-
const abortController = new AbortController()
|
|
262
|
-
|
|
263
305
|
if (queryParserReadCh.hasSubscribers && req) {
|
|
306
|
+
const abortController = new AbortController()
|
|
307
|
+
|
|
264
308
|
queryParserReadCh.publish({ req, res, query: req.query, abortController })
|
|
265
309
|
|
|
266
310
|
if (abortController.signal.aborted) return
|
|
267
311
|
}
|
|
268
312
|
|
|
269
|
-
return originalHandle.
|
|
313
|
+
return originalHandle.call(this, req, res, next)
|
|
270
314
|
}
|
|
271
315
|
})
|
|
272
316
|
|
|
@@ -97,7 +97,7 @@ function wrapStripe (Stripe) {
|
|
|
97
97
|
|
|
98
98
|
addHook({
|
|
99
99
|
name: 'stripe',
|
|
100
|
-
versions: ['9
|
|
100
|
+
versions: ['>=9 <22'],
|
|
101
101
|
}, Stripe => shimmer.wrapFunction(Stripe, wrapLegacyStripe))
|
|
102
102
|
|
|
103
103
|
addHook({
|
|
@@ -140,7 +140,7 @@ class SchemaExtractor {
|
|
|
140
140
|
return
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
if (span.context().
|
|
143
|
+
if (span.context().getTag(SCHEMA_TYPE) && operation === 'serialization') {
|
|
144
144
|
// we have already added a schema to this span, this call is an encode of nested schema types
|
|
145
145
|
return
|
|
146
146
|
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { storage } = require('../../datadog-core')
|
|
4
|
+
|
|
5
|
+
const DatabasePlugin = require('../../dd-trace/src/plugins/database')
|
|
6
|
+
|
|
7
|
+
class AzureCosmosPlugin extends DatabasePlugin {
|
|
8
|
+
static id = 'azure-cosmos'
|
|
9
|
+
// Channel prefix determines how the plugin subscribes to instrumentation events.
|
|
10
|
+
// Three patterns exist — set `static prefix` explicitly based on instrumentation type:
|
|
11
|
+
//
|
|
12
|
+
// Orchestrion: static prefix = 'tracing:orchestrion:<npm-package>:<channelName>'
|
|
13
|
+
// Shimmer + tracingChannel: static prefix = 'tracing:apm:<name>:<operation>'
|
|
14
|
+
// Shimmer + manual channels: omit prefix — defaults to `apm:${id}:${operation}`
|
|
15
|
+
static prefix = 'tracing:orchestrion:@azure/cosmos:executePlugins'
|
|
16
|
+
static peerServicePrecursors = ['db.name']
|
|
17
|
+
|
|
18
|
+
operationName () {
|
|
19
|
+
return 'cosmosdb.query'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
asyncEnd (ctx) {
|
|
23
|
+
if (!ctx.span) return
|
|
24
|
+
const span = ctx.currentStore?.span
|
|
25
|
+
if (span) {
|
|
26
|
+
const result = ctx.result
|
|
27
|
+
if (result?.code) span.setTag('db.response.status_code', (result.code).toString())
|
|
28
|
+
if (result?.substatus) span.setTag('cosmosdb.response.sub_status_code', result.substatus)
|
|
29
|
+
span.finish()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
error (ctx) {
|
|
34
|
+
if (!ctx.span) return
|
|
35
|
+
const span = ctx.currentStore?.span
|
|
36
|
+
if (span) {
|
|
37
|
+
const error = ctx.error
|
|
38
|
+
this.addError(error, span)
|
|
39
|
+
if (error?.code) span.setTag('db.response.status_code', (error.code).toString())
|
|
40
|
+
if (error?.substatus) span.setTag('cosmosdb.response.sub_status_code', error.substatus)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
bindStart (ctx) {
|
|
45
|
+
const requestContext = ctx.arguments[1]
|
|
46
|
+
const resource = this.getResource(requestContext)
|
|
47
|
+
const { dbName, containerName } = this.getDbInfo(requestContext)
|
|
48
|
+
const connectionMode = this.getConnectionMode(requestContext)
|
|
49
|
+
const { outHost, userAgent } = this.getHttpInfo(requestContext)
|
|
50
|
+
const pluginOn = ctx.arguments[3]
|
|
51
|
+
|
|
52
|
+
if (pluginOn != null && requestContext.operationType != null && requestContext.resourceType != null) {
|
|
53
|
+
const operationType = requestContext.operationType
|
|
54
|
+
const resourceType = requestContext.resourceType
|
|
55
|
+
// only trace operations not requests (pluginOn)
|
|
56
|
+
// trace requests only if they are read or query operations not on docs
|
|
57
|
+
// prevents doubled read spans for createIfNotExists calls
|
|
58
|
+
if (pluginOn === 'request' && ((operationType !== 'read' && operationType !== 'query') ||
|
|
59
|
+
(operationType === 'read' && resourceType !== 'docs'))) {
|
|
60
|
+
return storage('legacy').getStore()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// separately, skip tracing read requests without a path, these don't
|
|
64
|
+
// represent CRUD operations on a resource we care about
|
|
65
|
+
// not returning current store because we don't want the child http.request spans
|
|
66
|
+
// to be created
|
|
67
|
+
if (operationType === 'read' && requestContext.path === '') {
|
|
68
|
+
return { noop: true }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const span = this.startSpan(this.operationName(), {
|
|
73
|
+
resource,
|
|
74
|
+
type: 'cosmosdb',
|
|
75
|
+
kind: 'client',
|
|
76
|
+
meta: {
|
|
77
|
+
component: 'azure_cosmos',
|
|
78
|
+
'db.system': 'cosmosdb',
|
|
79
|
+
'db.name': dbName,
|
|
80
|
+
'cosmosdb.container': containerName,
|
|
81
|
+
'cosmosdb.connection.mode': connectionMode,
|
|
82
|
+
'http.useragent': userAgent,
|
|
83
|
+
'out.host': outHost,
|
|
84
|
+
},
|
|
85
|
+
}, ctx)
|
|
86
|
+
|
|
87
|
+
ctx.span = span
|
|
88
|
+
return ctx.currentStore
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getResource (requestContext) {
|
|
92
|
+
const path = requestContext.path
|
|
93
|
+
const parts = path.split('/')
|
|
94
|
+
let modified = false
|
|
95
|
+
for (let i = 2; i < parts.length; i += 2) {
|
|
96
|
+
if (parts[i].length > 0 && parts[i - 1] !== 'dbs' && parts[i - 1] !== 'colls') {
|
|
97
|
+
parts[i] = '?'
|
|
98
|
+
modified = true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return `${requestContext.operationType} ${modified ? parts.join('/') : path}`
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
getDbInfo (requestContext) {
|
|
106
|
+
let dbName = null
|
|
107
|
+
let containerName = null
|
|
108
|
+
|
|
109
|
+
if (requestContext.operationType === 'create' && requestContext.resourceType === 'dbs' &&
|
|
110
|
+
requestContext.body != null && requestContext.body.id != null) {
|
|
111
|
+
dbName = requestContext.body.id
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let resourceLink = requestContext.path
|
|
115
|
+
if (resourceLink?.length > 1 && resourceLink.startsWith('/')) {
|
|
116
|
+
resourceLink = resourceLink.slice(1)
|
|
117
|
+
const parts = resourceLink.split('/')
|
|
118
|
+
if (parts.length > 0 && parts[0].toLowerCase() === 'dbs' && parts.length >= 2) {
|
|
119
|
+
dbName = parts[1]
|
|
120
|
+
if (parts.length >= 4 && parts[2].toLowerCase() === 'colls' && parts[3] !== '') {
|
|
121
|
+
containerName = parts[3]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { dbName, containerName }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
getConnectionMode (requestContext) {
|
|
130
|
+
const mode = requestContext.client?.connectionPolicy?.connectionMode
|
|
131
|
+
if (mode === 0) {
|
|
132
|
+
return 'gateway'
|
|
133
|
+
}
|
|
134
|
+
return 'direct'
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
getHttpInfo (requestContext) {
|
|
138
|
+
const outHost = requestContext.client?.cosmosClientOptions?.endpoint
|
|
139
|
+
const userAgent = requestContext.headers?.['User-Agent']
|
|
140
|
+
return { outHost, userAgent }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = AzureCosmosPlugin
|
|
@@ -13,6 +13,7 @@ const triggerMap = {
|
|
|
13
13
|
serviceBusQueue: 'ServiceBus',
|
|
14
14
|
serviceBusTopic: 'ServiceBus',
|
|
15
15
|
eventHub: 'EventHubs',
|
|
16
|
+
cosmosDB: 'CosmosDB',
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
class AzureFunctionsPlugin extends TracingPlugin {
|
|
@@ -53,7 +54,7 @@ class AzureFunctionsPlugin extends TracingPlugin {
|
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
span._integrationName = 'azure-functions'
|
|
56
|
-
span.context().
|
|
57
|
+
span.context().setTag('component', 'azure-functions')
|
|
57
58
|
span.addTags(meta)
|
|
58
59
|
webContext.span = span
|
|
59
60
|
webContext.azureFunctionCtx = ctx
|
|
@@ -127,6 +128,8 @@ function getMetaForTrigger ({ functionName, methodName, invocationContext }) {
|
|
|
127
128
|
'resource.name': `EventHubs ${functionName}`,
|
|
128
129
|
'span.kind': 'consumer',
|
|
129
130
|
}
|
|
131
|
+
} else if (triggerMap[methodName] === 'CosmosDB') {
|
|
132
|
+
meta['resource.name'] = `CosmosDB ${functionName}`
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
return meta
|
|
@@ -155,7 +158,7 @@ function setSpanLinks (triggerType, tracer, span, ctx) {
|
|
|
155
158
|
if (!props || Object.keys(props).length === 0) return
|
|
156
159
|
const spanContext = tracer.extract('text_map', props)
|
|
157
160
|
if (spanContext) {
|
|
158
|
-
span.addLink(spanContext)
|
|
161
|
+
span.addLink({ context: spanContext })
|
|
159
162
|
}
|
|
160
163
|
}
|
|
161
164
|
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { buildLogHolder } = require('../../dd-trace/src/plugins/log_injection')
|
|
3
4
|
const LogPlugin = require('../../dd-trace/src/plugins/log_plugin')
|
|
4
5
|
|
|
5
6
|
class BunyanPlugin extends LogPlugin {
|
|
6
7
|
static id = 'bunyan'
|
|
8
|
+
|
|
9
|
+
constructor (...args) {
|
|
10
|
+
super(...args)
|
|
11
|
+
this.addSub('apm:bunyan:log', (arg) => this.handleLog(arg))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Inject `dd` directly on the record bunyan hands us. bunyan builds the
|
|
16
|
+
* record inside `mkRecord` via `objCopy(log.fields)` and then copies the
|
|
17
|
+
* caller's fields onto the result, so the `rec` object that flows
|
|
18
|
+
* through `_emit` is always bunyan-owned, has `Object.prototype` for its
|
|
19
|
+
* prototype, and is never the caller's input directly. Mutating it adds
|
|
20
|
+
* `dd` for every consumer (JSON streams via `JSON.stringify(rec)`, raw
|
|
21
|
+
* streams via the record reference) without paying for a Proxy view.
|
|
22
|
+
*
|
|
23
|
+
* @param {{ message: object }} arg
|
|
24
|
+
*/
|
|
25
|
+
handleLog (arg) {
|
|
26
|
+
const rec = arg.message
|
|
27
|
+
if (rec === null || typeof rec !== 'object' || Object.hasOwn(rec, 'dd')) return
|
|
28
|
+
|
|
29
|
+
const logHolder = buildLogHolder(this.tracer)
|
|
30
|
+
if (!logHolder) return
|
|
31
|
+
|
|
32
|
+
rec.dd = logHolder.dd
|
|
33
|
+
}
|
|
7
34
|
}
|
|
35
|
+
|
|
8
36
|
module.exports = BunyanPlugin
|
|
@@ -11,6 +11,7 @@ const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
|
11
11
|
const {
|
|
12
12
|
addIntelligentTestRunnerSpanTags,
|
|
13
13
|
finishAllTraceSpans,
|
|
14
|
+
getRelativeCoverageFiles,
|
|
14
15
|
getTestEndLine,
|
|
15
16
|
getTestSuiteCommonTags,
|
|
16
17
|
getTestSuitePath,
|
|
@@ -71,6 +72,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
71
72
|
isSuitesSkipped,
|
|
72
73
|
numSkippedSuites,
|
|
73
74
|
testCodeCoverageLinesTotal,
|
|
75
|
+
testSessionCoverageFiles,
|
|
74
76
|
hasUnskippableSuites,
|
|
75
77
|
hasForcedToRunSuites,
|
|
76
78
|
isEarlyFlakeDetectionEnabled,
|
|
@@ -78,7 +80,11 @@ class CucumberPlugin extends CiPlugin {
|
|
|
78
80
|
isTestManagementTestsEnabled,
|
|
79
81
|
isParallel,
|
|
80
82
|
}) => {
|
|
81
|
-
const {
|
|
83
|
+
const {
|
|
84
|
+
isSuitesSkippingEnabled,
|
|
85
|
+
isCodeCoverageEnabled,
|
|
86
|
+
isCoverageReportUploadEnabled,
|
|
87
|
+
} = this.libraryConfig || {}
|
|
82
88
|
addIntelligentTestRunnerSpanTags(
|
|
83
89
|
this.testSessionSpan,
|
|
84
90
|
this.testModuleSpan,
|
|
@@ -93,6 +99,12 @@ class CucumberPlugin extends CiPlugin {
|
|
|
93
99
|
hasForcedToRunSuites,
|
|
94
100
|
}
|
|
95
101
|
)
|
|
102
|
+
if (testSessionCoverageFiles?.length && isCoverageReportUploadEnabled) {
|
|
103
|
+
this.tracer._exporter.exportCoverage({
|
|
104
|
+
sessionId: this.testSessionSpan.context()._traceId,
|
|
105
|
+
files: testSessionCoverageFiles,
|
|
106
|
+
})
|
|
107
|
+
}
|
|
96
108
|
if (isEarlyFlakeDetectionEnabled) {
|
|
97
109
|
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
|
|
98
110
|
}
|
|
@@ -197,8 +209,10 @@ class CucumberPlugin extends CiPlugin {
|
|
|
197
209
|
}
|
|
198
210
|
const testSuiteSpan = this._testSuiteSpansByTestSuite.get(testSuitePath)
|
|
199
211
|
|
|
200
|
-
const relativeCoverageFiles = [
|
|
201
|
-
|
|
212
|
+
const relativeCoverageFiles = [
|
|
213
|
+
...getRelativeCoverageFiles(coverageFiles, this.repositoryRoot),
|
|
214
|
+
getTestSuitePath(suiteFile, this.repositoryRoot),
|
|
215
|
+
]
|
|
202
216
|
|
|
203
217
|
this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
204
218
|
|