datadog 2.34.0 → 2.36.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 (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -6
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +68 -31
  4. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  5. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_stack.c +37 -18
  7. data/ext/datadog_profiling_native_extension/collectors_stack.h +8 -2
  8. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +435 -314
  9. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +9 -7
  10. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +7 -8
  11. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -12
  12. data/ext/datadog_profiling_native_extension/extconf.rb +2 -2
  13. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
  14. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
  15. data/ext/datadog_profiling_native_extension/heap_recorder.c +44 -26
  16. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +14 -35
  17. data/ext/datadog_profiling_native_extension/profiling.c +41 -4
  18. data/ext/datadog_profiling_native_extension/ruby_helpers.c +33 -34
  19. data/ext/datadog_profiling_native_extension/stack_recorder.c +30 -14
  20. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
  21. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +4 -2
  22. data/ext/libdatadog_api/datadog_ruby_common.c +7 -8
  23. data/ext/libdatadog_api/datadog_ruby_common.h +0 -12
  24. data/ext/libdatadog_extconf_helpers.rb +1 -1
  25. data/lib/datadog/ai_guard/configuration.rb +1 -0
  26. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +53 -39
  27. data/lib/datadog/ai_guard/evaluation.rb +6 -1
  28. data/lib/datadog/ai_guard/ext.rb +12 -1
  29. data/lib/datadog/appsec/api_security/route_extractor.rb +9 -0
  30. data/lib/datadog/appsec/component.rb +1 -1
  31. data/lib/datadog/appsec/configuration.rb +7 -0
  32. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +37 -4
  33. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +64 -19
  34. data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -0
  35. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  36. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +41 -3
  37. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +20 -7
  38. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +92 -0
  39. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +9 -40
  40. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +33 -0
  41. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +17 -1
  42. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +20 -3
  43. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  44. data/lib/datadog/core/configuration/components.rb +1 -0
  45. data/lib/datadog/core/configuration/settings.rb +11 -8
  46. data/lib/datadog/core/configuration/supported_configurations.rb +2 -0
  47. data/lib/datadog/core/environment/process.rb +4 -2
  48. data/lib/datadog/core/remote/component.rb +1 -1
  49. data/lib/datadog/core/telemetry/event/app_started.rb +0 -21
  50. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +1 -1
  51. data/lib/datadog/core/utils/{array.rb → enumerable_compat.rb} +2 -2
  52. data/lib/datadog/core/utils/forking.rb +3 -1
  53. data/lib/datadog/core/utils/spawn_monkey_patch.rb +3 -1
  54. data/lib/datadog/core.rb +3 -0
  55. data/lib/datadog/di/base.rb +4 -1
  56. data/lib/datadog/di/component.rb +1 -1
  57. data/lib/datadog/error_tracking/collector.rb +2 -1
  58. data/lib/datadog/error_tracking/component.rb +2 -2
  59. data/lib/datadog/kit/tracing/method_tracer.rb +4 -1
  60. data/lib/datadog/opentelemetry/sdk/propagator.rb +9 -3
  61. data/lib/datadog/opentelemetry/sdk/span_processor.rb +4 -1
  62. data/lib/datadog/profiling/collectors/thread_context.rb +1 -4
  63. data/lib/datadog/profiling/component.rb +15 -25
  64. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +6 -5
  65. data/lib/datadog/profiling/stack_recorder.rb +0 -4
  66. data/lib/datadog/ruby_version.rb +25 -0
  67. data/lib/datadog/symbol_database/component.rb +306 -98
  68. data/lib/datadog/symbol_database/extractor.rb +226 -87
  69. data/lib/datadog/tracing/configuration/ext.rb +13 -0
  70. data/lib/datadog/tracing/configuration/settings.rb +17 -0
  71. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  72. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  73. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  74. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  75. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  76. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +1 -0
  77. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  78. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +4 -1
  79. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +4 -1
  80. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +4 -1
  81. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +4 -1
  82. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +4 -1
  83. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +4 -1
  84. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +4 -1
  85. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -0
  86. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -0
  87. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -0
  88. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -0
  89. data/lib/datadog/tracing/contrib/configuration/resolver.rb +7 -0
  90. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -0
  91. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  92. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  93. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -0
  94. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +2 -2
  95. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +1 -0
  96. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -0
  97. data/lib/datadog/tracing/contrib/excon/middleware.rb +1 -0
  98. data/lib/datadog/tracing/contrib/ext.rb +3 -0
  99. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -0
  100. data/lib/datadog/tracing/contrib/grape/endpoint.rb +3 -0
  101. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +1 -0
  102. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +1 -0
  103. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -0
  104. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
  105. data/lib/datadog/tracing/contrib/grpc.rb +1 -0
  106. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  107. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -0
  108. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -0
  109. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
  110. data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -0
  111. data/lib/datadog/tracing/contrib/http.rb +1 -0
  112. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -0
  113. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -0
  114. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -0
  115. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  116. data/lib/datadog/tracing/contrib/karafka.rb +1 -0
  117. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +5 -5
  118. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  119. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +1 -0
  120. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -0
  121. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +2 -2
  122. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +1 -0
  123. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -0
  124. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +3 -0
  125. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +2 -2
  126. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  127. data/lib/datadog/tracing/contrib/racecar/event.rb +1 -0
  128. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +23 -0
  129. data/lib/datadog/tracing/contrib/rack/middlewares.rb +4 -1
  130. data/lib/datadog/tracing/contrib/rack/route_inference.rb +3 -1
  131. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +2 -0
  132. data/lib/datadog/tracing/contrib/rails/runner.rb +2 -0
  133. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +4 -2
  134. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +2 -0
  135. data/lib/datadog/tracing/contrib/resque/resque_job.rb +1 -0
  136. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +1 -0
  137. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  138. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +4 -1
  139. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -0
  140. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -0
  141. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  142. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  143. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
  144. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  145. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  146. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  147. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  148. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  149. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +3 -2
  150. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
  151. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  152. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -0
  153. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  154. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  155. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +1 -0
  156. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +1 -1
  157. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +2 -0
  158. data/lib/datadog/tracing/contrib/waterdrop.rb +1 -0
  159. data/lib/datadog/tracing/distributed/propagation.rb +33 -1
  160. data/lib/datadog/tracing/distributed/trace_context.rb +11 -2
  161. data/lib/datadog/tracing/metadata/ext.rb +7 -0
  162. data/lib/datadog/tracing/trace_digest.rb +7 -0
  163. data/lib/datadog/tracing/trace_operation.rb +4 -1
  164. data/lib/datadog/tracing/tracer.rb +4 -0
  165. data/lib/datadog/tracing/transport/traces.rb +2 -2
  166. data/lib/datadog/version.rb +1 -1
  167. data/lib/datadog.rb +4 -1
  168. metadata +13 -11
@@ -107,6 +107,7 @@ module Datadog
107
107
  option :api_key do |o|
108
108
  o.type :string, nilable: true
109
109
  o.env Core::Environment::Ext::ENV_API_KEY
110
+ o.skip_telemetry true
110
111
  end
111
112
 
112
113
  # Datadog diagnostic settings.
@@ -394,16 +395,19 @@ module Datadog
394
395
  o.default false
395
396
  end
396
397
 
397
- # Controls data collection for the timeline feature.
398
- #
399
- # If you needed to disable this, please tell us why on <https://github.com/DataDog/dd-trace-rb/issues/new>,
400
- # so we can fix it!
401
- #
402
- # @default `DD_PROFILING_TIMELINE_ENABLED` environment variable as a boolean, otherwise `true`
398
+ # DEV-3.0: Remove `timeline_enabled` option
403
399
  option :timeline_enabled do |o|
404
400
  o.type :bool
405
401
  o.env 'DD_PROFILING_TIMELINE_ENABLED'
406
402
  o.default true
403
+ o.after_set do |_, _, precedence|
404
+ unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
405
+ Core.log_deprecation(key: :timeline_enabled) do
406
+ 'The profiling.advanced.timeline_enabled setting has been deprecated for removal and no longer does anything. ' \
407
+ 'Please remove it from your Datadog.configure block and do not set DD_PROFILING_TIMELINE_ENABLED.'
408
+ end
409
+ end
410
+ end
407
411
  end
408
412
 
409
413
  # The profiler gathers data by sending `SIGPROF` unix signals to Ruby application threads.
@@ -614,8 +618,7 @@ module Datadog
614
618
  o.type :bool
615
619
  o.env 'DD_PROFILING_SIGHANDLER_SAMPLING_ENABLED'
616
620
  o.default do
617
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.5') &&
618
- !(RUBY_VERSION.start_with?('3.3.') && Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.3.4'))
621
+ RubyVersion.is?('>= 3.2.5') && !RubyVersion.is?('>= 3.3', '< 3.3.4')
619
622
  end
620
623
  end
621
624
 
@@ -25,6 +25,7 @@ module Datadog
25
25
  "DD_APM_TRACING_ENABLED",
26
26
  "DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING",
27
27
  "DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE",
28
+ "DD_APPSEC_BODY_PARSING_SIZE_LIMIT",
28
29
  "DD_APPSEC_ENABLED",
29
30
  "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML",
30
31
  "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON",
@@ -270,6 +271,7 @@ module Datadog
270
271
  "DD_TRACE_PRESTO_ENABLED",
271
272
  "DD_TRACE_PRESTO_PEER_SERVICE",
272
273
  "DD_TRACE_PRESTO_SERVICE_NAME",
274
+ "DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT",
273
275
  "DD_TRACE_PROPAGATION_EXTRACT_FIRST",
274
276
  "DD_TRACE_PROPAGATION_STYLE",
275
277
  "DD_TRACE_PROPAGATION_STYLE_EXTRACT",
@@ -34,8 +34,10 @@ module Datadog
34
34
 
35
35
  tags << "#{Environment::Ext::TAG_ENTRYPOINT_TYPE}:#{TagNormalizer.normalize(entrypoint_type, remove_digit_start_char: false)}"
36
36
 
37
- rails_name = TagNormalizer.normalize_process_value(@rails_application_name.to_s)
38
- tags << "#{Environment::Ext::TAG_RAILS_APPLICATION}:#{rails_name}" unless rails_name.empty?
37
+ if defined?(@rails_application_name)
38
+ rails_name = TagNormalizer.normalize_process_value(@rails_application_name.to_s)
39
+ tags << "#{Environment::Ext::TAG_RAILS_APPLICATION}:#{rails_name}" unless rails_name.empty?
40
+ end
39
41
 
40
42
  if defined?(@service_user_configured)
41
43
  if @service_user_configured
@@ -144,7 +144,7 @@ module Datadog
144
144
  # timeout and an integer otherwise
145
145
  # - before Ruby 3.2, ConditionVariable returns itself
146
146
  # so we have to rely on @once having been set
147
- if RUBY_VERSION >= '3.2'
147
+ if RubyVersion.is?('>= 3.2')
148
148
  lifted = @condition.wait(@mutex, timeout)
149
149
  else
150
150
  @condition.wait(@mutex, timeout)
@@ -146,27 +146,6 @@ module Datadog
146
146
  )
147
147
  end
148
148
 
149
- # OpenTelemetry configuration options (using environment variable names)
150
- otel_exporter_headers_option = resolve_option(settings, 'opentelemetry.exporter.headers')
151
- otel_exporter_headers_option.values_per_precedence.each do |precedence, value|
152
- list << conf_value(
153
- option_telemetry_name(otel_exporter_headers_option),
154
- # Steep: Value is always a hash for opentelemetry.exporter.headers (ensured by o.type :hash)
155
- value&.map { |key, header_value| "#{key}=#{header_value}" }&.join(','), # steep:ignore NoMethod
156
- precedence
157
- )
158
- end
159
-
160
- otel_metrics_headers_option = resolve_option(settings, 'opentelemetry.metrics.headers')
161
- otel_metrics_headers_option.values_per_precedence.each do |precedence, value|
162
- list << conf_value(
163
- option_telemetry_name(otel_metrics_headers_option),
164
- # Steep: Value is always a hash for opentelemetry.metrics.headers (ensured by o.type :hash)
165
- value&.map { |key, header_value| "#{key}=#{header_value}" }&.join(','), # steep:ignore NoMethod
166
- precedence
167
- )
168
- end
169
-
170
149
  # Add some more custom additional payload values here
171
150
  if settings.logger.instance
172
151
  logger_instance_option = resolve_option(settings, 'logger.instance')
@@ -16,7 +16,7 @@ module Datadog
16
16
  def self.apply!
17
17
  return false unless supported?
18
18
 
19
- if RUBY_VERSION < '3.1'
19
+ if RubyVersion.is?('< 3.1')
20
20
  [
21
21
  ::Process.singleton_class, # Process.fork
22
22
  ::Kernel.singleton_class, # Kernel.fork
@@ -3,8 +3,8 @@
3
3
  module Datadog
4
4
  module Core
5
5
  module Utils
6
- # Common array-related utility functions.
7
- module Array
6
+ # Bring newer Enumerable methods to older Ruby versions.
7
+ module EnumerableCompat
8
8
  def self.filter_map(array, &block)
9
9
  if array.respond_to?(:filter_map)
10
10
  # DEV Supported since Ruby 2.7, saves an intermediate object creation
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../ruby_version'
4
+
3
5
  module Datadog
4
6
  module Core
5
7
  module Utils
@@ -45,7 +47,7 @@ module Datadog
45
47
  # object will cause forking to not be detected in the fork when it should have.
46
48
  #
47
49
  # This wrapper prevents this by initializing the fork PID when the object is created.
48
- if RUBY_VERSION >= '3'
50
+ if RubyVersion.is?('>= 3')
49
51
  def initialize(*args, **kwargs, &block)
50
52
  super
51
53
  update_fork_pid!
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../ruby_version'
4
+
3
5
  module Datadog
4
6
  module Core
5
7
  module Utils
@@ -19,7 +21,7 @@ module Datadog
19
21
  # Prepends `Process.spawn` to merge `env_provider` output into the child's environment hash.
20
22
  module ProcessSpawnPatch
21
23
  # The One and Only Correct Delegation Pattern
22
- if RUBY_VERSION >= '3'
24
+ if RubyVersion.is?('>= 3')
23
25
  def spawn(*args, **kwargs) # steep:ignore DifferentMethodParameterKind
24
26
  super(*SpawnMonkeyPatch.inject_envs(args), **kwargs)
25
27
  end
data/lib/datadog/core.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Keep this at the top, this is needed at require-time by some files
4
+ require_relative 'ruby_version'
5
+
3
6
  require_relative 'core/deprecations'
4
7
  require_relative 'core/configuration/config_helper'
5
8
  require_relative 'core/extensions'
@@ -10,6 +10,9 @@
10
10
 
11
11
  require_relative 'code_tracker'
12
12
 
13
+ # Needed since this file can be loaded without core
14
+ require_relative '../ruby_version'
15
+
13
16
  module Datadog
14
17
  # Namespace for Datadog dynamic instrumentation.
15
18
  #
@@ -44,7 +47,7 @@ module Datadog
44
47
  # DI code.
45
48
  def activate_tracking
46
49
  # :script_compiled trace point was added in Ruby 2.6.
47
- return unless RUBY_VERSION >= '2.6'
50
+ return unless RubyVersion.is?('>= 2.6')
48
51
 
49
52
  begin
50
53
  # Activate code tracking by default because line trace points will not work
@@ -45,7 +45,7 @@ module Datadog
45
45
  logger.warn("di: cannot enable dynamic instrumentation: MRI is required, but running on #{RUBY_ENGINE}")
46
46
  return false
47
47
  end
48
- if RUBY_VERSION < '2.6'
48
+ if RubyVersion.is?('< 2.6')
49
49
  logger.warn("di: cannot enable dynamic instrumentation: Ruby 2.6+ is required, but running on #{RUBY_VERSION}")
50
50
  return false
51
51
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'ext'
4
+ require_relative '../ruby_version'
4
5
 
5
6
  module Datadog
6
7
  module ErrorTracking
@@ -52,7 +53,7 @@ module Datadog
52
53
  end
53
54
  end
54
55
 
55
- if RUBY_VERSION >= Ext::RUBY_VERSION_WITH_RESCUE_EVENT
56
+ if RubyVersion.is?(">= #{Ext::RUBY_VERSION_WITH_RESCUE_EVENT}")
56
57
  # Starting from ruby3.3, as we are listening to :rescue event,
57
58
  # we just want to remove the span event if the error was
58
59
  # previously handled
@@ -33,7 +33,7 @@ module Datadog
33
33
  if RUBY_ENGINE != 'ruby'
34
34
  logger.warn("error tracking: cannot enable error tracking: MRI is required, but running on #{RUBY_ENGINE}")
35
35
  false
36
- elsif RUBY_VERSION < '2.7'
36
+ elsif RubyVersion.is?('< 2.7')
37
37
  logger.warn(
38
38
  "error tracking: cannot enable error tracking: Ruby 2.7+ is required, but running
39
39
  on #{RUBY_VERSION}"
@@ -63,7 +63,7 @@ module Datadog
63
63
  # Before Ruby3.3 the TracePoint listen for :raise events.
64
64
  # If an error is not handled, we will delete the according
65
65
  # span event in the collector.
66
- event = (RUBY_VERSION >= '3.3') ? :rescue : :raise
66
+ event = RubyVersion.is?('>= 3.3') ? :rescue : :raise
67
67
 
68
68
  # This TracePoint is in charge of capturing the handled exceptions
69
69
  # and of adding the corresponding span events to the collector
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Needed since this file can be loaded without core
4
+ require_relative '../../ruby_version'
5
+
3
6
  module Datadog
4
7
  module Kit
5
8
  module Tracing
@@ -72,7 +75,7 @@ module Datadog
72
75
  raise ArgumentError, 'span name is not a String'
73
76
  end
74
77
 
75
- args = (RUBY_VERSION >= '2.7.') ? '...' : '*args, &block'
78
+ args = RubyVersion.is?('>= 2.7') ? '...' : '*args, &block'
76
79
 
77
80
  hook_module = Module.new do
78
81
  define_singleton_method(:inspect) do
@@ -43,6 +43,15 @@ module Datadog
43
43
  digest = @datadog_propagator.extract(carrier)
44
44
  return context unless digest
45
45
 
46
+ # Always call continue_trace! so span links are created in restart mode
47
+ # (when digest.trace_id is nil) before we attempt to build the OTel SpanContext.
48
+ trace = Tracing.continue_trace!(digest)
49
+
50
+ # In restart mode DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=restart, the extracted
51
+ # digest carries no trace_id (fresh start). continue_trace! has already recorded
52
+ # the span link; return the current context so the caller's span starts a new root.
53
+ return context unless digest.trace_id
54
+
46
55
  # Converts the {Numeric} Datadog id object to OpenTelemetry's byte array format.
47
56
  # 128-bit unsigned, big-endian integer
48
57
  trace_id = [digest.trace_id >> 64, digest.trace_id & 0xFFFFFFFFFFFFFFFF].pack('Q>Q>')
@@ -70,9 +79,6 @@ module Datadog
70
79
  )
71
80
 
72
81
  span = ::OpenTelemetry::Trace.non_recording_span(span_context)
73
-
74
- trace = Tracing.continue_trace!(digest)
75
-
76
82
  span.datadog_trace = trace
77
83
 
78
84
  ::OpenTelemetry::Trace.context_with_span(span, parent_context: context)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'trace/span'
4
+ require_relative '../../core/utils'
4
5
  require_relative '../../tracing/span_link'
5
6
  require_relative '../../tracing/span_event'
6
7
  require_relative '../../tracing/trace_digest'
@@ -101,12 +102,14 @@ module Datadog
101
102
 
102
103
  unless span.links.nil?
103
104
  datadog_span.links = span.links.map do |link|
105
+ tracestate = link.span_context.tracestate&.to_s
106
+
104
107
  Datadog::Tracing::SpanLink.new(
105
108
  Datadog::Tracing::TraceDigest.new(
106
109
  trace_id: link.span_context.hex_trace_id.to_i(16),
107
110
  span_id: link.span_context.hex_span_id.to_i(16),
108
111
  trace_sampling_priority: (link.span_context.trace_flags&.sampled? ? 1 : 0),
109
- trace_state: link.span_context.tracestate&.to_s,
112
+ trace_state: tracestate && ::Datadog::Core::Utils.utf8_encode(tracestate, placeholder: nil),
110
113
  span_remote: link.span_context.remote?,
111
114
  ),
112
115
  attributes: link.attributes
@@ -19,7 +19,6 @@ module Datadog
19
19
  max_frames:,
20
20
  tracer:,
21
21
  endpoint_collection_enabled:,
22
- timeline_enabled:,
23
22
  waiting_for_gvl_threshold_ns:,
24
23
  otel_context_enabled:,
25
24
  native_filenames_enabled:
@@ -31,10 +30,10 @@ module Datadog
31
30
  max_frames: max_frames,
32
31
  tracer_context_key: tracer_context_key,
33
32
  endpoint_collection_enabled: endpoint_collection_enabled,
34
- timeline_enabled: timeline_enabled,
35
33
  waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
36
34
  otel_context_enabled: otel_context_enabled,
37
35
  native_filenames_enabled: validate_native_filenames(native_filenames_enabled),
36
+ overhead_filename: __FILE__,
38
37
  )
39
38
  end
40
39
 
@@ -43,7 +42,6 @@ module Datadog
43
42
  max_frames: 400,
44
43
  tracer: nil,
45
44
  endpoint_collection_enabled: false,
46
- timeline_enabled: false,
47
45
  waiting_for_gvl_threshold_ns: 10_000_000,
48
46
  otel_context_enabled: false,
49
47
  native_filenames_enabled: true,
@@ -54,7 +52,6 @@ module Datadog
54
52
  max_frames: max_frames,
55
53
  tracer: tracer,
56
54
  endpoint_collection_enabled: endpoint_collection_enabled,
57
- timeline_enabled: timeline_enabled,
58
55
  waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
59
56
  otel_context_enabled: otel_context_enabled,
60
57
  native_filenames_enabled: native_filenames_enabled,
@@ -37,7 +37,6 @@ module Datadog
37
37
  # NOTE: Please update the Initialization section of ProfilingDevelopment.md with any changes to this method
38
38
 
39
39
  no_signals_workaround_enabled = no_signals_workaround_enabled?(settings, logger)
40
- timeline_enabled = settings.profiling.advanced.timeline_enabled
41
40
  allocation_profiling_enabled = enable_allocation_profiling?(settings, logger)
42
41
  heap_sample_every = get_heap_sample_every(settings)
43
42
  heap_profiling_enabled = enable_heap_profiling?(settings, allocation_profiling_enabled, heap_sample_every, logger)
@@ -53,10 +52,9 @@ module Datadog
53
52
  heap_samples_enabled: heap_profiling_enabled,
54
53
  heap_size_enabled: heap_size_profiling_enabled,
55
54
  heap_sample_every: heap_sample_every,
56
- timeline_enabled: timeline_enabled,
57
55
  heap_clean_after_gc_enabled: settings.profiling.advanced.heap_clean_after_gc_enabled,
58
56
  )
59
- thread_context_collector = build_thread_context_collector(settings, recorder, optional_tracer, timeline_enabled)
57
+ thread_context_collector = build_thread_context_collector(settings, recorder, optional_tracer)
60
58
  worker = Datadog::Profiling::Collectors::CpuAndWallTimeWorker.new(
61
59
  gc_profiling_enabled: enable_gc_profiling?(settings, logger),
62
60
  no_signals_workaround_enabled: no_signals_workaround_enabled,
@@ -71,7 +69,6 @@ module Datadog
71
69
 
72
70
  internal_metadata = {
73
71
  no_signals_workaround_enabled: no_signals_workaround_enabled,
74
- timeline_enabled: timeline_enabled,
75
72
  heap_sample_every: heap_sample_every,
76
73
  }.freeze
77
74
 
@@ -99,13 +96,12 @@ module Datadog
99
96
  [nil, {profiling_enabled: false}]
100
97
  end
101
98
 
102
- private_class_method def self.build_thread_context_collector(settings, recorder, optional_tracer, timeline_enabled)
99
+ private_class_method def self.build_thread_context_collector(settings, recorder, optional_tracer)
103
100
  Datadog::Profiling::Collectors::ThreadContext.new(
104
101
  recorder: recorder,
105
102
  max_frames: settings.profiling.advanced.max_frames,
106
103
  tracer: optional_tracer,
107
104
  endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled,
108
- timeline_enabled: timeline_enabled,
109
105
  waiting_for_gvl_threshold_ns: settings.profiling.advanced.waiting_for_gvl_threshold_ns,
110
106
  otel_context_enabled: settings.profiling.advanced.preview_otel_context_enabled,
111
107
  native_filenames_enabled: settings.profiling.advanced.native_filenames_enabled,
@@ -145,15 +141,14 @@ module Datadog
145
141
  # that causes a segmentation fault during garbage collection of Ractors
146
142
  # (https://bugs.ruby-lang.org/issues/18464). We don't allow enabling gc profiling on such Rubies.
147
143
  # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
148
- if RUBY_VERSION.start_with?("3.0.") ||
149
- (RUBY_VERSION.start_with?("3.1.") && RUBY_VERSION < "3.1.4") ||
150
- (RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3")
144
+ if RubyVersion.is?(">= 3", "< 3.1.4") ||
145
+ RubyVersion.is?(">= 3.2", "< 3.2.3")
151
146
  logger.warn(
152
147
  "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling GC profiling would cause " \
153
148
  "crashes (https://bugs.ruby-lang.org/issues/18464). GC profiling has been disabled."
154
149
  )
155
150
  return false
156
- elsif RUBY_VERSION.start_with?("3.")
151
+ elsif RubyVersion.is?(">= 3", "< 4")
157
152
  logger.debug(
158
153
  "Using Ractors may result in GC profiling unexpectedly " \
159
154
  "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
@@ -181,7 +176,7 @@ module Datadog
181
176
  # Ruby 3.2.0 to 3.2.2 have a bug in the newobj tracepoint (https://bugs.ruby-lang.org/issues/19482,
182
177
  # https://github.com/ruby/ruby/pull/7464) that makes this crash in any configuration. This bug is
183
178
  # fixed on Ruby versions 3.2.3 and 3.3.0.
184
- if RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3"
179
+ if RubyVersion.is?(">= 3.2", "< 3.2.3")
185
180
  logger.warn(
186
181
  "Allocation profiling is not supported in Ruby versions 3.2.0, 3.2.1 and 3.2.2 and will be forcibly " \
187
182
  "disabled. This is due to a VM bug that can lead to crashes (https://bugs.ruby-lang.org/issues/19482). " \
@@ -195,9 +190,8 @@ module Datadog
195
190
  # that causes a segmentation fault during garbage collection of Ractors
196
191
  # (https://bugs.ruby-lang.org/issues/18464). We don't recommend using this feature on such Rubies.
197
192
  # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
198
- if RUBY_VERSION.start_with?("3.0.") ||
199
- (RUBY_VERSION.start_with?("3.1.") && RUBY_VERSION < "3.1.4") ||
200
- (RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3")
193
+ if RubyVersion.is?(">= 3", "< 3.1.4") ||
194
+ RubyVersion.is?(">= 3.2", "< 3.2.3")
201
195
  logger.warn(
202
196
  "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling allocation profiling while using " \
203
197
  "Ractors may cause unexpected issues, including crashes (https://bugs.ruby-lang.org/issues/18464). " \
@@ -206,7 +200,7 @@ module Datadog
206
200
  # ANNOYANCE - Only with Ractors
207
201
  # On all known versions of Ruby 3.x, due to https://bugs.ruby-lang.org/issues/19112, when a ractor gets
208
202
  # garbage collected, Ruby will disable all active tracepoints, which this feature internally relies on.
209
- elsif RUBY_VERSION.start_with?("3.")
203
+ elsif RubyVersion.is?(">= 3", "< 4")
210
204
  logger.debug(
211
205
  "Using Ractors may result in allocation profiling " \
212
206
  "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
@@ -224,7 +218,7 @@ module Datadog
224
218
 
225
219
  return false unless heap_profiling_enabled
226
220
 
227
- if RUBY_VERSION < "3.1"
221
+ if RubyVersion.is?("< 3.1")
228
222
  logger.warn(
229
223
  "Current Ruby version (#{RUBY_VERSION}) cannot support heap profiling due to VM limitations. " \
230
224
  "Please upgrade to Ruby >= 3.1 in order to use this feature. Heap profiling has been disabled."
@@ -266,7 +260,7 @@ module Datadog
266
260
  end
267
261
 
268
262
  if setting_value == false
269
- if RUBY_VERSION.start_with?("2.5.")
263
+ if RubyVersion.is?("< 2.6")
270
264
  logger.warn(
271
265
  'The profiling "no signals" workaround has been disabled via configuration on Ruby 2.5. ' \
272
266
  "This is not recommended " \
@@ -292,7 +286,7 @@ module Datadog
292
286
  # Setting is in auto mode. Let's probe to see if we should enable it:
293
287
 
294
288
  # We don't warn users in this situation because "upgrade your Ruby" is not a great warning
295
- return true if RUBY_VERSION.start_with?("2.5.")
289
+ return true if RubyVersion.is?("< 2.6")
296
290
 
297
291
  if Gem.loaded_specs["mysql2"] && incompatible_libmysqlclient_version?(settings, logger)
298
292
  logger.warn(
@@ -454,13 +448,13 @@ module Datadog
454
448
  end
455
449
 
456
450
  private_class_method def self.dir_interruption_workaround_enabled?(settings, no_signals_workaround_enabled)
457
- return false if no_signals_workaround_enabled || RUBY_VERSION >= "3.4"
451
+ return false if no_signals_workaround_enabled || RubyVersion.is?(">= 3.4")
458
452
 
459
453
  settings.profiling.advanced.dir_interruption_workaround_enabled
460
454
  end
461
455
 
462
456
  private_class_method def self.can_apply_exec_monkey_patch?(settings)
463
- return false if RUBY_VERSION < "2.7"
457
+ return false if RubyVersion.is?("< 2.7")
464
458
 
465
459
  # This file is 2.7+ only so we only require it here once we've checked the Ruby version
466
460
  require "datadog/profiling/ext/exec_monkey_patch"
@@ -469,11 +463,7 @@ module Datadog
469
463
  end
470
464
 
471
465
  private_class_method def self.enable_gvl_profiling?(settings, logger)
472
- return false if RUBY_VERSION < "3.2"
473
-
474
- # GVL profiling only makes sense in the context of timeline. We could emit a warning here, but not sure how
475
- # useful it is -- if a customer disables timeline, there's nowhere to look for GVL profiling anyway!
476
- settings.profiling.advanced.timeline_enabled && settings.profiling.advanced.gvl_enabled
466
+ RubyVersion.is?(">= 3.2") && settings.profiling.advanced.gvl_enabled
477
467
  end
478
468
  end
479
469
  end
@@ -4,9 +4,10 @@ module Datadog
4
4
  module Profiling
5
5
  # Monkey patches needed for profiler features and compatibility
6
6
  module Ext
7
- # All Ruby versions as of this writing have bugs in the dir class implementation, causing issues such as
7
+ # Ruby versions before 3.4 have bugs in the `Dir` class implementation, causing issues such as
8
8
  # https://github.com/DataDog/dd-trace-rb/issues/3450 .
9
- # See also https://bugs.ruby-lang.org/issues/20586 for more details.
9
+ # This was fixed upstream in https://bugs.ruby-lang.org/issues/20586 but we use this monkey patch to work around
10
+ # the issue on legacy versions (it gets applied by `Datadog::Profiling::Component`).
10
11
  #
11
12
  # This monkey patch for the Ruby `Dir` class works around these bugs for affected Ruby versions by temporarily
12
13
  # blocking the profiler from interrupting system calls.
@@ -27,7 +28,7 @@ module Datadog
27
28
  end
28
29
  end
29
30
 
30
- if RUBY_VERSION.start_with?("2.")
31
+ if RubyVersion.is?("< 3")
31
32
  # Monkey patches for Dir.singleton_class (Ruby 2 version). See DirMonkeyPatches above for more details.
32
33
  module DirClassMonkeyPatches
33
34
  # Steep: Workaround that defines args and block only for Ruby 2.x.
@@ -269,7 +270,7 @@ module Datadog
269
270
  end
270
271
  end
271
272
 
272
- if RUBY_VERSION.start_with?("2.")
273
+ if RubyVersion.is?("< 3")
273
274
  # Monkey patches for Dir (Ruby 2 version). See DirMonkeyPatches above for more details.
274
275
  module DirInstanceMonkeyPatches
275
276
  # Steep: Workaround that defines args and block only for Ruby 2.x.
@@ -299,7 +300,7 @@ module Datadog
299
300
  end
300
301
  end
301
302
 
302
- unless RUBY_VERSION.start_with?("2.5.") # This is Ruby 2.6+
303
+ if RubyVersion.is?(">= 2.6.0") # This method is Ruby 2.6+
303
304
  # See note on methods that yield above.
304
305
  def each_child(*args, &block)
305
306
  if block
@@ -13,7 +13,6 @@ module Datadog
13
13
  heap_samples_enabled:,
14
14
  heap_size_enabled:,
15
15
  heap_sample_every:,
16
- timeline_enabled:,
17
16
  heap_clean_after_gc_enabled:
18
17
  )
19
18
  # This mutex works in addition to the fancy C-level mutexes we have in the native side (see the docs there).
@@ -30,7 +29,6 @@ module Datadog
30
29
  heap_samples_enabled: heap_samples_enabled,
31
30
  heap_size_enabled: heap_size_enabled,
32
31
  heap_sample_every: heap_sample_every,
33
- timeline_enabled: timeline_enabled,
34
32
  heap_clean_after_gc_enabled: heap_clean_after_gc_enabled,
35
33
  )
36
34
  end
@@ -40,7 +38,6 @@ module Datadog
40
38
  heap_samples_enabled: false,
41
39
  heap_size_enabled: false,
42
40
  heap_sample_every: 1,
43
- timeline_enabled: false,
44
41
  heap_clean_after_gc_enabled: true,
45
42
  **options
46
43
  )
@@ -49,7 +46,6 @@ module Datadog
49
46
  heap_samples_enabled: heap_samples_enabled,
50
47
  heap_size_enabled: heap_size_enabled,
51
48
  heap_sample_every: heap_sample_every,
52
- timeline_enabled: timeline_enabled,
53
49
  heap_clean_after_gc_enabled: heap_clean_after_gc_enabled,
54
50
  **options,
55
51
  )
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ # Compares the running Ruby against version requirements.
5
+ #
6
+ # Lexical comparisons against `RUBY_VERSION` are subtly wrong: `RUBY_VERSION < "3.2.3"` is also
7
+ # `true` on 3.2.10 and 3.2.11, since those sort *before* "3.2.3" as strings.
8
+ #
9
+ # @example
10
+ # RubyVersion.is?(">= 3.2", "< 3.2.3") # => true on Ruby 3.2.0, 3.2.1, 3.2.2 (NOT 3.2.3+, NOT 3.2.10+)
11
+ module RubyVersion
12
+ extend RubyVersion # steep currently needs this (instead of extend self or def self.is?) for the inline rbs to work
13
+
14
+ CURRENT_RUBY_VERSION = Gem::Version.new(RUBY_VERSION) #: ::Gem::Version
15
+ private_constant :CURRENT_RUBY_VERSION
16
+
17
+ # Returns `true` when the running Ruby satisfies ALL of the given requirements. Each uses the
18
+ # same syntax as a gem dependency (e.g. `">= 3.1"`, `">= 3.2"`, `"< 3.2.3"`).
19
+ #
20
+ # @rbs (*String requirements, ?ruby_version: ::Gem::Version) -> bool
21
+ def is?(*requirements, ruby_version: CURRENT_RUBY_VERSION)
22
+ Gem::Requirement.new(*requirements).satisfied_by?(ruby_version)
23
+ end
24
+ end
25
+ end