dd-trace 5.97.0 → 5.99.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 (175) hide show
  1. package/LICENSE-3rdparty.csv +0 -1
  2. package/ext/tags.js +1 -0
  3. package/index.d.ts +35 -3
  4. package/package.json +48 -46
  5. package/packages/datadog-instrumentations/src/crypto.js +45 -0
  6. package/packages/datadog-instrumentations/src/cucumber.js +65 -3
  7. package/packages/datadog-instrumentations/src/cypress-config.js +153 -53
  8. package/packages/datadog-instrumentations/src/dns.js +24 -56
  9. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  10. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +74 -0
  11. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +4 -1
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  13. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +10 -3
  14. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  15. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/modelcontextprotocol-sdk.js +59 -0
  16. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +11 -2
  17. package/packages/datadog-instrumentations/src/jest.js +104 -12
  18. package/packages/datadog-instrumentations/src/mocha/utils.js +8 -0
  19. package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +7 -0
  20. package/packages/datadog-instrumentations/src/pino.js +4 -28
  21. package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +27 -0
  22. package/packages/datadog-instrumentations/src/playwright.js +5 -17
  23. package/packages/datadog-instrumentations/src/redis.js +12 -6
  24. package/packages/datadog-instrumentations/src/stripe.js +38 -24
  25. package/packages/datadog-instrumentations/src/vitest.js +32 -4
  26. package/packages/datadog-instrumentations/src/zlib.js +29 -0
  27. package/packages/datadog-plugin-aws-sdk/src/base.js +2 -3
  28. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
  29. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  31. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
  32. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  34. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +8 -15
  35. package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -9
  36. package/packages/datadog-plugin-cucumber/src/index.js +8 -2
  37. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +114 -6
  38. package/packages/datadog-plugin-cypress/src/index.js +59 -2
  39. package/packages/datadog-plugin-cypress/src/source-map-utils.js +48 -1
  40. package/packages/datadog-plugin-fs/src/index.js +1 -1
  41. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
  42. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
  43. package/packages/datadog-plugin-http/src/client.js +1 -1
  44. package/packages/datadog-plugin-http/src/server.js +21 -13
  45. package/packages/datadog-plugin-http2/src/client.js +1 -1
  46. package/packages/datadog-plugin-http2/src/server.js +10 -2
  47. package/packages/datadog-plugin-jest/src/index.js +2 -2
  48. package/packages/datadog-plugin-mocha/src/index.js +1 -2
  49. package/packages/datadog-plugin-modelcontextprotocol-sdk/src/index.js +24 -0
  50. package/packages/datadog-plugin-modelcontextprotocol-sdk/src/tracing.js +55 -0
  51. package/packages/datadog-plugin-mongodb-core/src/index.js +4 -9
  52. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  53. package/packages/datadog-plugin-next/src/index.js +8 -2
  54. package/packages/datadog-plugin-pg/src/index.js +1 -1
  55. package/packages/datadog-plugin-playwright/src/index.js +2 -3
  56. package/packages/datadog-plugin-tedious/src/index.js +1 -1
  57. package/packages/datadog-plugin-vitest/src/index.js +14 -6
  58. package/packages/datadog-plugin-ws/src/close.js +3 -1
  59. package/packages/datadog-plugin-ws/src/producer.js +2 -0
  60. package/packages/datadog-plugin-ws/src/receiver.js +2 -1
  61. package/packages/dd-trace/src/aiguard/channels.js +8 -0
  62. package/packages/dd-trace/src/aiguard/index.js +7 -3
  63. package/packages/dd-trace/src/aiguard/sdk.js +66 -22
  64. package/packages/dd-trace/src/aiguard/tags.js +1 -0
  65. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
  66. package/packages/dd-trace/src/appsec/blocking.js +62 -34
  67. package/packages/dd-trace/src/appsec/graphql.js +6 -6
  68. package/packages/dd-trace/src/appsec/index.js +9 -11
  69. package/packages/dd-trace/src/appsec/rasp/command_injection.js +4 -5
  70. package/packages/dd-trace/src/appsec/rasp/lfi.js +8 -4
  71. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +5 -10
  72. package/packages/dd-trace/src/appsec/rasp/ssrf.js +5 -6
  73. package/packages/dd-trace/src/appsec/recommended.json +2438 -13
  74. package/packages/dd-trace/src/appsec/reporter.js +6 -5
  75. package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
  76. package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
  77. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +6 -10
  78. package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
  79. package/packages/dd-trace/src/appsec/store.js +50 -0
  80. package/packages/dd-trace/src/appsec/waf/index.js +3 -5
  81. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
  82. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
  83. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
  84. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  85. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -4
  86. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
  87. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -5
  88. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +3 -4
  89. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +6 -6
  90. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +2 -2
  91. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
  92. package/packages/dd-trace/src/config/config-types.d.ts +0 -4
  93. package/packages/dd-trace/src/config/defaults.js +10 -11
  94. package/packages/dd-trace/src/config/generated-config-types.d.ts +14 -8
  95. package/packages/dd-trace/src/config/index.js +49 -32
  96. package/packages/dd-trace/src/config/parsers.js +26 -9
  97. package/packages/dd-trace/src/config/supported-configurations.json +86 -33
  98. package/packages/dd-trace/src/constants.js +1 -0
  99. package/packages/dd-trace/src/debugger/config.js +2 -0
  100. package/packages/dd-trace/src/debugger/devtools_client/send.js +25 -5
  101. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
  102. package/packages/dd-trace/src/encode/0.4.js +11 -11
  103. package/packages/dd-trace/src/encode/span-stats.js +4 -1
  104. package/packages/dd-trace/src/exporters/agent/index.js +0 -1
  105. package/packages/dd-trace/src/exporters/agent/writer.js +1 -2
  106. package/packages/dd-trace/src/exporters/agentless/writer.js +3 -3
  107. package/packages/dd-trace/src/exporters/common/util.js +2 -2
  108. package/packages/dd-trace/src/id.js +2 -0
  109. package/packages/dd-trace/src/index.js +2 -5
  110. package/packages/dd-trace/src/lambda/handler.js +1 -3
  111. package/packages/dd-trace/src/llmobs/plugins/{anthropic.js → anthropic/index.js} +5 -63
  112. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +106 -0
  113. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +3 -2
  114. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +3 -2
  115. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +2 -1
  116. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +0 -49
  117. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +2 -1
  118. package/packages/dd-trace/src/llmobs/plugins/langchain/messages.js +76 -0
  119. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -26
  120. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/index.js +68 -0
  121. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +57 -0
  122. package/packages/dd-trace/src/llmobs/sdk.js +2 -2
  123. package/packages/dd-trace/src/log/index.js +0 -10
  124. package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +103 -0
  125. package/packages/dd-trace/src/openfeature/flagging_provider.js +3 -0
  126. package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
  127. package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
  128. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  129. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +3 -2
  130. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  131. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +3 -2
  132. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +19 -51
  133. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
  134. package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
  135. package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
  136. package/packages/dd-trace/src/opentelemetry/trace/index.js +70 -0
  137. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +74 -0
  138. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +342 -0
  139. package/packages/dd-trace/src/opentelemetry/tracer.js +9 -11
  140. package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -10
  141. package/packages/dd-trace/src/opentracing/span.js +1 -1
  142. package/packages/dd-trace/src/opentracing/tracer.js +17 -5
  143. package/packages/dd-trace/src/plugins/index.js +1 -0
  144. package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
  145. package/packages/dd-trace/src/plugins/plugin.js +6 -11
  146. package/packages/dd-trace/src/plugins/storage.js +2 -2
  147. package/packages/dd-trace/src/plugins/tracing.js +22 -5
  148. package/packages/dd-trace/src/plugins/util/test.js +128 -5
  149. package/packages/dd-trace/src/plugins/util/url.js +2 -1
  150. package/packages/dd-trace/src/plugins/util/web.js +6 -88
  151. package/packages/dd-trace/src/profiling/profiler.js +34 -77
  152. package/packages/dd-trace/src/profiling/profilers/event_plugins/crypto.js +32 -0
  153. package/packages/dd-trace/src/profiling/profilers/event_plugins/zlib.js +19 -0
  154. package/packages/dd-trace/src/profiling/profilers/events.js +35 -0
  155. package/packages/dd-trace/src/proxy.js +3 -4
  156. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +17 -13
  157. package/packages/dd-trace/src/service-naming/index.js +1 -1
  158. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
  159. package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
  160. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
  161. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
  162. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +21 -1
  163. package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
  164. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
  165. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +15 -1
  166. package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
  167. package/packages/dd-trace/src/span_processor.js +1 -2
  168. package/packages/dd-trace/src/span_stats.js +5 -1
  169. package/packages/dd-trace/src/tagger.js +2 -2
  170. package/packages/dd-trace/src/telemetry/send-data.js +5 -7
  171. package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
  172. package/vendor/dist/protobufjs/index.js +1 -1
  173. package/packages/dd-trace/src/log/utils.js +0 -16
  174. package/vendor/dist/ignore/LICENSE +0 -21
  175. package/vendor/dist/ignore/index.js +0 -1
@@ -9,7 +9,6 @@ const { getEnvironmentVariable } = require('../../config/helper')
9
9
  const satisfies = require('../../../../../vendor/dist/semifies')
10
10
 
11
11
  const istanbul = require('../../../../../vendor/dist/istanbul-lib-coverage')
12
- const ignore = require('../../../../../vendor/dist/ignore')
13
12
 
14
13
  const id = require('../../id')
15
14
  const {
@@ -137,6 +136,7 @@ const JEST_WORKER_TRACE_PAYLOAD_CODE = 60
137
136
  const JEST_WORKER_COVERAGE_PAYLOAD_CODE = 61
138
137
  const JEST_WORKER_LOGS_PAYLOAD_CODE = 62
139
138
  const JEST_WORKER_TELEMETRY_PAYLOAD_CODE = 63
139
+ const JEST_WORKER_QUARANTINE_PAYLOAD_CODE = 64
140
140
 
141
141
  // cucumber worker variables
142
142
  const CUCUMBER_WORKER_TRACE_PAYLOAD_CODE = 70
@@ -262,6 +262,7 @@ module.exports = {
262
262
  JEST_WORKER_COVERAGE_PAYLOAD_CODE,
263
263
  JEST_WORKER_LOGS_PAYLOAD_CODE,
264
264
  JEST_WORKER_TELEMETRY_PAYLOAD_CODE,
265
+ JEST_WORKER_QUARANTINE_PAYLOAD_CODE,
265
266
  CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
266
267
  MOCHA_WORKER_TRACE_PAYLOAD_CODE,
267
268
  PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE,
@@ -669,24 +670,146 @@ function getCodeOwnersFileEntries (rootDir) {
669
670
  const trimmed = content.trim()
670
671
  if (trimmed === '') continue
671
672
  const [pattern, ...owners] = trimmed.split(/\s+/)
672
- entries.push({ pattern, owners })
673
+ entries.push(setCodeOwnersPatternRegex({ pattern, owners }))
673
674
  }
674
675
  // Reverse because rules defined last take precedence
675
676
  return entries.reverse()
676
677
  }
677
678
 
678
- const codeOwnersPerFileName = new Map()
679
+ const codeOwnersPerEntries = new WeakMap()
680
+
681
+ /**
682
+ * @param {string} character
683
+ * @returns {string}
684
+ */
685
+ function escapeRegexCharacter (character) {
686
+ return character.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw`\$&`)
687
+ }
688
+
689
+ /**
690
+ * @param {string} pattern
691
+ * @returns {boolean}
692
+ */
693
+ function hasUnescapedWildcard (pattern) {
694
+ for (let i = 0; i < pattern.length; i++) {
695
+ const character = pattern[i]
696
+ if (character === '\\') {
697
+ i++
698
+ } else if (character === '*' || character === '?') {
699
+ return true
700
+ }
701
+ }
702
+ return false
703
+ }
704
+
705
+ /**
706
+ * @param {string} pattern
707
+ * @returns {string}
708
+ */
709
+ function codeOwnersPatternToRegexSource (pattern) {
710
+ let source = ''
711
+ for (let i = 0; i < pattern.length; i++) {
712
+ const character = pattern[i]
713
+
714
+ if (character === '\\') {
715
+ const escapedCharacter = pattern[i + 1]
716
+ source += escapedCharacter === undefined
717
+ ? escapeRegexCharacter(character)
718
+ : escapeRegexCharacter(escapedCharacter)
719
+ i++
720
+ } else if (character === '*') {
721
+ if (pattern[i + 1] === '*') {
722
+ if (pattern[i + 2] === '/') {
723
+ source += '(?:.*/)?'
724
+ i += 2
725
+ } else {
726
+ source += '.*'
727
+ i++
728
+ }
729
+ } else {
730
+ source += '[^/]*'
731
+ }
732
+ } else if (character === '?') {
733
+ source += '[^/]'
734
+ } else {
735
+ source += escapeRegexCharacter(character)
736
+ }
737
+ }
738
+ return source
739
+ }
740
+
741
+ /**
742
+ * @param {string} pattern
743
+ * @returns {RegExp|null}
744
+ */
745
+ function getCodeOwnersPatternRegex (pattern) {
746
+ if (!pattern || pattern[0] === '!') {
747
+ return null
748
+ }
749
+
750
+ const directoryOnly = pattern.endsWith('/')
751
+ const normalizedPattern = pattern.replace(/^\/+/, '').replace(/\/+$/, '')
752
+ const anchored = pattern.startsWith('/') || normalizedPattern.includes('/')
753
+
754
+ if (!normalizedPattern) {
755
+ return null
756
+ }
757
+
758
+ const lastSlashIndex = normalizedPattern.lastIndexOf('/')
759
+ const lastSegment = lastSlashIndex === -1 ? normalizedPattern : normalizedPattern.slice(lastSlashIndex + 1)
760
+ const descendantSuffix = directoryOnly || !hasUnescapedWildcard(lastSegment) ? '(?:/.*)?' : ''
761
+ const patternSource = codeOwnersPatternToRegexSource(normalizedPattern)
762
+ const regexSource = anchored
763
+ ? `^${patternSource}${descendantSuffix}$`
764
+ : `(?:^|/)${patternSource}${descendantSuffix}$`
765
+
766
+ return new RegExp(regexSource)
767
+ }
768
+
769
+ function setCodeOwnersPatternRegex (entry) {
770
+ Object.defineProperty(entry, 'regex', {
771
+ configurable: true,
772
+ value: getCodeOwnersPatternRegex(entry.pattern),
773
+ writable: true,
774
+ })
775
+ return entry
776
+ }
777
+
778
+ /**
779
+ * Match a repository-relative filename against a CODEOWNERS pattern.
780
+ * See GitHub's CODEOWNERS pattern rules:
781
+ * https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
782
+ *
783
+ * @param {RegExp|null} regex
784
+ * @param {string} filename
785
+ * @returns {boolean}
786
+ */
787
+ function isCodeOwnersPatternMatch (regex, filename) {
788
+ if (!regex || !filename) {
789
+ return false
790
+ }
791
+
792
+ const normalizedFilename = filename.replaceAll('\\', '/').replace(/^\/+/, '')
793
+ return regex.test(normalizedFilename)
794
+ }
679
795
 
680
796
  function getCodeOwnersForFilename (filename, entries) {
681
797
  if (!entries) {
682
798
  return null
683
799
  }
684
- if (codeOwnersPerFileName.has(filename)) {
800
+ let codeOwnersPerFileName = codeOwnersPerEntries.get(entries)
801
+
802
+ if (!codeOwnersPerFileName) {
803
+ codeOwnersPerFileName = new Map()
804
+ codeOwnersPerEntries.set(entries, codeOwnersPerFileName)
805
+ } else if (codeOwnersPerFileName.has(filename)) {
685
806
  return codeOwnersPerFileName.get(filename)
686
807
  }
808
+
687
809
  for (const entry of entries) {
688
810
  try {
689
- const isResponsible = ignore().add(entry.pattern).ignores(filename)
811
+ const regex = entry.regex === undefined ? setCodeOwnersPatternRegex(entry).regex : entry.regex
812
+ const isResponsible = isCodeOwnersPatternMatch(regex, filename)
690
813
  if (isResponsible) {
691
814
  const codeOwners = JSON.stringify(entry.owners)
692
815
  codeOwnersPerFileName.set(filename, codeOwners)
@@ -31,7 +31,8 @@ function extractURL (req) {
31
31
  }
32
32
 
33
33
  function getProtocol (req) {
34
- return (req.socket?.encrypted || req.connection?.encrypted) ? 'https' : 'http'
34
+ // Do not check deprecated `req.connection` property.
35
+ return req.socket?.encrypted ? 'https' : 'http'
35
36
  }
36
37
 
37
38
  /**
@@ -7,8 +7,9 @@ const log = require('../../log')
7
7
  const tags = require('../../../../../ext/tags')
8
8
  const types = require('../../../../../ext/types')
9
9
  const kinds = require('../../../../../ext/kinds')
10
- const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../constants')
10
+ const { ERROR_MESSAGE } = require('../../constants')
11
11
  const TracingPlugin = require('../tracing')
12
+ const { storage } = require('../../../../datadog-core')
12
13
  const urlFilter = require('./urlfilter')
13
14
  const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
14
15
  const { extractURL, obfuscateQs, calculateHttpEndpoint } = require('./url')
@@ -125,33 +126,13 @@ const web = {
125
126
  context.tracer = tracer
126
127
  context.span = span
127
128
  context.res = res
129
+ context.store = storage('legacy').getStore()
128
130
 
129
131
  this.setConfig(req, config)
130
132
  addRequestTags(context, this.TYPE)
131
133
 
132
134
  return span
133
135
  },
134
- wrap (req) {
135
- const context = contexts.get(req)
136
- if (!context.instrumented) {
137
- this.wrapEnd(context)
138
- context.instrumented = true
139
- }
140
- },
141
- // Start a span and activate a scope for a request.
142
- instrument (tracer, config, req, res, name, callback) {
143
- const span = this.startSpan(tracer, config, req, res, name)
144
-
145
- this.wrap(req)
146
-
147
- return callback && tracer.scope().activate(span, () => callback(span))
148
- },
149
-
150
- // Reactivate the request scope in case it was changed by a middleware.
151
- reactivate (req, fn) {
152
- return reactivate(req, fn)
153
- },
154
-
155
136
  // Add a route segment that will be used for the resource name.
156
137
  enterRoute (req, path) {
157
138
  if (typeof path === 'string') {
@@ -172,61 +153,6 @@ const web = {
172
153
  contexts.get(req).paths.pop()
173
154
  },
174
155
 
175
- // Start a new middleware span and activate a new scope with the span.
176
- wrapMiddleware (req, middleware, name, fn) {
177
- if (!this.active(req)) return fn()
178
-
179
- const context = contexts.get(req)
180
- const tracer = context.tracer
181
- const childOf = this.active(req)
182
- const config = context.config
183
- const traceCtx = context.traceCtx
184
-
185
- if (config.middleware === false) return this.bindAndWrapMiddlewareErrors(fn, req, tracer, childOf)
186
-
187
- const span = startSpanHelper(tracer, name, { childOf }, traceCtx, config)
188
-
189
- analyticsSampler.sample(span, config.measured)
190
-
191
- span.addTags({
192
- [RESOURCE_NAME]: middleware._name || middleware.name || '<anonymous>',
193
- })
194
-
195
- context.middleware.push(span)
196
-
197
- return tracer.scope().activate(span, fn)
198
- },
199
-
200
- // catch errors and apply to active span
201
- bindAndWrapMiddlewareErrors (fn, req, tracer, activeSpan) {
202
- try {
203
- return tracer.scope().bind(fn, activeSpan).apply(this, arguments)
204
- } catch (e) {
205
- web.addError(req, e) // TODO: remove when error formatting is moved to Span
206
- throw e
207
- }
208
- },
209
-
210
- // Finish the active middleware span.
211
- finish (req, error) {
212
- if (!this.active(req)) return
213
-
214
- const context = contexts.get(req)
215
- const span = context.middleware.pop()
216
-
217
- if (span) {
218
- if (error) {
219
- span.addTags({
220
- [ERROR_TYPE]: error.name,
221
- [ERROR_MESSAGE]: error.message,
222
- [ERROR_STACK]: error.stack,
223
- })
224
- }
225
-
226
- span.finish()
227
- }
228
- },
229
-
230
156
  // Register a callback to run before res.end() is called.
231
157
  beforeEnd (req, callback) {
232
158
  contexts.get(req).beforeEnd.push(callback)
@@ -278,7 +204,6 @@ const web = {
278
204
  startServerlessSpanWithInferredProxy (tracer, config, name, req, traceCtx) {
279
205
  const headers = req.headers
280
206
  const reqCtx = contexts.get(req)
281
- const { storage } = require('../../../../datadog-core')
282
207
  const store = storage('legacy').getStore()
283
208
  const pubsubSpan = store?.span?._name === 'pubsub.push.receive' ? store.span : null
284
209
 
@@ -391,7 +316,6 @@ const web = {
391
316
  }
392
317
  },
393
318
  wrapEnd (context) {
394
- const scope = context.tracer.scope()
395
319
  const req = context.req
396
320
  const res = context.res
397
321
  const end = res.end
@@ -406,7 +330,9 @@ const web = {
406
330
  return ends.get(this)
407
331
  },
408
332
  set (value) {
409
- ends.set(this, scope.bind(value, context.span))
333
+ ends.set(this, function () {
334
+ return storage('legacy').run(context.store, value, ...arguments)
335
+ })
410
336
  },
411
337
  })
412
338
  },
@@ -453,14 +379,6 @@ function splitHeader (str) {
453
379
  return typeof str === 'string' ? str.split(/\s*,\s*/) : []
454
380
  }
455
381
 
456
- function reactivate (req, fn) {
457
- const context = contexts.get(req)
458
-
459
- return context
460
- ? context.tracer.scope().activate(context.span, fn)
461
- : fn()
462
- }
463
-
464
382
  function addRequestTags (context, spanType) {
465
383
  const { req, span, inferredProxySpan, config } = context
466
384
  const url = extractURL(req)
@@ -12,12 +12,6 @@ const { isWebServerSpan, endpointNameFromTags, getStartedSpans } = require('./we
12
12
  const profileSubmittedChannel = dc.channel('datadog:profiling:profile-submitted')
13
13
  const spanFinishedChannel = dc.channel('dd-trace:span:finish')
14
14
 
15
- function logError (logger, ...args) {
16
- if (logger) {
17
- logger.error(...args)
18
- }
19
- }
20
-
21
15
  function findWebSpan (startedSpans, spanId) {
22
16
  for (let i = startedSpans.length; --i >= 0;) {
23
17
  const ispan = startedSpans[i]
@@ -71,33 +65,6 @@ class Profiler extends EventEmitter {
71
65
  return this.#config?.flushInterval
72
66
  }
73
67
 
74
- /**
75
- * @param {import('../config/config-base')} config - Tracer configuration
76
- */
77
- start (config) {
78
- // TODO: Unify with main logger and rewrite template strings to use printf formatting.
79
- const logger = {
80
- debug: log.debug.bind(log),
81
- info: log.info.bind(log),
82
- warn: log.warn.bind(log),
83
- error: log.error.bind(log),
84
- }
85
-
86
- // TODO: Rewrite this to not need to copy the config.
87
- const options = {
88
- ...config,
89
- logger,
90
- }
91
-
92
- try {
93
- return this._start(options)
94
- } catch (err) {
95
- logError(logger, 'Error starting profiler. For troubleshooting tips, see ' +
96
- '<https://dtdg.co/nodejs-profiler-troubleshooting>', err)
97
- return false
98
- }
99
- }
100
-
101
68
  get enabled () {
102
69
  return this.#enabled
103
70
  }
@@ -141,10 +108,6 @@ class Profiler extends EventEmitter {
141
108
  return fn()
142
109
  }
143
110
 
144
- #logError (err) {
145
- logError(this.#logger, err)
146
- }
147
-
148
111
  #getCompressionFn () {
149
112
  if (!this.#compressionFnInitialized) {
150
113
  this.#compressionFnInitialized = true
@@ -181,8 +144,8 @@ class Profiler extends EventEmitter {
181
144
  }
182
145
  break
183
146
  }
184
- } catch (err) {
185
- this.#logError(err)
147
+ } catch (error) {
148
+ log.error(error)
186
149
  }
187
150
  }
188
151
  return this.#compressionFn
@@ -191,41 +154,36 @@ class Profiler extends EventEmitter {
191
154
  /**
192
155
  * @param {import('../config/config-base')} options - Tracer configuration
193
156
  */
194
- _start (options) {
157
+ start (options) {
195
158
  if (this.enabled) return true
159
+ this.#enabled = true
196
160
 
197
161
  const config = this.#config = new Config(options)
198
-
199
162
  this.#logger = config.logger
200
- this.#enabled = true
201
- this._setInterval()
202
163
 
164
+ this._setInterval()
203
165
  // Log errors if the source map finder fails, but don't prevent the rest
204
166
  // of the profiler from running without source maps.
205
167
  let mapper
206
- try {
207
- const { setLogger, SourceMapper } = require('@datadog/pprof')
208
- setLogger(config.logger)
209
-
210
- if (config.sourceMap) {
211
- mapper = new SourceMapper(config.debugSourceMaps)
212
- mapper.loadDirectory(process.cwd())
213
- .then(() => {
214
- if (config.debugSourceMaps) {
215
- const count = mapper.infoMap.size
216
- this.#logger.debug(() => {
217
- return count === 0
218
- ? 'Found no source maps'
219
- : `Found source maps for following files: [${[...mapper.infoMap.keys()].join(', ')}]`
220
- })
221
- }
222
- })
223
- .catch((err) => {
224
- this.#logError(err)
225
- })
226
- }
227
- } catch (err) {
228
- this.#logError(err)
168
+ const { setLogger, SourceMapper } = require('@datadog/pprof')
169
+ setLogger(config.logger)
170
+
171
+ if (config.sourceMap) {
172
+ mapper = new SourceMapper(config.debugSourceMaps)
173
+ mapper.loadDirectory(process.cwd())
174
+ .then(() => {
175
+ if (config.debugSourceMaps) {
176
+ const count = mapper.infoMap.size
177
+ this.#logger.debug(() => {
178
+ return count === 0
179
+ ? 'Found no source maps'
180
+ : `Found source maps for following files: [${[...mapper.infoMap.keys()].join(', ')}]`
181
+ })
182
+ }
183
+ })
184
+ .catch((error) => {
185
+ log.error(error)
186
+ })
229
187
  }
230
188
 
231
189
  try {
@@ -246,12 +204,13 @@ class Profiler extends EventEmitter {
246
204
  }
247
205
 
248
206
  this._capture(this._timeoutInterval, start)
249
- return true
250
- } catch (e) {
251
- this.#logError(e)
207
+ } catch (error) {
208
+ log.error(error)
252
209
  this.#stop()
253
210
  return false
254
211
  }
212
+
213
+ return true
255
214
  }
256
215
 
257
216
  #nearOOMExport (profileType, encodedProfile, info) {
@@ -389,10 +348,10 @@ class Profiler extends EventEmitter {
389
348
  return `Collected ${profiler.type} profile: ` + profileJson
390
349
  })
391
350
  hasEncoded = true
392
- } catch (err) {
351
+ } catch (error) {
393
352
  // If encoding one of the profile types fails, we should still try to
394
353
  // encode and submit the other profile types.
395
- this.#logError(err)
354
+ log.error(error)
396
355
  }
397
356
  }))
398
357
 
@@ -401,8 +360,8 @@ class Profiler extends EventEmitter {
401
360
  profileSubmittedChannel.publish()
402
361
  this.#logger.debug('Submitted profiles')
403
362
  }
404
- } catch (err) {
405
- this.#logError(err)
363
+ } catch (error) {
364
+ log.error(error)
406
365
  this.#stop()
407
366
  }
408
367
  }
@@ -424,10 +383,8 @@ class Profiler extends EventEmitter {
424
383
  : undefined
425
384
  const exportSpec = { profiles, infos, start, end, tags, endpointCounts, customAttributes }
426
385
  const tasks = this.#config.exporters.map(exporter =>
427
- exporter.export(exportSpec).catch(err => {
428
- if (this.#logger) {
429
- this.#logger.warn(err)
430
- }
386
+ exporter.export(exportSpec).catch(error => {
387
+ log.warn(error)
431
388
  })
432
389
  )
433
390
 
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+
3
+ const EventPlugin = require('./event')
4
+
5
+ // Params captured on the instrumentation context that are safe to forward as pprof labels. Must be
6
+ // a subset of the names declared in asyncParamsByMethod in datadog-instrumentations/src/crypto.js.
7
+ const allowedParams = new Set([
8
+ 'algorithm', 'digest', 'iterations', 'keylen', 'offset', 'operation', 'size', 'type',
9
+ ])
10
+
11
+ class CryptoPlugin extends EventPlugin {
12
+ static id = 'crypto'
13
+
14
+ static operation = 'operation'
15
+
16
+ static entryType = 'crypto'
17
+
18
+ extendEvent (event, ctx) {
19
+ const detail = {}
20
+ for (const name of allowedParams) {
21
+ const value = ctx[name]
22
+ if (typeof value === 'string' || typeof value === 'number') {
23
+ detail[name] = value
24
+ }
25
+ }
26
+ event.detail = detail
27
+
28
+ return event
29
+ }
30
+ }
31
+
32
+ module.exports = CryptoPlugin
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const EventPlugin = require('./event')
4
+
5
+ class ZlibPlugin extends EventPlugin {
6
+ static id = 'zlib'
7
+
8
+ static operation = 'operation'
9
+
10
+ static entryType = 'zlib'
11
+
12
+ extendEvent (event, ctx) {
13
+ event.detail = { operation: ctx.operation }
14
+
15
+ return event
16
+ }
17
+ }
18
+
19
+ module.exports = ZlibPlugin
@@ -194,13 +194,46 @@ class FilesystemDecorator {
194
194
  }
195
195
  }
196
196
 
197
+ class ZlibDecorator {
198
+ constructor (stringTable) {
199
+ this.stringTable = stringTable
200
+ this.operationNameLabelKey = stringTable.dedup('operation')
201
+ }
202
+
203
+ decorateSample (sampleInput, item) {
204
+ sampleInput.label.push(labelFromStr(this.stringTable, this.operationNameLabelKey, item.detail.operation))
205
+ }
206
+ }
207
+
208
+ class CryptoDecorator {
209
+ constructor (stringTable) {
210
+ this.stringTable = stringTable
211
+ }
212
+
213
+ decorateSample (sampleInput, item) {
214
+ const labels = sampleInput.label
215
+ const stringTable = this.stringTable
216
+ for (const [key, value] of Object.entries(item.detail)) {
217
+ switch (typeof value) {
218
+ case 'string':
219
+ labels.push(labelFromStrStr(stringTable, key, value))
220
+ break
221
+ case 'number':
222
+ labels.push(new Label({ key: stringTable.dedup(key), num: value }))
223
+ }
224
+ }
225
+ }
226
+ }
227
+
197
228
  // Keys correspond to PerformanceEntry.entryType, values are constructor
198
229
  // functions for type-specific decorators.
199
230
  const decoratorTypes = {
231
+ crypto: CryptoDecorator,
200
232
  fs: FilesystemDecorator,
201
233
  dns: DNSDecorator,
202
234
  gc: GCDecorator,
203
235
  net: NetDecorator,
236
+ zlib: ZlibDecorator,
204
237
  }
205
238
 
206
239
  // Translates performance entries into pprof samples.
@@ -348,12 +381,14 @@ class DatadogInstrumentationEventSource {
348
381
  constructor (eventHandler, eventFilter) {
349
382
  // List all entries explicitly for bundlers to pick up the require calls correctly.
350
383
  const plugins = [
384
+ require('./event_plugins/crypto'),
351
385
  require('./event_plugins/dns_lookup'),
352
386
  require('./event_plugins/dns_lookupservice'),
353
387
  require('./event_plugins/dns_resolve'),
354
388
  require('./event_plugins/dns_reverse'),
355
389
  require('./event_plugins/fs'),
356
390
  require('./event_plugins/net'),
391
+ require('./event_plugins/zlib'),
357
392
  ]
358
393
  this.plugins = plugins.map((Plugin) => {
359
394
  return new Plugin(eventHandler, eventFilter)
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const { getValueFromEnvSources } = require('./config/helper')
4
3
  const NoopProxy = require('./noop/proxy')
5
4
  const DatadogTracer = require('./tracer')
6
5
  const getConfig = require('./config')
@@ -213,7 +212,7 @@ class Tracer extends NoopProxy {
213
212
  this._testApiManualPlugin.configure({ ...config, enabled: true }, false)
214
213
  }
215
214
  if (config.ciVisAgentlessLogSubmissionEnabled) {
216
- if (getValueFromEnvSources('DD_API_KEY')) {
215
+ if (config.apiKey) {
217
216
  const LogSubmissionPlugin = require('./ci-visibility/log-submission/log-submission-plugin')
218
217
  const automaticLogPlugin = new LogSubmissionPlugin(this)
219
218
  automaticLogPlugin.configure({ ...config, enabled: true })
@@ -255,10 +254,10 @@ class Tracer extends NoopProxy {
255
254
  // do not stop tracer initialization if the profiler fails to be imported
256
255
  try {
257
256
  return require('./profiler').start(config)
258
- } catch (e) {
257
+ } catch (error) {
259
258
  log.error(
260
259
  'Error starting profiler. For troubleshooting tips, see <https://dtdg.co/nodejs-profiler-troubleshooting>',
261
- e
260
+ error
262
261
  )
263
262
  return false
264
263
  }