dd-trace 5.55.0 → 5.57.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 (150) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/index.d.ts +44 -2
  3. package/init.js +4 -1
  4. package/package.json +24 -23
  5. package/packages/datadog-core/src/utils/src/set.js +8 -10
  6. package/packages/datadog-esbuild/index.js +22 -0
  7. package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
  8. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
  9. package/packages/datadog-instrumentations/src/cucumber.js +4 -6
  10. package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
  11. package/packages/datadog-instrumentations/src/fastify.js +91 -9
  12. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
  13. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
  14. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  15. package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
  16. package/packages/datadog-instrumentations/src/ioredis.js +8 -13
  17. package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
  18. package/packages/datadog-instrumentations/src/jest.js +423 -325
  19. package/packages/datadog-instrumentations/src/memcached.js +17 -24
  20. package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
  21. package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
  22. package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
  23. package/packages/datadog-instrumentations/src/openai.js +30 -2
  24. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  25. package/packages/datadog-instrumentations/src/prisma.js +116 -0
  26. package/packages/datadog-instrumentations/src/redis.js +32 -43
  27. package/packages/datadog-instrumentations/src/router.js +1 -1
  28. package/packages/datadog-instrumentations/src/sharedb.js +10 -16
  29. package/packages/datadog-instrumentations/src/vitest.js +4 -4
  30. package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
  31. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
  32. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
  33. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
  34. package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
  35. package/packages/datadog-plugin-azure-functions/src/index.js +5 -4
  36. package/packages/datadog-plugin-bunyan/src/index.js +2 -2
  37. package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
  38. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
  39. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
  40. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  41. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
  42. package/packages/datadog-plugin-cucumber/src/index.js +4 -2
  43. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
  44. package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
  45. package/packages/datadog-plugin-http/src/client.js +1 -0
  46. package/packages/datadog-plugin-http/src/server.js +2 -1
  47. package/packages/datadog-plugin-http2/src/client.js +1 -0
  48. package/packages/datadog-plugin-http2/src/server.js +1 -0
  49. package/packages/datadog-plugin-jest/src/index.js +4 -3
  50. package/packages/datadog-plugin-memcached/src/index.js +6 -2
  51. package/packages/datadog-plugin-mocha/src/index.js +3 -2
  52. package/packages/datadog-plugin-moleculer/src/client.js +15 -9
  53. package/packages/datadog-plugin-moleculer/src/server.js +9 -5
  54. package/packages/datadog-plugin-next/src/index.js +2 -1
  55. package/packages/datadog-plugin-openai/src/tracing.js +127 -80
  56. package/packages/datadog-plugin-oracledb/src/index.js +2 -1
  57. package/packages/datadog-plugin-pino/src/index.js +2 -2
  58. package/packages/datadog-plugin-prisma/src/client.js +62 -0
  59. package/packages/datadog-plugin-prisma/src/engine.js +81 -0
  60. package/packages/datadog-plugin-prisma/src/index.js +22 -0
  61. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
  62. package/packages/datadog-plugin-redis/src/index.js +9 -3
  63. package/packages/datadog-plugin-router/src/index.js +1 -0
  64. package/packages/datadog-plugin-sharedb/src/index.js +13 -5
  65. package/packages/datadog-plugin-winston/src/index.js +2 -2
  66. package/packages/dd-trace/src/appsec/channels.js +26 -21
  67. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  68. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
  69. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +1 -1
  70. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +44 -1
  71. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -1
  72. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +7 -2
  73. package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
  74. package/packages/dd-trace/src/appsec/index.js +28 -2
  75. package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
  76. package/packages/dd-trace/src/appsec/reporter.js +6 -4
  77. package/packages/dd-trace/src/baggage.js +2 -2
  78. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
  79. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  80. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
  81. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
  82. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  83. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
  84. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
  85. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
  86. package/packages/dd-trace/src/config.js +334 -312
  87. package/packages/dd-trace/src/constants.js +2 -1
  88. package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
  89. package/packages/dd-trace/src/datastreams/context.js +1 -1
  90. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  91. package/packages/dd-trace/src/datastreams/writer.js +3 -3
  92. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
  93. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  94. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
  95. package/packages/dd-trace/src/debugger/devtools_client/send.js +5 -1
  96. package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
  97. package/packages/dd-trace/src/debugger/devtools_client/status.js +5 -1
  98. package/packages/dd-trace/src/dogstatsd.js +3 -3
  99. package/packages/dd-trace/src/exporters/agent/index.js +10 -5
  100. package/packages/dd-trace/src/exporters/agent/writer.js +4 -2
  101. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
  102. package/packages/dd-trace/src/exporters/log/index.js +1 -1
  103. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
  104. package/packages/dd-trace/src/guardrails/index.js +3 -1
  105. package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
  106. package/packages/dd-trace/src/llmobs/index.js +11 -5
  107. package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
  108. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  109. package/packages/dd-trace/src/llmobs/tagger.js +13 -13
  110. package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
  111. package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
  112. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  113. package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -28
  114. package/packages/dd-trace/src/opentracing/span.js +1 -0
  115. package/packages/dd-trace/src/plugin_manager.js +3 -3
  116. package/packages/dd-trace/src/plugins/cache.js +2 -2
  117. package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
  118. package/packages/dd-trace/src/plugins/database.js +3 -1
  119. package/packages/dd-trace/src/plugins/index.js +1 -0
  120. package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
  121. package/packages/dd-trace/src/plugins/outbound.js +8 -6
  122. package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
  123. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  124. package/packages/dd-trace/src/plugins/util/ci.js +83 -30
  125. package/packages/dd-trace/src/plugins/util/git.js +1 -0
  126. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
  127. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
  128. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  129. package/packages/dd-trace/src/plugins/util/test.js +80 -10
  130. package/packages/dd-trace/src/plugins/util/web.js +1 -0
  131. package/packages/dd-trace/src/profiler.js +0 -2
  132. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
  133. package/packages/dd-trace/src/profiling/profilers/events.js +10 -2
  134. package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
  135. package/packages/dd-trace/src/proxy.js +12 -27
  136. package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
  137. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
  138. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
  139. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
  140. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
  141. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  142. package/packages/dd-trace/src/supported-configurations.json +13 -3
  143. package/packages/dd-trace/src/telemetry/telemetry.js +11 -4
  144. package/packages/dd-trace/src/tracer.js +11 -0
  145. package/packages/dd-trace/src/tracer_metadata.js +25 -0
  146. package/packages/dd-trace/src/util.js +11 -4
  147. package/version.js +3 -1
  148. package/packages/datadog-core/src/utils/src/get.js +0 -11
  149. package/packages/datadog-core/src/utils/src/has.js +0 -14
  150. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
@@ -3,6 +3,7 @@ const fs = require('fs')
3
3
  const { URL } = require('url')
4
4
  const log = require('../../log')
5
5
  const { getEnvironmentVariable } = require('../../config-helper')
6
+ const satisfies = require('semifies')
6
7
 
7
8
  const istanbul = require('istanbul-lib-coverage')
8
9
  const ignore = require('ignore')
@@ -127,8 +128,28 @@ const DD_CAPABILITIES_IMPACTED_TESTS = '_dd.library_capabilities.impacted_tests'
127
128
  const DD_CAPABILITIES_TEST_MANAGEMENT_QUARANTINE = '_dd.library_capabilities.test_management.quarantine'
128
129
  const DD_CAPABILITIES_TEST_MANAGEMENT_DISABLE = '_dd.library_capabilities.test_management.disable'
129
130
  const DD_CAPABILITIES_TEST_MANAGEMENT_ATTEMPT_TO_FIX = '_dd.library_capabilities.test_management.attempt_to_fix'
131
+ const DD_CAPABILITIES_FAILED_TEST_REPLAY = '_dd.library_capabilities.failed_test_replay'
130
132
  const UNSUPPORTED_TIA_FRAMEWORKS = new Set(['playwright', 'vitest'])
131
133
  const UNSUPPORTED_TIA_FRAMEWORKS_PARALLEL_MODE = new Set(['cucumber', 'mocha'])
134
+ const MINIMUM_FRAMEWORK_VERSION_FOR_EFD = {
135
+ playwright: '>=1.38.0'
136
+ }
137
+ const MINIMUM_FRAMEWORK_VERSION_FOR_IMPACTED_TESTS = {
138
+ playwright: '>=1.38.0'
139
+ }
140
+ const MINIMUM_FRAMEWORK_VERSION_FOR_QUARANTINE = {
141
+ playwright: '>=1.38.0'
142
+ }
143
+ const MINIMUM_FRAMEWORK_VERSION_FOR_DISABLE = {
144
+ playwright: '>=1.38.0'
145
+ }
146
+ const MINIMUM_FRAMEWORK_VERSION_FOR_ATTEMPT_TO_FIX = {
147
+ playwright: '>=1.38.0'
148
+ }
149
+ const MINIMUM_FRAMEWORK_VERSION_FOR_FAILED_TEST_REPLAY = {
150
+ playwright: '>=1.38.0'
151
+ }
152
+
132
153
  const UNSUPPORTED_ATTEMPT_TO_FIX_FRAMEWORKS_PARALLEL_MODE = new Set(['mocha'])
133
154
  const NOT_SUPPORTED_GRANULARITY_IMPACTED_TESTS_FRAMEWORKS = new Set(['mocha', 'playwright', 'vitest'])
134
155
 
@@ -257,6 +278,7 @@ module.exports = {
257
278
  DD_CAPABILITIES_TEST_MANAGEMENT_QUARANTINE,
258
279
  DD_CAPABILITIES_TEST_MANAGEMENT_DISABLE,
259
280
  DD_CAPABILITIES_TEST_MANAGEMENT_ATTEMPT_TO_FIX,
281
+ DD_CAPABILITIES_FAILED_TEST_REPLAY,
260
282
  TEST_LEVEL_EVENT_TYPES,
261
283
  TEST_RETRY_REASON_TYPES,
262
284
  getNumFromKnownTests,
@@ -409,7 +431,7 @@ function checkShaDiscrepancies (ciMetadata, userProvidedGitMetadata) {
409
431
 
410
432
  incrementCountMetric(
411
433
  TELEMETRY_GIT_SHA_MATCH,
412
- { match: gitCommitShaMatch }
434
+ { matched: gitCommitShaMatch }
413
435
  )
414
436
  }
415
437
 
@@ -895,20 +917,68 @@ function isTiaSupported (testFramework, isParallel) {
895
917
  (isParallel && UNSUPPORTED_TIA_FRAMEWORKS_PARALLEL_MODE.has(testFramework)))
896
918
  }
897
919
 
898
- function isAttemptToFixSupported (testFramework, isParallel) {
920
+ function isEarlyFlakeDetectionSupported (testFramework, frameworkVersion) {
921
+ return testFramework === 'playwright'
922
+ ? satisfies(frameworkVersion, MINIMUM_FRAMEWORK_VERSION_FOR_EFD[testFramework])
923
+ : true
924
+ }
925
+
926
+ function isImpactedTestsSupported (testFramework, frameworkVersion) {
927
+ return testFramework === 'playwright'
928
+ ? satisfies(frameworkVersion, MINIMUM_FRAMEWORK_VERSION_FOR_IMPACTED_TESTS[testFramework])
929
+ : true
930
+ }
931
+
932
+ function isQuarantineSupported (testFramework, frameworkVersion) {
933
+ return testFramework === 'playwright'
934
+ ? satisfies(frameworkVersion, MINIMUM_FRAMEWORK_VERSION_FOR_QUARANTINE[testFramework])
935
+ : true
936
+ }
937
+
938
+ function isDisableSupported (testFramework, frameworkVersion) {
939
+ return testFramework === 'playwright'
940
+ ? satisfies(frameworkVersion, MINIMUM_FRAMEWORK_VERSION_FOR_DISABLE[testFramework])
941
+ : true
942
+ }
943
+
944
+ function isAttemptToFixSupported (testFramework, isParallel, frameworkVersion) {
945
+ if (testFramework === 'playwright') {
946
+ return satisfies(frameworkVersion, MINIMUM_FRAMEWORK_VERSION_FOR_ATTEMPT_TO_FIX[testFramework])
947
+ }
948
+
899
949
  return !(isParallel && UNSUPPORTED_ATTEMPT_TO_FIX_FRAMEWORKS_PARALLEL_MODE.has(testFramework))
900
950
  }
901
951
 
902
- function getLibraryCapabilitiesTags (testFramework, isParallel) {
952
+ function isFailedTestReplaySupported (testFramework, frameworkVersion) {
953
+ return testFramework === 'playwright'
954
+ ? satisfies(frameworkVersion, MINIMUM_FRAMEWORK_VERSION_FOR_FAILED_TEST_REPLAY[testFramework])
955
+ : true
956
+ }
957
+
958
+ function getLibraryCapabilitiesTags (testFramework, isParallel, frameworkVersion) {
903
959
  return {
904
- [DD_CAPABILITIES_TEST_IMPACT_ANALYSIS]: isTiaSupported(testFramework, isParallel) ? '1' : undefined,
905
- [DD_CAPABILITIES_EARLY_FLAKE_DETECTION]: '1',
960
+ [DD_CAPABILITIES_TEST_IMPACT_ANALYSIS]: isTiaSupported(testFramework, isParallel)
961
+ ? '1'
962
+ : undefined,
963
+ [DD_CAPABILITIES_EARLY_FLAKE_DETECTION]: isEarlyFlakeDetectionSupported(testFramework, frameworkVersion)
964
+ ? '1'
965
+ : undefined,
906
966
  [DD_CAPABILITIES_AUTO_TEST_RETRIES]: '1',
907
- [DD_CAPABILITIES_IMPACTED_TESTS]: '1',
908
- [DD_CAPABILITIES_TEST_MANAGEMENT_QUARANTINE]: '1',
909
- [DD_CAPABILITIES_TEST_MANAGEMENT_DISABLE]: '1',
910
- [DD_CAPABILITIES_TEST_MANAGEMENT_ATTEMPT_TO_FIX]: isAttemptToFixSupported(testFramework, isParallel)
911
- ? '4'
967
+ [DD_CAPABILITIES_IMPACTED_TESTS]: isImpactedTestsSupported(testFramework, frameworkVersion)
968
+ ? '1'
969
+ : undefined,
970
+ [DD_CAPABILITIES_TEST_MANAGEMENT_QUARANTINE]: isQuarantineSupported(testFramework, frameworkVersion)
971
+ ? '1'
972
+ : undefined,
973
+ [DD_CAPABILITIES_TEST_MANAGEMENT_DISABLE]: isDisableSupported(testFramework, frameworkVersion)
974
+ ? '1'
975
+ : undefined,
976
+ [DD_CAPABILITIES_TEST_MANAGEMENT_ATTEMPT_TO_FIX]:
977
+ isAttemptToFixSupported(testFramework, isParallel, frameworkVersion)
978
+ ? '4'
979
+ : undefined,
980
+ [DD_CAPABILITIES_FAILED_TEST_REPLAY]: isFailedTestReplaySupported(testFramework, frameworkVersion)
981
+ ? '1'
912
982
  : undefined
913
983
  }
914
984
  }
@@ -70,6 +70,7 @@ const web = {
70
70
 
71
71
  span.context()._name = `${name}.request`
72
72
  span.context()._tags.component = name
73
+ span._integrationName = name
73
74
 
74
75
  web.setConfig(req, config)
75
76
  },
@@ -23,8 +23,6 @@ module.exports = {
23
23
  activation = 'auto'
24
24
  } else if (enabled === 'true') {
25
25
  activation = 'manual'
26
- } else if (injectionEnabled.includes('profiler')) {
27
- activation = 'injection'
28
26
  } // else activation = undefined
29
27
 
30
28
  return profiler.start({
@@ -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,
@@ -291,8 +291,16 @@ class NodeApiEventSource {
291
291
 
292
292
  class DatadogInstrumentationEventSource {
293
293
  constructor (eventHandler, eventFilter) {
294
- this.plugins = ['dns_lookup', 'dns_lookupservice', 'dns_resolve', 'dns_reverse', 'fs', 'net'].map(m => {
295
- const Plugin = require(`./event_plugins/${m}`)
294
+ // List all entries explicitly for bundlers to pick up the require calls correctly.
295
+ const plugins = [
296
+ require('./event_plugins/dns_lookup'),
297
+ require('./event_plugins/dns_lookupservice'),
298
+ require('./event_plugins/dns_resolve'),
299
+ require('./event_plugins/dns_reverse'),
300
+ require('./event_plugins/fs'),
301
+ require('./event_plugins/net')
302
+ ]
303
+ this.plugins = plugins.map((Plugin) => {
296
304
  return new Plugin(eventHandler, eventFilter)
297
305
  })
298
306
 
@@ -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',