dd-trace 5.56.0 → 5.57.1

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 (134) hide show
  1. package/index.d.ts +44 -2
  2. package/init.js +4 -1
  3. package/package.json +20 -20
  4. package/packages/datadog-esbuild/index.js +22 -0
  5. package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
  6. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
  7. package/packages/datadog-instrumentations/src/cucumber.js +4 -6
  8. package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
  9. package/packages/datadog-instrumentations/src/fastify.js +91 -9
  10. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
  11. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  13. package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
  14. package/packages/datadog-instrumentations/src/ioredis.js +8 -13
  15. package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
  16. package/packages/datadog-instrumentations/src/jest.js +28 -6
  17. package/packages/datadog-instrumentations/src/memcached.js +17 -24
  18. package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
  19. package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
  20. package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
  21. package/packages/datadog-instrumentations/src/openai.js +30 -2
  22. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  23. package/packages/datadog-instrumentations/src/prisma.js +116 -0
  24. package/packages/datadog-instrumentations/src/redis.js +32 -43
  25. package/packages/datadog-instrumentations/src/router.js +1 -1
  26. package/packages/datadog-instrumentations/src/sharedb.js +10 -16
  27. package/packages/datadog-instrumentations/src/vitest.js +4 -4
  28. package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
  29. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
  31. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
  32. package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
  33. package/packages/datadog-plugin-bunyan/src/index.js +2 -2
  34. package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
  35. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
  36. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
  37. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  38. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
  39. package/packages/datadog-plugin-cucumber/src/index.js +4 -2
  40. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
  41. package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
  42. package/packages/datadog-plugin-http/src/client.js +1 -0
  43. package/packages/datadog-plugin-http/src/server.js +2 -1
  44. package/packages/datadog-plugin-http2/src/client.js +1 -0
  45. package/packages/datadog-plugin-http2/src/server.js +1 -0
  46. package/packages/datadog-plugin-jest/src/index.js +4 -3
  47. package/packages/datadog-plugin-memcached/src/index.js +6 -2
  48. package/packages/datadog-plugin-mocha/src/index.js +3 -2
  49. package/packages/datadog-plugin-moleculer/src/client.js +15 -9
  50. package/packages/datadog-plugin-moleculer/src/server.js +9 -5
  51. package/packages/datadog-plugin-next/src/index.js +2 -1
  52. package/packages/datadog-plugin-openai/src/tracing.js +127 -80
  53. package/packages/datadog-plugin-pino/src/index.js +2 -2
  54. package/packages/datadog-plugin-prisma/src/client.js +62 -0
  55. package/packages/datadog-plugin-prisma/src/engine.js +81 -0
  56. package/packages/datadog-plugin-prisma/src/index.js +22 -0
  57. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
  58. package/packages/datadog-plugin-redis/src/index.js +9 -3
  59. package/packages/datadog-plugin-router/src/index.js +1 -0
  60. package/packages/datadog-plugin-sharedb/src/index.js +13 -5
  61. package/packages/datadog-plugin-winston/src/index.js +2 -2
  62. package/packages/dd-trace/src/appsec/channels.js +26 -21
  63. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
  64. package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
  65. package/packages/dd-trace/src/appsec/index.js +16 -1
  66. package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
  67. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
  68. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  69. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
  70. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
  71. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  72. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
  73. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
  74. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
  75. package/packages/dd-trace/src/config.js +286 -270
  76. package/packages/dd-trace/src/constants.js +2 -1
  77. package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
  78. package/packages/dd-trace/src/datastreams/context.js +1 -1
  79. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  80. package/packages/dd-trace/src/datastreams/writer.js +3 -3
  81. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
  82. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  83. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
  84. package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
  85. package/packages/dd-trace/src/dogstatsd.js +3 -3
  86. package/packages/dd-trace/src/exporters/agent/index.js +10 -5
  87. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  88. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
  89. package/packages/dd-trace/src/exporters/log/index.js +1 -1
  90. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
  91. package/packages/dd-trace/src/guardrails/index.js +3 -1
  92. package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
  93. package/packages/dd-trace/src/llmobs/index.js +11 -5
  94. package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
  95. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  96. package/packages/dd-trace/src/llmobs/tagger.js +13 -13
  97. package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
  98. package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
  99. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  100. package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
  101. package/packages/dd-trace/src/opentracing/span.js +1 -0
  102. package/packages/dd-trace/src/plugin_manager.js +3 -3
  103. package/packages/dd-trace/src/plugins/cache.js +2 -2
  104. package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
  105. package/packages/dd-trace/src/plugins/database.js +3 -1
  106. package/packages/dd-trace/src/plugins/index.js +1 -0
  107. package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
  108. package/packages/dd-trace/src/plugins/outbound.js +8 -6
  109. package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
  110. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  111. package/packages/dd-trace/src/plugins/util/ci.js +83 -30
  112. package/packages/dd-trace/src/plugins/util/git.js +1 -0
  113. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
  114. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
  115. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  116. package/packages/dd-trace/src/plugins/util/test.js +80 -10
  117. package/packages/dd-trace/src/plugins/util/web.js +1 -0
  118. package/packages/dd-trace/src/profiler.js +0 -2
  119. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
  120. package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
  121. package/packages/dd-trace/src/proxy.js +12 -27
  122. package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
  123. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
  124. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
  125. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
  126. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
  127. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  128. package/packages/dd-trace/src/supported-configurations.json +12 -3
  129. package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
  130. package/packages/dd-trace/src/tracer.js +11 -0
  131. package/packages/dd-trace/src/tracer_metadata.js +25 -0
  132. package/packages/dd-trace/src/util.js +11 -4
  133. package/version.js +3 -1
  134. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
@@ -24,9 +24,7 @@ function exporterFromURL (url) {
24
24
  ? 'manual'
25
25
  : profilingEnabled === 'auto'
26
26
  ? 'auto'
27
- : injectionEnabled.includes('profiling')
28
- ? 'injection'
29
- : 'unknown'
27
+ : 'unknown'
30
28
  return new AgentExporter({
31
29
  url,
32
30
  logger,
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const telemetryMetrics = require('../telemetry/metrics')
4
- const profilersNamespace = telemetryMetrics.manager.namespace('profilers')
5
3
  const dc = require('dc-polyfill')
6
4
  const log = require('../log')
7
5
 
@@ -9,42 +7,17 @@ const log = require('../log')
9
7
  const DEFAULT_LONG_LIVED_THRESHOLD = 30_000
10
8
 
11
9
  /**
12
- * This class embodies the SSI profiler-triggering heuristics and also emits telemetry metrics about
13
- * the profiler behavior under SSI. It emits the following metrics:
14
- * - `number_of_profiles`: The number of profiles that were submitted
15
- * - `number_of_runtime_id`: The number of runtime IDs in the app (always 1 for Node.js, emitted
16
- * once when the tags won't change for the remaineder of of the app's lifetime.)
17
- * It will also add tags describing the state of heuristics triggers, the enablement choice, and
18
- * whether actual profiles were sent (as opposed to mock profiles). There is a mock profiler that is
19
- * activated when the profiler is not enabled, and it will emit mock profile submission events at
20
- * the same cadence the profiler would, providing insight into how many profiles would've been
21
- * emitted if SSI enabled profiling. Note that heuristics (and thus telemetry) is per tracer
22
- * instance, and each worker thread will have its own instance.
10
+ * This class embodies the SSI profiler-triggering heuristics under SSI.
23
11
  */
24
12
  class SSIHeuristics {
25
13
  constructor (config) {
26
- const injectionIncludesProfiler = config.injectionEnabled.includes('profiler')
27
- this._heuristicsActive = injectionIncludesProfiler || config.profiling.enabled === 'auto'
28
- this._emitsTelemetry = config.injectionEnabled.length > 0 && config.profiling.enabled !== 'false'
29
-
30
- if (this._emitsTelemetry) {
31
- if (config.profiling.enabled === 'true') {
32
- this.enablementChoice = 'manually_enabled'
33
- } else if (injectionIncludesProfiler) {
34
- this.enablementChoice = 'ssi_enabled'
35
- } else if (config.profiling.enabled === 'auto') {
36
- this.enablementChoice = 'auto_enabled'
37
- } else {
38
- this.enablementChoice = 'ssi_not_enabled'
39
- }
40
- }
41
-
42
14
  const longLivedThreshold = config.profiling.longLivedThreshold || DEFAULT_LONG_LIVED_THRESHOLD
43
15
  if (typeof longLivedThreshold !== 'number' || longLivedThreshold <= 0) {
44
16
  this.longLivedThreshold = DEFAULT_LONG_LIVED_THRESHOLD
45
17
  log.warn(
46
- `Invalid SSIHeuristics.longLivedThreshold value: ${config.profiling.longLivedThreshold}. ` +
47
- `Using default value: ${DEFAULT_LONG_LIVED_THRESHOLD}`
18
+ 'Invalid SSIHeuristics.longLivedThreshold value: %s. Using default value:',
19
+ config.profiling.longLivedThreshold,
20
+ DEFAULT_LONG_LIVED_THRESHOLD
48
21
  )
49
22
  } else {
50
23
  this.longLivedThreshold = longLivedThreshold
@@ -55,39 +28,21 @@ class SSIHeuristics {
55
28
  this.shortLived = true
56
29
  }
57
30
 
58
- get emitsTelemetry () {
59
- return this._emitsTelemetry
60
- }
61
-
62
- get heuristicsActive () {
63
- return this._heuristicsActive
64
- }
65
-
66
31
  start () {
67
- if (this.heuristicsActive || this.emitsTelemetry) {
68
- // Used to determine short-livedness of the process. We could use the process start time as the
69
- // reference point, but the tracer initialization point is more relevant, as we couldn't be
70
- // collecting profiles earlier anyway. The difference is not particularly significant if the
71
- // tracer is initialized early in the process lifetime.
72
- setTimeout(() => {
73
- this.shortLived = false
74
- this._maybeTriggered()
75
- }, this.longLivedThreshold).unref()
76
-
77
- this._onSpanCreated = this._onSpanCreated.bind(this)
78
- dc.subscribe('dd-trace:span:start', this._onSpanCreated)
79
-
80
- if (this.emitsTelemetry) {
81
- this._onProfileSubmitted = this._onProfileSubmitted.bind(this)
82
- this._onMockProfileSubmitted = this._onMockProfileSubmitted.bind(this)
83
-
84
- dc.subscribe('datadog:profiling:profile-submitted', this._onProfileSubmitted)
85
- dc.subscribe('datadog:profiling:mock-profile-submitted', this._onMockProfileSubmitted)
86
- }
87
-
88
- this._onAppClosing = this._onAppClosing.bind(this)
89
- dc.subscribe('datadog:telemetry:app-closing', this._onAppClosing)
90
- }
32
+ // Used to determine short-livedness of the process. We could use the process start time as the
33
+ // reference point, but the tracer initialization point is more relevant, as we couldn't be
34
+ // collecting profiles earlier anyway. The difference is not particularly significant if the
35
+ // tracer is initialized early in the process lifetime.
36
+ setTimeout(() => {
37
+ this.shortLived = false
38
+ this._maybeTriggered()
39
+ }, this.longLivedThreshold).unref()
40
+
41
+ this._onSpanCreated = this._onSpanCreated.bind(this)
42
+ dc.subscribe('dd-trace:span:start', this._onSpanCreated)
43
+
44
+ this._onAppClosing = this._onAppClosing.bind(this)
45
+ dc.subscribe('datadog:telemetry:app-closing', this._onAppClosing)
91
46
  }
92
47
 
93
48
  onTriggered (callback) {
@@ -118,70 +73,7 @@ class SSIHeuristics {
118
73
  dc.unsubscribe('dd-trace:span:start', this._onSpanCreated)
119
74
  }
120
75
 
121
- _onProfileSubmitted () {
122
- this.hasSentProfiles = true
123
- this._incProfileCount()
124
- }
125
-
126
- _onMockProfileSubmitted () {
127
- this._incProfileCount()
128
- }
129
-
130
- _incProfileCount () {
131
- this._ensureProfileMetrics()
132
- this._profileCount.inc()
133
- }
134
-
135
- _ensureProfileMetrics () {
136
- const decision = []
137
- if (this.noSpan) {
138
- decision.push('no_span')
139
- }
140
- if (this.shortLived) {
141
- decision.push('short_lived')
142
- }
143
- if (decision.length === 0) {
144
- decision.push('triggered')
145
- }
146
-
147
- const tags = [
148
- 'installation:ssi',
149
- `enablement_choice:${this.enablementChoice}`,
150
- `has_sent_profiles:${this.hasSentProfiles}`,
151
- `heuristic_hypothetical_decision:${decision.join('_')}`
152
- ]
153
-
154
- this._profileCount = profilersNamespace.count('ssi_heuristic.number_of_profiles', tags)
155
- this._runtimeIdCount = profilersNamespace.count('ssi_heuristic.number_of_runtime_id', tags)
156
-
157
- if (
158
- !this._emittedRuntimeId &&
159
- decision[0] === 'triggered' &&
160
- // When heuristics are active, hasSentProfiles can transition from false to true when the
161
- // profiler gets started and the first profile is submitted, so we have to wait for it.
162
- (!this.heuristicsActive || this.hasSentProfiles)
163
- ) {
164
- // Tags won't change anymore, so we can emit the runtime ID metric now.
165
- this._emittedRuntimeId = true
166
- this._runtimeIdCount.inc()
167
- }
168
- }
169
-
170
76
  _onAppClosing () {
171
- if (this.emitsTelemetry) {
172
- this._ensureProfileMetrics()
173
- // Last ditch effort to emit a runtime ID count metric
174
- if (!this._emittedRuntimeId) {
175
- this._emittedRuntimeId = true
176
- this._runtimeIdCount.inc()
177
- }
178
- // So we have the metrics in the final state
179
- this._profileCount.inc(0)
180
-
181
- dc.unsubscribe('datadog:profiling:profile-submitted', this._onProfileSubmitted)
182
- dc.unsubscribe('datadog:profiling:mock-profile-submitted', this._onMockProfileSubmitted)
183
- }
184
-
185
77
  dc.unsubscribe('datadog:telemetry:app-closing', this._onAppClosing)
186
78
  if (this.noSpan) {
187
79
  dc.unsubscribe('dd-trace:span:start', this._onSpanCreated)
@@ -153,36 +153,22 @@ class Tracer extends NoopProxy {
153
153
  }
154
154
  }
155
155
 
156
- if (config.profiling.enabled !== 'false') {
157
- const { SSIHeuristics } = require('./profiling/ssi-heuristics')
158
- const ssiHeuristics = new SSIHeuristics(config)
159
- ssiHeuristics.start()
160
- let mockProfiler = null
161
- if (config.profiling.enabled === 'true') {
162
- this._profilerStarted = this._startProfiler(config)
163
- } else if (ssiHeuristics.emitsTelemetry) {
164
- // Start a mock profiler that emits mock profile-submitted events for the telemetry.
165
- // It will be stopped if the real profiler is started by the heuristics.
166
- mockProfiler = require('./profiling/ssi-telemetry-mock-profiler')
167
- mockProfiler.start(config)
168
- }
169
-
170
- if (ssiHeuristics.heuristicsActive) {
156
+ if (config.profiling.enabled === 'true') {
157
+ this._profilerStarted = this._startProfiler(config)
158
+ } else {
159
+ this._profilerStarted = Promise.resolve(false)
160
+ if (config.profiling.enabled === 'auto') {
161
+ const { SSIHeuristics } = require('./profiling/ssi-heuristics')
162
+ const ssiHeuristics = new SSIHeuristics(config)
163
+ ssiHeuristics.start()
171
164
  ssiHeuristics.onTriggered(() => {
172
- if (mockProfiler) {
173
- mockProfiler.stop()
174
- }
175
165
  this._startProfiler(config)
176
166
  ssiHeuristics.onTriggered() // deregister this callback
177
167
  })
178
168
  }
179
-
180
- if (!this._profilerStarted) {
181
- this._profilerStarted = Promise.resolve(false)
182
- }
183
169
  }
184
170
 
185
- if (config.runtimeMetrics) {
171
+ if (config.runtimeMetrics.enabled) {
186
172
  runtimeMetrics.start(config)
187
173
  }
188
174
 
@@ -205,8 +191,8 @@ class Tracer extends NoopProxy {
205
191
  automaticLogPlugin.configure({ ...config, enabled: true })
206
192
  } else {
207
193
  log.warn(
208
- 'DD_AGENTLESS_LOG_SUBMISSION_ENABLED is set, ' +
209
- 'but DD_API_KEY is undefined, so no automatic log submission will be performed.'
194
+ // eslint-disable-next-line @stylistic/max-len
195
+ 'DD_AGENTLESS_LOG_SUBMISSION_ENABLED is set, but DD_API_KEY is undefined, so no automatic log submission will be performed.'
210
196
  )
211
197
  }
212
198
  }
@@ -229,8 +215,7 @@ class Tracer extends NoopProxy {
229
215
  return require('./profiler').start(config)
230
216
  } catch (e) {
231
217
  log.error(
232
- 'Error starting profiler. For troubleshooting tips, see ' +
233
- '<https://dtdg.co/nodejs-profiler-troubleshooting>',
218
+ 'Error starting profiler. For troubleshooting tips, see <https://dtdg.co/nodejs-profiler-troubleshooting>',
234
219
  e
235
220
  )
236
221
  }
@@ -15,7 +15,7 @@ const noop = runtimeMetrics = {
15
15
 
16
16
  module.exports = {
17
17
  start (config) {
18
- if (!config?.runtimeMetrics) return
18
+ if (!config?.runtimeMetrics.enabled) return
19
19
 
20
20
  runtimeMetrics = require('./runtime_metrics')
21
21
 
@@ -6,7 +6,6 @@ const v8 = require('v8')
6
6
  const os = require('os')
7
7
  const { DogStatsDClient, MetricsAggregationClient } = require('../dogstatsd')
8
8
  const log = require('../log')
9
- const Histogram = require('../histogram')
10
9
  const { performance, PerformanceObserver } = require('perf_hooks')
11
10
  const { getEnvironmentVariable } = require('../config-helper')
12
11
 
@@ -17,11 +16,9 @@ const INTERVAL = Number.parseInt(DD_RUNTIME_METRICS_FLUSH_INTERVAL, 10)
17
16
  // Node >=16 has PerformanceObserver with `gc` type, but <16.7 had a critical bug.
18
17
  // See: https://github.com/nodejs/node/issues/39548
19
18
  const hasGCObserver = NODE_MAJOR >= 18 || (NODE_MAJOR === 16 && NODE_MINOR >= 7)
20
- const hasGCProfiler = NODE_MAJOR >= 20 || (NODE_MAJOR === 18 && NODE_MINOR >= 15)
21
19
 
22
20
  let nativeMetrics = null
23
21
  let gcObserver = null
24
- let gcProfiler = null
25
22
 
26
23
  let interval
27
24
  let client
@@ -34,15 +31,23 @@ reset()
34
31
  const runtimeMetrics = module.exports = {
35
32
  start (config) {
36
33
  const clientConfig = DogStatsDClient.generateClientConfig(config)
34
+ const watchers = []
37
35
 
38
- try {
39
- nativeMetrics = require('@datadog/native-metrics')
40
-
36
+ if (config.runtimeMetrics.gc !== false) {
41
37
  if (hasGCObserver) {
42
- nativeMetrics.start('loop') // Only add event loop watcher and not GC.
38
+ startGCObserver()
43
39
  } else {
44
- nativeMetrics.start()
40
+ watchers.push('gc')
45
41
  }
42
+ }
43
+
44
+ if (config.runtimeMetrics.eventLoop !== false) {
45
+ watchers.push('loop')
46
+ }
47
+
48
+ try {
49
+ nativeMetrics = require('@datadog/native-metrics')
50
+ nativeMetrics.start(...watchers)
46
51
  } catch (e) {
47
52
  log.error('Error starting native metrics', e)
48
53
  nativeMetrics = null
@@ -52,9 +57,6 @@ const runtimeMetrics = module.exports = {
52
57
 
53
58
  time = process.hrtime()
54
59
 
55
- startGCObserver()
56
- startGCProfiler()
57
-
58
60
  if (nativeMetrics) {
59
61
  interval = setInterval(() => {
60
62
  captureCommonMetrics()
@@ -129,8 +131,6 @@ function reset () {
129
131
  nativeMetrics = null
130
132
  gcObserver && gcObserver.disconnect()
131
133
  gcObserver = null
132
- gcProfiler && gcProfiler.stop()
133
- gcProfiler = null
134
134
  }
135
135
 
136
136
  function captureCpuUsage () {
@@ -195,29 +195,6 @@ function captureHeapSpace () {
195
195
  client.gauge('runtime.node.heap.physical_size.by.space', stats[i].physical_space_size, tags)
196
196
  }
197
197
  }
198
- function captureGCMetrics () {
199
- if (!gcProfiler) return
200
-
201
- const profile = gcProfiler.stop()
202
- const pauseAll = new Histogram()
203
- const pause = {}
204
-
205
- for (const stat of profile.statistics) {
206
- const type = stat.gcType.replaceAll(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
207
-
208
- pause[type] = pause[type] || new Histogram()
209
- pause[type].record(stat.cost)
210
- pauseAll.record(stat.cost)
211
- }
212
-
213
- histogram('runtime.node.gc.pause', pauseAll)
214
-
215
- for (const type in pause) {
216
- histogram('runtime.node.gc.pause.by.type', pause[type], `gc_type:${type}`)
217
- }
218
-
219
- gcProfiler.start()
220
- }
221
198
 
222
199
  /**
223
200
  * Gathers and reports Event Loop Utilization (ELU) since last run
@@ -242,7 +219,6 @@ function captureCommonMetrics () {
242
219
  captureProcess()
243
220
  captureHeapStats()
244
221
  captureELU()
245
- captureGCMetrics()
246
222
  }
247
223
 
248
224
  function captureNativeMetrics () {
@@ -293,7 +269,7 @@ function histogram (name, stats, tag) {
293
269
  }
294
270
 
295
271
  function startGCObserver () {
296
- if (gcObserver || hasGCProfiler || !hasGCObserver) return
272
+ if (gcObserver) return
297
273
 
298
274
  gcObserver = new PerformanceObserver(list => {
299
275
  for (const entry of list.getEntries()) {
@@ -307,13 +283,6 @@ function startGCObserver () {
307
283
  gcObserver.observe({ type: 'gc' })
308
284
  }
309
285
 
310
- function startGCProfiler () {
311
- if (gcProfiler || !hasGCProfiler) return
312
-
313
- gcProfiler = new v8.GCProfiler()
314
- gcProfiler.start()
315
- }
316
-
317
286
  function gcType (kind) {
318
287
  if (NODE_MAJOR >= 22) {
319
288
  switch (kind) {
@@ -22,7 +22,7 @@ const messaging = {
22
22
  opName: () => 'kafka.produce',
23
23
  serviceName: ({ tracerService }) => `${tracerService}-kafka`
24
24
  },
25
- '@confluentinc/kafka-javascript': {
25
+ 'confluentinc-kafka-javascript': {
26
26
  opName: () => 'kafka.produce',
27
27
  serviceName: ({ tracerService }) => `${tracerService}-kafka`
28
28
  },
@@ -56,7 +56,7 @@ const messaging = {
56
56
  opName: () => 'kafka.consume',
57
57
  serviceName: ({ tracerService }) => `${tracerService}-kafka`
58
58
  },
59
- '@confluentinc/kafka-javascript': {
59
+ 'confluentinc-kafka-javascript': {
60
60
  opName: () => 'kafka.consume',
61
61
  serviceName: ({ tracerService }) => `${tracerService}-kafka`
62
62
  },
@@ -100,6 +100,10 @@ const storage = {
100
100
  opName: () => 'pg.query',
101
101
  serviceName: withSuffixFunction('postgres')
102
102
  },
103
+ prisma: {
104
+ opName: ({ operation }) => `prisma.${operation}`,
105
+ serviceName: withSuffixFunction('prisma')
106
+ },
103
107
  redis: redisConfig,
104
108
  tedious: {
105
109
  opName: () => 'tedious.request',
@@ -22,7 +22,7 @@ const messaging = {
22
22
  opName: () => 'kafka.send',
23
23
  serviceName: identityService
24
24
  },
25
- '@confluentinc/kafka-javascript': {
25
+ 'confluentinc-kafka-javascript': {
26
26
  opName: () => 'kafka.send',
27
27
  serviceName: identityService
28
28
  },
@@ -47,7 +47,7 @@ const messaging = {
47
47
  opName: () => 'kafka.process',
48
48
  serviceName: identityService
49
49
  },
50
- '@confluentinc/kafka-javascript': {
50
+ 'confluentinc-kafka-javascript': {
51
51
  opName: () => 'kafka.process',
52
52
  serviceName: identityService
53
53
  },
@@ -68,6 +68,10 @@ const storage = {
68
68
  opName: () => 'postgresql.query',
69
69
  serviceName: withFunction
70
70
  },
71
+ prisma: {
72
+ opName: ({ operation }) => `prisma.${operation}`,
73
+ serviceName: configWithFallback
74
+ },
71
75
  redis: redisNaming,
72
76
  tedious: {
73
77
  opName: () => 'mssql.query',
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "supportedConfigurations": {
3
3
  "DD_AAS_DOTNET_EXTENSION_VERSION": ["A"],
4
+ "DD_ACTION_EXECUTION_ID": ["A"],
4
5
  "DD_AGENT_HOST": ["A"],
5
6
  "DD_AGENTLESS_LOG_SUBMISSION_ENABLED": ["A"],
6
7
  "DD_AGENTLESS_LOG_SUBMISSION_URL": ["A"],
@@ -49,6 +50,7 @@
49
50
  "DD_CODE_ORIGIN_FOR_SPANS_ENABLED": ["A"],
50
51
  "DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED": ["A"],
51
52
  "DD_CRASHTRACKING_ENABLED": ["A"],
53
+ "DD_CUSTOM_TRACE_ID": ["A"],
52
54
  "DD_DATA_STREAMS_ENABLED": ["A"],
53
55
  "DD_DBM_PROPAGATION_MODE": ["A"],
54
56
  "DD_DOGSTATSD_HOST": ["A"],
@@ -72,6 +74,8 @@
72
74
  "DD_GIT_PROPERTIES_FILE": ["A"],
73
75
  "DD_GIT_REPOSITORY_URL": ["A"],
74
76
  "DD_GIT_TAG": ["A"],
77
+ "DD_GIT_PULL_REQUEST_BASE_BRANCH": ["A"],
78
+ "DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA": ["A"],
75
79
  "DD_GRPC_CLIENT_ERROR_STATUSES": ["A"],
76
80
  "DD_GRPC_SERVER_ERROR_STATUSES": ["A"],
77
81
  "DD_IAST_DB_ROWS_TO_TAINT": ["A"],
@@ -106,6 +110,7 @@
106
110
  "DD_MINI_AGENT_PATH": ["A"],
107
111
  "DD_OPENAI_LOGS_ENABLED": ["A"],
108
112
  "DD_OPENAI_SPAN_CHAR_LIMIT": ["A"],
113
+ "DD_PIPELINE_EXECUTION_ID": ["A"],
109
114
  "DD_PLAYWRIGHT_WORKER": ["A"],
110
115
  "DD_PROFILING_CODEHOTSPOTS_ENABLED": ["A"],
111
116
  "DD_PROFILING_CPU_ENABLED": ["A"],
@@ -126,7 +131,10 @@
126
131
  "DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": ["A"],
127
132
  "DD_REMOTE_CONFIGURATION_ENABLED": ["A"],
128
133
  "DD_RUNTIME_METRICS_ENABLED": ["A"],
134
+ "DD_RUNTIME_METRICS_EVENT_LOOP_ENABLED": ["A"],
135
+ "DD_RUNTIME_METRICS_GC_ENABLED": ["A"],
129
136
  "DD_RUNTIME_METRICS_FLUSH_INTERVAL": ["A"],
137
+ "DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["A"],
130
138
  "DD_SERVICE_MAPPING": ["A"],
131
139
  "DD_SERVICE": ["A"],
132
140
  "DD_SITE": ["A"],
@@ -145,7 +153,6 @@
145
153
  "DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES": ["A"],
146
154
  "DD_TEST_MANAGEMENT_ENABLED": ["A"],
147
155
  "DD_TEST_SESSION_NAME": ["A"],
148
- "DD_TRACE__CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED": ["A"],
149
156
  "DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
150
157
  "DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
151
158
  "DD_TRACE_AEROSPIKE_ENABLED": ["A"],
@@ -238,7 +245,6 @@
238
245
  "DD_TRACE_EXPERIMENTAL_B3_ENABLED": ["A"],
239
246
  "DD_TRACE_EXPERIMENTAL_EXPORTER": ["A"],
240
247
  "DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED": ["A"],
241
- "DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED": ["A"],
242
248
  "DD_TRACE_EXPERIMENTAL_SPAN_COUNTS": ["A"],
243
249
  "DD_TRACE_EXPERIMENTAL_STATE_TRACKING": ["A"],
244
250
  "DD_TRACE_EXPRESS_ENABLED": ["A"],
@@ -351,6 +357,7 @@
351
357
  "DD_TRACE_PLAYWRIGHT_CORE_ENABLED": ["A"],
352
358
  "DD_TRACE_PLAYWRIGHT_ENABLED": ["A"],
353
359
  "DD_TRACE_PLAYWRIGHT_TEST_ENABLED": ["A"],
360
+ "DD_TRACE_PRISMA_ENABLED": ["A"],
354
361
  "DD_TRACE_PROCESS_ENABLED": ["A"],
355
362
  "DD_TRACE_PROMISE_ENABLED": ["A"],
356
363
  "DD_TRACE_PROMISE_JS_ENABLED": ["A"],
@@ -427,6 +434,7 @@
427
434
  "DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED"],
428
435
  "DD_PROFILING_TIMELINE_ENABLED": ["DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED"],
429
436
  "DD_REMOTE_CONFIGURATION_ENABLED": ["DD_REMOTE_CONFIG_ENABLED" ],
437
+ "DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED"],
430
438
  "DD_SERVICE": ["DD_SERVICE_NAME"],
431
439
  "DD_TRACE_AGENT_URL": ["DD_TRACE_URL"]
432
440
  },
@@ -435,6 +443,7 @@
435
443
  "DD_PROFILING_EXPERIMENTAL_CPU_ENABLED": "DD_PROFILING_CPU_ENABLED",
436
444
  "DD_EXPERIMENTAL_PROFILING_ENABLED": "DD_PROFILING_ENABLED",
437
445
  "DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED": "DD_PROFILING_CODEHOTSPOTS_ENABLED",
438
- "DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED": "DD_PROFILING_TIMELINE_ENABLED"
446
+ "DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED": "DD_PROFILING_TIMELINE_ENABLED",
447
+ "DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED": "DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED"
439
448
  }
440
449
  }
@@ -321,7 +321,11 @@ const nameMapping = {
321
321
  clientIpHeader: 'DD_TRACE_CLIENT_IP_HEADER',
322
322
  'grpc.client.error.statuses': 'DD_GRPC_CLIENT_ERROR_STATUSES',
323
323
  'grpc.server.error.statuses': 'DD_GRPC_SERVER_ERROR_STATUSES',
324
- traceId128BitLoggingEnabled: 'DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED'
324
+ traceId128BitLoggingEnabled: 'DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED',
325
+ instrumentationSource: 'instrumentation_source',
326
+ injectionEnabled: 'ssi_injection_enabled',
327
+ injectForce: 'ssi_forced_injection_enabled',
328
+ 'runtimeMetrics.enabled': 'runtimeMetrics'
325
329
  }
326
330
 
327
331
  const namesNeedFormatting = new Set(['DD_TAGS', 'peerServiceMapping', 'serviceMapping'])
@@ -24,6 +24,17 @@ class DatadogTracer extends Tracer {
24
24
  this._scope = new Scope()
25
25
  setStartupLogConfig(config)
26
26
  flushStartupLogs(log)
27
+
28
+ if (!config._isInServerlessEnvironment()) {
29
+ const storeConfig = require('./tracer_metadata')
30
+ // Keep a reference to the handle, to keep the memfd alive in memory.
31
+ // It is read by the service discovery feature.
32
+ const metadata = storeConfig(config)
33
+ if (metadata === undefined) {
34
+ log.warn('Could not store tracer configuration for service discovery')
35
+ }
36
+ this._inmem_cfg = metadata
37
+ }
27
38
  }
28
39
 
29
40
  configure (config) {
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ // Load binding first to not import other modules if it throws
4
+ const libdatadog = require('@datadog/libdatadog')
5
+ const tracerVersion = require('../../../version').VERSION
6
+
7
+ function storeConfig (config) {
8
+ const processDiscovery = libdatadog.maybeLoad('process-discovery')
9
+ if (processDiscovery === undefined) {
10
+ return
11
+ }
12
+
13
+ const metadata = new processDiscovery.TracerMetadata(
14
+ config.tags['runtime-id'],
15
+ tracerVersion,
16
+ config.hostname,
17
+ config.server || null,
18
+ config.env || null,
19
+ config.version || null
20
+ )
21
+
22
+ return processDiscovery.storeMetadata(metadata)
23
+ }
24
+
25
+ module.exports = storeConfig
@@ -61,12 +61,10 @@ function globMatch (pattern, subject) {
61
61
  return true
62
62
  }
63
63
 
64
- // TODO: this adds stack traces relative to packages/
65
- // shouldn't paths be relative to the root of dd-trace?
66
64
  function calculateDDBasePath (dirname) {
67
65
  const dirSteps = dirname.split(path.sep)
68
66
  const packagesIndex = dirSteps.lastIndexOf('packages')
69
- return dirSteps.slice(0, packagesIndex + 1).join(path.sep) + path.sep
67
+ return dirSteps.slice(0, packagesIndex).join(path.sep) + path.sep
70
68
  }
71
69
 
72
70
  function normalizeProfilingEnabledValue (configValue) {
@@ -77,11 +75,20 @@ function normalizeProfilingEnabledValue (configValue) {
77
75
  : configValue === 'auto' ? 'auto' : undefined
78
76
  }
79
77
 
78
+ function normalizePluginEnvName (envPluginName, makeLowercase = false) {
79
+ if (envPluginName.startsWith('@')) {
80
+ envPluginName = envPluginName.slice(1)
81
+ }
82
+ envPluginName = envPluginName.replaceAll(/[^a-z0-9_]/ig, '_')
83
+ return makeLowercase ? envPluginName.toLowerCase() : envPluginName
84
+ }
85
+
80
86
  module.exports = {
81
87
  isTrue,
82
88
  isFalse,
83
89
  isError,
84
90
  globMatch,
85
91
  ddBasePath: calculateDDBasePath(__dirname),
86
- normalizeProfilingEnabledValue
92
+ normalizeProfilingEnabledValue,
93
+ normalizePluginEnvName
87
94
  }
package/version.js CHANGED
@@ -3,10 +3,12 @@
3
3
  /* eslint-disable no-var */
4
4
  /* eslint-disable unicorn/prefer-number-properties */
5
5
 
6
- var ddMatches = require('./package.json').version.match(/^(\d+)\.(\d+)\.(\d+)/)
6
+ var version = require('./package.json').version
7
+ var ddMatches = version.match(/^(\d+)\.(\d+)\.(\d+)/)
7
8
  var nodeMatches = process.versions.node.match(/^(\d+)\.(\d+)\.(\d+)/)
8
9
 
9
10
  module.exports = {
11
+ VERSION: version,
10
12
  DD_MAJOR: parseInt(ddMatches[1]),
11
13
  DD_MINOR: parseInt(ddMatches[2]),
12
14
  DD_PATCH: parseInt(ddMatches[3]),