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.
Files changed (156) hide show
  1. package/LICENSE-3rdparty.csv +1 -1
  2. package/ext/types.d.ts +1 -0
  3. package/ext/types.js +1 -0
  4. package/index.d.ts +361 -0
  5. package/package.json +18 -13
  6. package/packages/datadog-code-origin/index.js +38 -0
  7. package/packages/datadog-core/index.js +2 -2
  8. package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
  9. package/packages/datadog-esbuild/index.js +4 -2
  10. package/packages/datadog-instrumentations/src/amqplib.js +65 -5
  11. package/packages/datadog-instrumentations/src/avsc.js +37 -0
  12. package/packages/datadog-instrumentations/src/azure-functions.js +48 -0
  13. package/packages/datadog-instrumentations/src/child_process.js +144 -27
  14. package/packages/datadog-instrumentations/src/express.js +37 -4
  15. package/packages/datadog-instrumentations/src/fastify.js +12 -1
  16. package/packages/datadog-instrumentations/src/fs.js +27 -7
  17. package/packages/datadog-instrumentations/src/helpers/hooks.js +6 -0
  18. package/packages/datadog-instrumentations/src/helpers/register.js +9 -0
  19. package/packages/datadog-instrumentations/src/jest.js +2 -1
  20. package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
  21. package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
  22. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
  23. package/packages/datadog-instrumentations/src/multer.js +37 -0
  24. package/packages/datadog-instrumentations/src/mysql2.js +220 -1
  25. package/packages/datadog-instrumentations/src/openai.js +2 -2
  26. package/packages/datadog-instrumentations/src/protobufjs.js +127 -0
  27. package/packages/datadog-instrumentations/src/url.js +84 -0
  28. package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
  29. package/packages/datadog-instrumentations/src/winston.js +22 -0
  30. package/packages/datadog-plugin-amqplib/src/consumer.js +4 -4
  31. package/packages/datadog-plugin-avsc/src/index.js +9 -0
  32. package/packages/datadog-plugin-avsc/src/schema_iterator.js +169 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  34. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -0
  36. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  37. package/packages/datadog-plugin-azure-functions/src/index.js +77 -0
  38. package/packages/datadog-plugin-fastify/src/code_origin.js +31 -0
  39. package/packages/datadog-plugin-fastify/src/index.js +10 -12
  40. package/packages/datadog-plugin-fastify/src/tracing.js +19 -0
  41. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +8 -1
  42. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
  43. package/packages/datadog-plugin-grpc/src/client.js +3 -0
  44. package/packages/datadog-plugin-grpc/src/server.js +3 -0
  45. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
  46. package/packages/datadog-plugin-kafkajs/src/consumer.js +8 -4
  47. package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
  48. package/packages/datadog-plugin-mocha/src/index.js +4 -1
  49. package/packages/datadog-plugin-openai/src/index.js +9 -1015
  50. package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
  51. package/packages/datadog-plugin-protobufjs/src/index.js +14 -0
  52. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +180 -0
  53. package/packages/dd-trace/src/appsec/addresses.js +8 -1
  54. package/packages/dd-trace/src/appsec/channels.js +7 -1
  55. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +13 -1
  56. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +8 -1
  57. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
  58. package/packages/dd-trace/src/appsec/iast/index.js +3 -0
  59. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +1 -0
  60. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +55 -7
  61. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +15 -0
  62. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -2
  63. package/packages/dd-trace/src/appsec/index.js +61 -43
  64. package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
  65. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +99 -0
  66. package/packages/dd-trace/src/appsec/rasp/index.js +27 -10
  67. package/packages/dd-trace/src/appsec/rasp/lfi.js +112 -0
  68. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +24 -4
  69. package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
  70. package/packages/dd-trace/src/appsec/rasp/utils.js +4 -2
  71. package/packages/dd-trace/src/appsec/recommended.json +3 -7
  72. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +6 -1
  73. package/packages/dd-trace/src/appsec/remote_config/index.js +10 -0
  74. package/packages/dd-trace/src/appsec/reporter.js +17 -9
  75. package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -3
  76. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +1 -1
  77. package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
  78. package/packages/dd-trace/src/azure_metadata.js +120 -0
  79. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
  80. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
  81. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -14
  82. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
  83. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
  84. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
  85. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
  86. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +53 -0
  87. package/packages/dd-trace/src/config.js +86 -6
  88. package/packages/dd-trace/src/constants.js +3 -1
  89. package/packages/dd-trace/src/datastreams/pathway.js +1 -0
  90. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +25 -17
  91. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
  92. package/packages/dd-trace/src/debugger/devtools_client/index.js +52 -5
  93. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +4 -4
  94. package/packages/dd-trace/src/debugger/devtools_client/send.js +29 -2
  95. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +187 -0
  96. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +40 -0
  97. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +252 -0
  98. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
  99. package/packages/dd-trace/src/debugger/devtools_client/state.js +19 -4
  100. package/packages/dd-trace/src/debugger/index.js +10 -3
  101. package/packages/dd-trace/src/exporters/common/request.js +8 -34
  102. package/packages/dd-trace/src/exporters/common/url-to-http-options-polyfill.js +31 -0
  103. package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
  104. package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
  105. package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
  106. package/packages/dd-trace/src/llmobs/index.js +103 -0
  107. package/packages/dd-trace/src/llmobs/noop.js +82 -0
  108. package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
  109. package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
  110. package/packages/dd-trace/src/llmobs/sdk.js +377 -0
  111. package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
  112. package/packages/dd-trace/src/llmobs/storage.js +7 -0
  113. package/packages/dd-trace/src/llmobs/tagger.js +322 -0
  114. package/packages/dd-trace/src/llmobs/util.js +176 -0
  115. package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
  116. package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
  117. package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
  118. package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
  119. package/packages/dd-trace/src/llmobs/writers/spans/base.js +49 -0
  120. package/packages/dd-trace/src/noop/proxy.js +3 -0
  121. package/packages/dd-trace/src/noop/span.js +3 -0
  122. package/packages/dd-trace/src/opentelemetry/span.js +1 -1
  123. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
  124. package/packages/dd-trace/src/opentracing/propagation/text_map.js +73 -12
  125. package/packages/dd-trace/src/opentracing/span.js +12 -0
  126. package/packages/dd-trace/src/opentracing/tracer.js +8 -1
  127. package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
  128. package/packages/dd-trace/src/payload-tagging/index.js +1 -1
  129. package/packages/dd-trace/src/payload-tagging/jsonpath-plus.js +2094 -0
  130. package/packages/dd-trace/src/plugin_manager.js +4 -2
  131. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -0
  132. package/packages/dd-trace/src/plugins/index.js +3 -0
  133. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  134. package/packages/dd-trace/src/plugins/outbound.js +9 -0
  135. package/packages/dd-trace/src/plugins/schema.js +35 -0
  136. package/packages/dd-trace/src/plugins/util/ci.js +23 -1
  137. package/packages/dd-trace/src/plugins/util/serverless.js +7 -0
  138. package/packages/dd-trace/src/plugins/util/stacktrace.js +94 -0
  139. package/packages/dd-trace/src/plugins/util/tags.js +7 -0
  140. package/packages/dd-trace/src/plugins/util/test.js +20 -22
  141. package/packages/dd-trace/src/plugins/util/web.js +6 -4
  142. package/packages/dd-trace/src/priority_sampler.js +16 -0
  143. package/packages/dd-trace/src/profiling/config.js +3 -1
  144. package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
  145. package/packages/dd-trace/src/profiling/profiler.js +24 -14
  146. package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
  147. package/packages/dd-trace/src/profiling/profilers/wall.js +95 -66
  148. package/packages/dd-trace/src/proxy.js +20 -1
  149. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
  150. package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +12 -0
  151. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
  152. package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +12 -0
  153. package/packages/dd-trace/src/span_processor.js +5 -0
  154. package/packages/dd-trace/src/telemetry/index.js +11 -1
  155. package/packages/datadog-core/src/storage/async_resource.js +0 -108
  156. 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': fields.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:${queue}`, 'type:rabbitmq'], span, payloadSize)
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 RouterPlugin = require('../../datadog-plugin-router/src')
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 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
- })
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
  }
@@ -64,6 +64,9 @@ class GrpcClientPlugin extends ClientPlugin {
64
64
 
65
65
  error ({ span, error }) {
66
66
  this.addCode(span, error.code)
67
+ if (error.code && !this._tracerConfig.grpc.client.error.statuses.includes(error.code)) {
68
+ return
69
+ }
67
70
  this.addError(error, span)
68
71
  }
69
72
 
@@ -70,6 +70,9 @@ class GrpcServerPlugin extends ServerPlugin {
70
70
  if (!span) return
71
71
 
72
72
  this.addCode(span, error.code)
73
+ if (error.code && !this._tracerConfig.grpc.server.error.statuses.includes(error.code)) {
74
+ return
75
+ }
73
76
  this.addError(error)
74
77
  }
75
78
 
@@ -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
- this.tracer
15
- .setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'], null, payloadSize)
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
  }