dd-trace 4.47.1 → 4.49.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 +1 -1
- package/ext/types.d.ts +1 -0
- package/ext/types.js +1 -0
- package/index.d.ts +361 -0
- package/package.json +18 -13
- package/packages/datadog-code-origin/index.js +38 -0
- package/packages/datadog-core/index.js +2 -2
- package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-instrumentations/src/amqplib.js +65 -5
- package/packages/datadog-instrumentations/src/avsc.js +37 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +48 -0
- package/packages/datadog-instrumentations/src/child_process.js +144 -27
- package/packages/datadog-instrumentations/src/express.js +37 -4
- package/packages/datadog-instrumentations/src/fastify.js +12 -1
- package/packages/datadog-instrumentations/src/fs.js +27 -7
- package/packages/datadog-instrumentations/src/helpers/hooks.js +6 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -0
- package/packages/datadog-instrumentations/src/jest.js +2 -1
- package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
- package/packages/datadog-instrumentations/src/multer.js +37 -0
- package/packages/datadog-instrumentations/src/mysql2.js +220 -1
- package/packages/datadog-instrumentations/src/openai.js +2 -2
- package/packages/datadog-instrumentations/src/protobufjs.js +127 -0
- package/packages/datadog-instrumentations/src/url.js +84 -0
- package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
- package/packages/datadog-instrumentations/src/winston.js +22 -0
- package/packages/datadog-plugin-amqplib/src/consumer.js +4 -4
- package/packages/datadog-plugin-avsc/src/index.js +9 -0
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +169 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-azure-functions/src/index.js +77 -0
- package/packages/datadog-plugin-fastify/src/code_origin.js +31 -0
- package/packages/datadog-plugin-fastify/src/index.js +10 -12
- package/packages/datadog-plugin-fastify/src/tracing.js +19 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +8 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
- package/packages/datadog-plugin-grpc/src/client.js +3 -0
- package/packages/datadog-plugin-grpc/src/server.js +3 -0
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +8 -4
- package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
- package/packages/datadog-plugin-mocha/src/index.js +4 -1
- package/packages/datadog-plugin-openai/src/index.js +9 -1015
- package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
- package/packages/datadog-plugin-protobufjs/src/index.js +14 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +180 -0
- package/packages/dd-trace/src/appsec/addresses.js +8 -1
- package/packages/dd-trace/src/appsec/channels.js +7 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +13 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +8 -1
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/index.js +3 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +1 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +55 -7
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +15 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -2
- package/packages/dd-trace/src/appsec/index.js +61 -43
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +99 -0
- package/packages/dd-trace/src/appsec/rasp/index.js +27 -10
- package/packages/dd-trace/src/appsec/rasp/lfi.js +112 -0
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +24 -4
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
- package/packages/dd-trace/src/appsec/rasp/utils.js +4 -2
- package/packages/dd-trace/src/appsec/recommended.json +3 -7
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +6 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +10 -0
- package/packages/dd-trace/src/appsec/reporter.js +17 -9
- package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -3
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
- package/packages/dd-trace/src/azure_metadata.js +120 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -14
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +53 -0
- package/packages/dd-trace/src/config.js +86 -6
- package/packages/dd-trace/src/constants.js +3 -1
- package/packages/dd-trace/src/datastreams/pathway.js +1 -0
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +25 -17
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +52 -5
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +4 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +29 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +187 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +40 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +252 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +19 -4
- package/packages/dd-trace/src/debugger/index.js +10 -3
- package/packages/dd-trace/src/exporters/common/request.js +8 -34
- package/packages/dd-trace/src/exporters/common/url-to-http-options-polyfill.js +31 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
- package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
- package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
- package/packages/dd-trace/src/llmobs/index.js +103 -0
- package/packages/dd-trace/src/llmobs/noop.js +82 -0
- package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
- package/packages/dd-trace/src/llmobs/sdk.js +377 -0
- package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
- package/packages/dd-trace/src/llmobs/storage.js +7 -0
- package/packages/dd-trace/src/llmobs/tagger.js +322 -0
- package/packages/dd-trace/src/llmobs/util.js +176 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
- package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +49 -0
- package/packages/dd-trace/src/noop/proxy.js +3 -0
- package/packages/dd-trace/src/noop/span.js +3 -0
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +73 -12
- package/packages/dd-trace/src/opentracing/span.js +12 -0
- package/packages/dd-trace/src/opentracing/tracer.js +8 -1
- package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
- package/packages/dd-trace/src/payload-tagging/index.js +1 -1
- package/packages/dd-trace/src/payload-tagging/jsonpath-plus.js +2094 -0
- package/packages/dd-trace/src/plugin_manager.js +4 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -0
- package/packages/dd-trace/src/plugins/index.js +3 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/outbound.js +9 -0
- package/packages/dd-trace/src/plugins/schema.js +35 -0
- package/packages/dd-trace/src/plugins/util/ci.js +23 -1
- package/packages/dd-trace/src/plugins/util/serverless.js +7 -0
- package/packages/dd-trace/src/plugins/util/stacktrace.js +94 -0
- package/packages/dd-trace/src/plugins/util/tags.js +7 -0
- package/packages/dd-trace/src/plugins/util/test.js +20 -22
- package/packages/dd-trace/src/plugins/util/web.js +6 -4
- package/packages/dd-trace/src/priority_sampler.js +16 -0
- package/packages/dd-trace/src/profiling/config.js +3 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
- package/packages/dd-trace/src/profiling/profiler.js +24 -14
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +95 -66
- package/packages/dd-trace/src/proxy.js +20 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +12 -0
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/telemetry/index.js +11 -1
- package/packages/datadog-core/src/storage/async_resource.js +0 -108
- package/packages/datadog-core/src/storage/index.js +0 -5
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { addHook, channel } = require('./helpers/instrument')
|
|
4
|
+
const shimmer = require('../../datadog-shimmer')
|
|
5
|
+
const names = ['url', 'node:url']
|
|
6
|
+
|
|
7
|
+
const parseFinishedChannel = channel('datadog:url:parse:finish')
|
|
8
|
+
const urlGetterChannel = channel('datadog:url:getter:finish')
|
|
9
|
+
const instrumentedGetters = ['host', 'origin', 'hostname']
|
|
10
|
+
|
|
11
|
+
addHook({ name: names }, function (url) {
|
|
12
|
+
shimmer.wrap(url, 'parse', (parse) => {
|
|
13
|
+
return function wrappedParse (input) {
|
|
14
|
+
const parsedValue = parse.apply(this, arguments)
|
|
15
|
+
if (!parseFinishedChannel.hasSubscribers) return parsedValue
|
|
16
|
+
|
|
17
|
+
parseFinishedChannel.publish({
|
|
18
|
+
input,
|
|
19
|
+
parsed: parsedValue,
|
|
20
|
+
isURL: false
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return parsedValue
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const URLPrototype = url.URL.prototype.constructor.prototype
|
|
28
|
+
instrumentedGetters.forEach(property => {
|
|
29
|
+
const originalDescriptor = Object.getOwnPropertyDescriptor(URLPrototype, property)
|
|
30
|
+
|
|
31
|
+
if (originalDescriptor?.get) {
|
|
32
|
+
const newDescriptor = shimmer.wrap(originalDescriptor, 'get', function (originalGet) {
|
|
33
|
+
return function get () {
|
|
34
|
+
const result = originalGet.apply(this, arguments)
|
|
35
|
+
if (!urlGetterChannel.hasSubscribers) return result
|
|
36
|
+
|
|
37
|
+
const context = { urlObject: this, result, property }
|
|
38
|
+
urlGetterChannel.publish(context)
|
|
39
|
+
|
|
40
|
+
return context.result
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
Object.defineProperty(URLPrototype, property, newDescriptor)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
shimmer.wrap(url, 'URL', (URL) => {
|
|
49
|
+
return class extends URL {
|
|
50
|
+
constructor (input, base) {
|
|
51
|
+
super(...arguments)
|
|
52
|
+
|
|
53
|
+
if (!parseFinishedChannel.hasSubscribers) return
|
|
54
|
+
|
|
55
|
+
parseFinishedChannel.publish({
|
|
56
|
+
input,
|
|
57
|
+
base,
|
|
58
|
+
parsed: this,
|
|
59
|
+
isURL: true
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
if (url.URL.parse) {
|
|
66
|
+
shimmer.wrap(url.URL, 'parse', (parse) => {
|
|
67
|
+
return function wrappedParse (input, base) {
|
|
68
|
+
const parsedValue = parse.apply(this, arguments)
|
|
69
|
+
if (!parseFinishedChannel.hasSubscribers) return parsedValue
|
|
70
|
+
|
|
71
|
+
parseFinishedChannel.publish({
|
|
72
|
+
input,
|
|
73
|
+
base,
|
|
74
|
+
parsed: parsedValue,
|
|
75
|
+
isURL: true
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return parsedValue
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return url
|
|
84
|
+
})
|
|
@@ -6,7 +6,7 @@ const NM = 'node_modules/'
|
|
|
6
6
|
* For a given full path to a module,
|
|
7
7
|
* return the package name it belongs to and the local path to the module
|
|
8
8
|
* input: '/foo/node_modules/@co/stuff/foo/bar/baz.js'
|
|
9
|
-
* output: { pkg: '@co/stuff', path: 'foo/bar/baz.js' }
|
|
9
|
+
* output: { pkg: '@co/stuff', path: 'foo/bar/baz.js', pkgJson: '/foo/node_modules/@co/stuff/package.json' }
|
|
10
10
|
*/
|
|
11
11
|
module.exports = function extractPackageAndModulePath (fullPath) {
|
|
12
12
|
const nm = fullPath.lastIndexOf(NM)
|
|
@@ -17,17 +17,20 @@ module.exports = function extractPackageAndModulePath (fullPath) {
|
|
|
17
17
|
const subPath = fullPath.substring(nm + NM.length)
|
|
18
18
|
const firstSlash = subPath.indexOf('/')
|
|
19
19
|
|
|
20
|
+
const firstPath = fullPath.substring(fullPath[0], nm + NM.length)
|
|
21
|
+
|
|
20
22
|
if (subPath[0] === '@') {
|
|
21
23
|
const secondSlash = subPath.substring(firstSlash + 1).indexOf('/')
|
|
22
|
-
|
|
23
24
|
return {
|
|
24
25
|
pkg: subPath.substring(0, firstSlash + 1 + secondSlash),
|
|
25
|
-
path: subPath.substring(firstSlash + 1 + secondSlash + 1)
|
|
26
|
+
path: subPath.substring(firstSlash + 1 + secondSlash + 1),
|
|
27
|
+
pkgJson: firstPath + subPath.substring(0, firstSlash + 1 + secondSlash) + '/package.json'
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
return {
|
|
30
32
|
pkg: subPath.substring(0, firstSlash),
|
|
31
|
-
path: subPath.substring(firstSlash + 1)
|
|
33
|
+
path: subPath.substring(firstSlash + 1),
|
|
34
|
+
pkgJson: firstPath + subPath.substring(0, firstSlash) + '/package.json'
|
|
32
35
|
}
|
|
33
36
|
}
|
|
@@ -8,6 +8,18 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
8
8
|
|
|
9
9
|
const patched = new WeakSet()
|
|
10
10
|
|
|
11
|
+
// Test Visibility log submission channels
|
|
12
|
+
const configureCh = channel('ci:log-submission:winston:configure')
|
|
13
|
+
const addTransport = channel('ci:log-submission:winston:add-transport')
|
|
14
|
+
|
|
15
|
+
addHook({ name: 'winston', file: 'lib/winston/transports/index.js', versions: ['>=3'] }, transportsPackage => {
|
|
16
|
+
if (configureCh.hasSubscribers) {
|
|
17
|
+
configureCh.publish(transportsPackage.Http)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return transportsPackage
|
|
21
|
+
})
|
|
22
|
+
|
|
11
23
|
addHook({ name: 'winston', file: 'lib/winston/logger.js', versions: ['>=3'] }, Logger => {
|
|
12
24
|
const logCh = channel('apm:winston:log')
|
|
13
25
|
shimmer.wrap(Logger.prototype, 'write', write => {
|
|
@@ -20,6 +32,16 @@ addHook({ name: 'winston', file: 'lib/winston/logger.js', versions: ['>=3'] }, L
|
|
|
20
32
|
return write.apply(this, arguments)
|
|
21
33
|
}
|
|
22
34
|
})
|
|
35
|
+
|
|
36
|
+
shimmer.wrap(Logger.prototype, 'configure', configure => function () {
|
|
37
|
+
const configureResponse = configure.apply(this, arguments)
|
|
38
|
+
// After the original `configure`, because it resets transports
|
|
39
|
+
if (addTransport.hasSubscribers) {
|
|
40
|
+
addTransport.publish(this)
|
|
41
|
+
}
|
|
42
|
+
return configureResponse
|
|
43
|
+
})
|
|
44
|
+
|
|
23
45
|
return Logger
|
|
24
46
|
})
|
|
25
47
|
|
|
@@ -9,17 +9,18 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
9
9
|
static get id () { return 'amqplib' }
|
|
10
10
|
static get operation () { return 'command' }
|
|
11
11
|
|
|
12
|
-
start ({ method, fields, message }) {
|
|
12
|
+
start ({ method, fields, message, queue }) {
|
|
13
13
|
if (method !== 'basic.deliver' && method !== 'basic.get') return
|
|
14
14
|
|
|
15
15
|
const childOf = extract(this.tracer, message)
|
|
16
16
|
|
|
17
|
+
const queueName = queue || fields.queue || fields.routingKey
|
|
17
18
|
const span = this.startSpan({
|
|
18
19
|
childOf,
|
|
19
20
|
resource: getResourceName(method, fields),
|
|
20
21
|
type: 'worker',
|
|
21
22
|
meta: {
|
|
22
|
-
'amqp.queue':
|
|
23
|
+
'amqp.queue': queueName,
|
|
23
24
|
'amqp.exchange': fields.exchange,
|
|
24
25
|
'amqp.routingKey': fields.routingKey,
|
|
25
26
|
'amqp.consumerTag': fields.consumerTag,
|
|
@@ -32,10 +33,9 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
32
33
|
this.config.dsmEnabled && message?.properties?.headers
|
|
33
34
|
) {
|
|
34
35
|
const payloadSize = getAmqpMessageSize({ headers: message.properties.headers, content: message.content })
|
|
35
|
-
const queue = fields.queue ? fields.queue : fields.routingKey
|
|
36
36
|
this.tracer.decodeDataStreamsContext(message.properties.headers)
|
|
37
37
|
this.tracer
|
|
38
|
-
.setCheckpoint(['direction:in', `topic:${
|
|
38
|
+
.setCheckpoint(['direction:in', `topic:${queueName}`, 'type:rabbitmq'], span, payloadSize)
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const SchemaPlugin = require('../../dd-trace/src/plugins/schema')
|
|
2
|
+
const SchemaExtractor = require('./schema_iterator')
|
|
3
|
+
|
|
4
|
+
class AvscPlugin extends SchemaPlugin {
|
|
5
|
+
static get id () { return 'avsc' }
|
|
6
|
+
static get schemaExtractor () { return SchemaExtractor }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
module.exports = AvscPlugin
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const AVRO = 'avro'
|
|
2
|
+
const {
|
|
3
|
+
SCHEMA_DEFINITION,
|
|
4
|
+
SCHEMA_ID,
|
|
5
|
+
SCHEMA_NAME,
|
|
6
|
+
SCHEMA_OPERATION,
|
|
7
|
+
SCHEMA_WEIGHT,
|
|
8
|
+
SCHEMA_TYPE
|
|
9
|
+
} = require('../../dd-trace/src/constants')
|
|
10
|
+
const log = require('../../dd-trace/src/log')
|
|
11
|
+
const {
|
|
12
|
+
SchemaBuilder
|
|
13
|
+
} = require('../../dd-trace/src/datastreams/schemas/schema_builder')
|
|
14
|
+
|
|
15
|
+
class SchemaExtractor {
|
|
16
|
+
constructor (schema) {
|
|
17
|
+
this.schema = schema
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getType (type) {
|
|
21
|
+
const typeMapping = {
|
|
22
|
+
string: 'string',
|
|
23
|
+
int: 'integer',
|
|
24
|
+
long: 'integer',
|
|
25
|
+
float: 'number',
|
|
26
|
+
double: 'number',
|
|
27
|
+
boolean: 'boolean',
|
|
28
|
+
bytes: 'string',
|
|
29
|
+
record: 'object',
|
|
30
|
+
enum: 'string',
|
|
31
|
+
array: 'array',
|
|
32
|
+
map: 'object',
|
|
33
|
+
fixed: 'string'
|
|
34
|
+
}
|
|
35
|
+
const typeName = type.typeName ?? type.name ?? type
|
|
36
|
+
return typeName === 'null' ? typeName : typeMapping[typeName] || 'string'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static extractProperty (field, schemaName, fieldName, builder, depth) {
|
|
40
|
+
let array = false
|
|
41
|
+
let type
|
|
42
|
+
let format
|
|
43
|
+
let enumValues
|
|
44
|
+
let description
|
|
45
|
+
let ref
|
|
46
|
+
|
|
47
|
+
const fieldType = field.type?.types ?? field.type?.typeName ?? field.type
|
|
48
|
+
|
|
49
|
+
if (Array.isArray(fieldType)) {
|
|
50
|
+
// Union Type
|
|
51
|
+
type = 'union[' + fieldType.map(t => SchemaExtractor.getType(t.type || t)).join(',') + ']'
|
|
52
|
+
} else if (fieldType === 'array') {
|
|
53
|
+
// Array Type
|
|
54
|
+
array = true
|
|
55
|
+
const nestedType = field.type.itemsType.typeName
|
|
56
|
+
type = SchemaExtractor.getType(nestedType)
|
|
57
|
+
} else if (fieldType === 'record') {
|
|
58
|
+
// Nested Record Type
|
|
59
|
+
type = 'object'
|
|
60
|
+
ref = `#/components/schemas/${field.type.name}`
|
|
61
|
+
if (!SchemaExtractor.extractSchema(field.type, builder, depth + 1, this)) {
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
} else if (fieldType === 'enum') {
|
|
65
|
+
enumValues = []
|
|
66
|
+
let i = 0
|
|
67
|
+
type = 'string'
|
|
68
|
+
while (field.type.symbols[i]) {
|
|
69
|
+
enumValues.push(field.type.symbols[i])
|
|
70
|
+
i += 1
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
// Primitive type
|
|
74
|
+
type = SchemaExtractor.getType(fieldType.type || fieldType)
|
|
75
|
+
if (fieldType === 'bytes') {
|
|
76
|
+
format = 'byte'
|
|
77
|
+
} else if (fieldType === 'int') {
|
|
78
|
+
format = 'int32'
|
|
79
|
+
} else if (fieldType === 'long') {
|
|
80
|
+
format = 'int64'
|
|
81
|
+
} else if (fieldType === 'float') {
|
|
82
|
+
format = 'float'
|
|
83
|
+
} else if (fieldType === 'double') {
|
|
84
|
+
format = 'double'
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return builder.addProperty(schemaName, fieldName, array, type, description, ref, format, enumValues)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static extractSchema (schema, builder, depth, extractor) {
|
|
92
|
+
depth += 1
|
|
93
|
+
const schemaName = schema.name
|
|
94
|
+
if (extractor) {
|
|
95
|
+
// if we already have a defined extractor, this is a nested schema. create a new extractor for the nested
|
|
96
|
+
// schema, ensure it is added to our schema builder's cache, and replace the builders iterator with our
|
|
97
|
+
// nested schema iterator / extractor. Once complete, add the new schema to our builder's schemas.
|
|
98
|
+
const nestedSchemaExtractor = new SchemaExtractor(schema)
|
|
99
|
+
builder.iterator = nestedSchemaExtractor
|
|
100
|
+
const nestedSchema = SchemaBuilder.getSchema(schemaName, nestedSchemaExtractor, builder)
|
|
101
|
+
for (const nestedSubSchemaName in nestedSchema.components.schemas) {
|
|
102
|
+
if (nestedSchema.components.schemas.hasOwnProperty(nestedSubSchemaName)) {
|
|
103
|
+
builder.schema.components.schemas[nestedSubSchemaName] = nestedSchema.components.schemas[nestedSubSchemaName]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return true
|
|
107
|
+
} else {
|
|
108
|
+
if (!builder.shouldExtractSchema(schemaName, depth)) {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
for (const field of schema.fields) {
|
|
112
|
+
if (!this.extractProperty(field, schemaName, field.name, builder, depth)) {
|
|
113
|
+
log.warn(`DSM: Unable to extract field with name: ${field.name} from Avro schema with name: ${schemaName}`)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return true
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static extractSchemas (descriptor, dataStreamsProcessor) {
|
|
121
|
+
return dataStreamsProcessor.getSchema(descriptor.name, new SchemaExtractor(descriptor))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
iterateOverSchema (builder) {
|
|
125
|
+
this.constructor.extractSchema(this.schema, builder, 0)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static attachSchemaOnSpan (args, span, operation, tracer) {
|
|
129
|
+
const { messageClass } = args
|
|
130
|
+
const descriptor = messageClass?.constructor?.type ?? messageClass
|
|
131
|
+
|
|
132
|
+
if (!descriptor || !span) {
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (span.context()._tags[SCHEMA_TYPE] && operation === 'serialization') {
|
|
137
|
+
// we have already added a schema to this span, this call is an encode of nested schema types
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
span.setTag(SCHEMA_TYPE, AVRO)
|
|
142
|
+
span.setTag(SCHEMA_NAME, descriptor.name)
|
|
143
|
+
span.setTag(SCHEMA_OPERATION, operation)
|
|
144
|
+
|
|
145
|
+
if (!tracer._dataStreamsProcessor.canSampleSchema(operation)) {
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// if the span is unsampled, do not sample the schema
|
|
150
|
+
if (!tracer._prioritySampler.isSampled(span)) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const weight = tracer._dataStreamsProcessor.trySampleSchema(operation)
|
|
155
|
+
if (weight === 0) {
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const schemaData = SchemaBuilder.getSchemaDefinition(
|
|
160
|
+
this.extractSchemas(descriptor, tracer._dataStreamsProcessor)
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
span.setTag(SCHEMA_DEFINITION, schemaData.definition)
|
|
164
|
+
span.setTag(SCHEMA_WEIGHT, weight)
|
|
165
|
+
span.setTag(SCHEMA_ID, schemaData.id)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = SchemaExtractor
|
|
@@ -4,6 +4,7 @@ const BaseAwsSdkPlugin = require('../base')
|
|
|
4
4
|
|
|
5
5
|
class EventBridge extends BaseAwsSdkPlugin {
|
|
6
6
|
static get id () { return 'eventbridge' }
|
|
7
|
+
static get isPayloadReporter () { return true }
|
|
7
8
|
|
|
8
9
|
generateTags (params, operation, response) {
|
|
9
10
|
if (!params || !params.source) return {}
|
|
@@ -10,6 +10,7 @@ const { storage } = require('../../../datadog-core')
|
|
|
10
10
|
class Kinesis extends BaseAwsSdkPlugin {
|
|
11
11
|
static get id () { return 'kinesis' }
|
|
12
12
|
static get peerServicePrecursors () { return ['streamname'] }
|
|
13
|
+
static get isPayloadReporter () { return true }
|
|
13
14
|
|
|
14
15
|
constructor (...args) {
|
|
15
16
|
super(...args)
|
|
@@ -5,6 +5,7 @@ const BaseAwsSdkPlugin = require('../base')
|
|
|
5
5
|
class S3 extends BaseAwsSdkPlugin {
|
|
6
6
|
static get id () { return 's3' }
|
|
7
7
|
static get peerServicePrecursors () { return ['bucketname'] }
|
|
8
|
+
static get isPayloadReporter () { return true }
|
|
8
9
|
|
|
9
10
|
generateTags (params, operation, response) {
|
|
10
11
|
const tags = {}
|
|
@@ -9,6 +9,7 @@ const { DsmPathwayCodec } = require('../../../dd-trace/src/datastreams/pathway')
|
|
|
9
9
|
class Sqs extends BaseAwsSdkPlugin {
|
|
10
10
|
static get id () { return 'sqs' }
|
|
11
11
|
static get peerServicePrecursors () { return ['queuename'] }
|
|
12
|
+
static get isPayloadReporter () { return true }
|
|
12
13
|
|
|
13
14
|
constructor (...args) {
|
|
14
15
|
super(...args)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
5
|
+
const serverless = require('../../dd-trace/src/plugins/util/serverless')
|
|
6
|
+
const web = require('../../dd-trace/src/plugins/util/web')
|
|
7
|
+
|
|
8
|
+
const triggerMap = {
|
|
9
|
+
deleteRequest: 'Http',
|
|
10
|
+
http: 'Http',
|
|
11
|
+
get: 'Http',
|
|
12
|
+
patch: 'Http',
|
|
13
|
+
post: 'Http',
|
|
14
|
+
put: 'Http'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class AzureFunctionsPlugin extends TracingPlugin {
|
|
18
|
+
static get id () { return 'azure-functions' }
|
|
19
|
+
static get operation () { return 'invoke' }
|
|
20
|
+
static get kind () { return 'server' }
|
|
21
|
+
static get type () { return 'serverless' }
|
|
22
|
+
|
|
23
|
+
static get prefix () { return 'tracing:datadog:azure-functions:invoke' }
|
|
24
|
+
|
|
25
|
+
bindStart (ctx) {
|
|
26
|
+
const { functionName, methodName } = ctx
|
|
27
|
+
const store = storage.getStore()
|
|
28
|
+
|
|
29
|
+
const span = this.startSpan(this.operationName(), {
|
|
30
|
+
service: this.serviceName(),
|
|
31
|
+
type: 'serverless',
|
|
32
|
+
meta: {
|
|
33
|
+
'aas.function.name': functionName,
|
|
34
|
+
'aas.function.trigger': mapTriggerTag(methodName)
|
|
35
|
+
}
|
|
36
|
+
}, false)
|
|
37
|
+
|
|
38
|
+
ctx.span = span
|
|
39
|
+
ctx.parentStore = store
|
|
40
|
+
ctx.currentStore = { ...store, span }
|
|
41
|
+
|
|
42
|
+
return ctx.currentStore
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
error (ctx) {
|
|
46
|
+
this.addError(ctx.error)
|
|
47
|
+
ctx.currentStore.span.setTag('error.message', ctx.error)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
asyncEnd (ctx) {
|
|
51
|
+
const { httpRequest, result = {} } = ctx
|
|
52
|
+
const path = (new URL(httpRequest.url)).pathname
|
|
53
|
+
const req = {
|
|
54
|
+
method: httpRequest.method,
|
|
55
|
+
headers: Object.fromEntries(httpRequest.headers.entries()),
|
|
56
|
+
url: path
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const context = web.patch(req)
|
|
60
|
+
context.config = this.config
|
|
61
|
+
context.paths = [path]
|
|
62
|
+
context.res = { statusCode: result.status }
|
|
63
|
+
context.span = ctx.currentStore.span
|
|
64
|
+
|
|
65
|
+
serverless.finishSpan(context)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
configure (config) {
|
|
69
|
+
return super.configure(web.normalizeConfig(config))
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function mapTriggerTag (methodName) {
|
|
74
|
+
return triggerMap[methodName] || 'Unknown'
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = AzureFunctionsPlugin
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { entryTags } = require('../../datadog-code-origin')
|
|
4
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
5
|
+
const web = require('../../dd-trace/src/plugins/util/web')
|
|
6
|
+
|
|
7
|
+
const kCodeOriginForSpansTagsSym = Symbol('datadog.codeOriginForSpansTags')
|
|
8
|
+
|
|
9
|
+
class FastifyCodeOriginForSpansPlugin extends Plugin {
|
|
10
|
+
static get id () {
|
|
11
|
+
return 'fastify'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
constructor (...args) {
|
|
15
|
+
super(...args)
|
|
16
|
+
|
|
17
|
+
this.addSub('apm:fastify:request:handle', ({ req, routeConfig }) => {
|
|
18
|
+
const tags = routeConfig?.[kCodeOriginForSpansTagsSym]
|
|
19
|
+
if (!tags) return
|
|
20
|
+
const context = web.getContext(req)
|
|
21
|
+
context.span?.addTags(tags)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
this.addSub('apm:fastify:route:added', ({ routeOptions, onRoute }) => {
|
|
25
|
+
if (!routeOptions.config) routeOptions.config = {}
|
|
26
|
+
routeOptions.config[kCodeOriginForSpansTagsSym] = entryTags(onRoute)
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = FastifyCodeOriginForSpansPlugin
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const FastifyTracingPlugin = require('./tracing')
|
|
4
|
+
const FastifyCodeOriginForSpansPlugin = require('./code_origin')
|
|
5
|
+
const CompositePlugin = require('../../dd-trace/src/plugins/composite')
|
|
4
6
|
|
|
5
|
-
class FastifyPlugin extends
|
|
6
|
-
static get id () {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
this.addSub('apm:fastify:request:handle', ({ req }) => {
|
|
14
|
-
this.setFramework(req, 'fastify', this.config)
|
|
15
|
-
})
|
|
7
|
+
class FastifyPlugin extends CompositePlugin {
|
|
8
|
+
static get id () { return 'fastify' }
|
|
9
|
+
static get plugins () {
|
|
10
|
+
return {
|
|
11
|
+
tracing: FastifyTracingPlugin,
|
|
12
|
+
codeOriginForSpans: FastifyCodeOriginForSpansPlugin
|
|
13
|
+
}
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
16
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const RouterPlugin = require('../../datadog-plugin-router/src')
|
|
4
|
+
|
|
5
|
+
class FastifyTracingPlugin extends RouterPlugin {
|
|
6
|
+
static get id () {
|
|
7
|
+
return 'fastify'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
constructor (...args) {
|
|
11
|
+
super(...args)
|
|
12
|
+
|
|
13
|
+
this.addSub('apm:fastify:request:handle', ({ req }) => {
|
|
14
|
+
this.setFramework(req, 'fastify', this.config)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = FastifyTracingPlugin
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { getMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
3
4
|
const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
|
|
4
5
|
|
|
5
6
|
class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
|
|
@@ -11,7 +12,7 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
|
|
|
11
12
|
const topic = subscription.metadata && subscription.metadata.topic
|
|
12
13
|
const childOf = this.tracer.extract('text_map', message.attributes) || null
|
|
13
14
|
|
|
14
|
-
this.startSpan({
|
|
15
|
+
const span = this.startSpan({
|
|
15
16
|
childOf,
|
|
16
17
|
resource: topic,
|
|
17
18
|
type: 'worker',
|
|
@@ -23,6 +24,12 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
|
|
|
23
24
|
'pubsub.ack': 0
|
|
24
25
|
}
|
|
25
26
|
})
|
|
27
|
+
if (this.config.dsmEnabled && message?.attributes) {
|
|
28
|
+
const payloadSize = getMessageSize(message)
|
|
29
|
+
this.tracer.decodeDataStreamsContext(message.attributes)
|
|
30
|
+
this.tracer
|
|
31
|
+
.setCheckpoint(['direction:in', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
|
|
32
|
+
}
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
finish (message) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
|
|
4
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
5
|
+
const { getHeadersSize } = require('../../dd-trace/src/datastreams/processor')
|
|
4
6
|
|
|
5
7
|
class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
|
|
6
8
|
static get id () { return 'google-cloud-pubsub' }
|
|
@@ -25,6 +27,12 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
|
|
|
25
27
|
msg.attributes = {}
|
|
26
28
|
}
|
|
27
29
|
this.tracer.inject(span, 'text_map', msg.attributes)
|
|
30
|
+
if (this.config.dsmEnabled) {
|
|
31
|
+
const payloadSize = getHeadersSize(msg)
|
|
32
|
+
const dataStreamsContext = this.tracer
|
|
33
|
+
.setCheckpoint(['direction:out', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
|
|
34
|
+
DsmPathwayCodec.encode(dataStreamsContext, msg.attributes)
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
}
|
|
@@ -5,14 +5,17 @@ class KafkajsBatchConsumerPlugin extends ConsumerPlugin {
|
|
|
5
5
|
static get id () { return 'kafkajs' }
|
|
6
6
|
static get operation () { return 'consume-batch' }
|
|
7
7
|
|
|
8
|
-
start ({ topic, partition, messages, groupId }) {
|
|
8
|
+
start ({ topic, partition, messages, groupId, clusterId }) {
|
|
9
9
|
if (!this.config.dsmEnabled) return
|
|
10
10
|
for (const message of messages) {
|
|
11
11
|
if (!message || !message.headers) continue
|
|
12
12
|
const payloadSize = getMessageSize(message)
|
|
13
13
|
this.tracer.decodeDataStreamsContext(message.headers)
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const edgeTags = ['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka']
|
|
15
|
+
if (clusterId) {
|
|
16
|
+
edgeTags.push(`kafka_cluster_id:${clusterId}`)
|
|
17
|
+
}
|
|
18
|
+
this.tracer.setCheckpoint(edgeTags, null, payloadSize)
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
}
|