datadog 2.29.0 → 2.31.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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +87 -2
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +21 -12
  4. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +9 -7
  5. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +18 -0
  6. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
  7. data/ext/datadog_profiling_native_extension/extconf.rb +6 -24
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +5 -6
  9. data/ext/datadog_profiling_native_extension/http_transport.c +51 -64
  10. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
  11. data/ext/datadog_profiling_native_extension/profiling.c +3 -1
  12. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +24 -8
  13. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -3
  14. data/ext/datadog_profiling_native_extension/stack_recorder.c +29 -43
  15. data/ext/libdatadog_api/crashtracker.c +5 -8
  16. data/ext/libdatadog_api/crashtracker_report_exception.c +34 -144
  17. data/ext/libdatadog_api/datadog_ruby_common.c +18 -0
  18. data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
  19. data/ext/libdatadog_api/di.c +79 -0
  20. data/ext/libdatadog_api/extconf.rb +5 -20
  21. data/ext/libdatadog_api/init.c +5 -2
  22. data/ext/libdatadog_extconf_helpers.rb +57 -11
  23. data/lib/datadog/ai_guard/component.rb +2 -0
  24. data/lib/datadog/ai_guard/configuration/settings.rb +3 -0
  25. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +41 -3
  26. data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
  27. data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
  28. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +3 -1
  29. data/lib/datadog/ai_guard/evaluation/request.rb +14 -9
  30. data/lib/datadog/ai_guard/evaluation/result.rb +3 -1
  31. data/lib/datadog/ai_guard/evaluation.rb +36 -7
  32. data/lib/datadog/ai_guard.rb +26 -8
  33. data/lib/datadog/appsec/autoload.rb +1 -1
  34. data/lib/datadog/appsec/component.rb +11 -7
  35. data/lib/datadog/appsec/contrib/active_record/patcher.rb +3 -0
  36. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  37. data/lib/datadog/appsec/contrib/excon/patcher.rb +2 -0
  38. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
  39. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
  40. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
  41. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +10 -11
  42. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  43. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +25 -2
  44. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  45. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
  46. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  47. data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
  48. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +2 -0
  49. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +2 -2
  50. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +3 -3
  51. data/lib/datadog/appsec/event.rb +1 -17
  52. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
  53. data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
  54. data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -2
  55. data/lib/datadog/appsec/utils/http/media_type.rb +1 -2
  56. data/lib/datadog/appsec/utils/http/url_encoded.rb +2 -2
  57. data/lib/datadog/appsec.rb +5 -9
  58. data/lib/datadog/core/configuration/base.rb +17 -5
  59. data/lib/datadog/core/configuration/components.rb +21 -8
  60. data/lib/datadog/core/configuration/config_helper.rb +9 -0
  61. data/lib/datadog/core/configuration/option.rb +32 -6
  62. data/lib/datadog/core/configuration/option_definition.rb +38 -12
  63. data/lib/datadog/core/configuration/options.rb +41 -7
  64. data/lib/datadog/core/configuration/settings.rb +42 -3
  65. data/lib/datadog/core/configuration/supported_configurations.rb +17 -0
  66. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  67. data/lib/datadog/core/contrib/rails/utils.rb +7 -3
  68. data/lib/datadog/core/crashtracking/component.rb +7 -15
  69. data/lib/datadog/core/environment/container.rb +2 -2
  70. data/lib/datadog/core/environment/ext.rb +1 -0
  71. data/lib/datadog/core/environment/identity.rb +25 -3
  72. data/lib/datadog/core/environment/process.rb +12 -0
  73. data/lib/datadog/core/metrics/client.rb +5 -5
  74. data/lib/datadog/core/process_discovery.rb +5 -0
  75. data/lib/datadog/core/remote/component.rb +38 -21
  76. data/lib/datadog/core/runtime/metrics.rb +2 -3
  77. data/lib/datadog/core/telemetry/component.rb +3 -0
  78. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
  79. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  80. data/lib/datadog/core/telemetry/event/app_started.rb +151 -169
  81. data/lib/datadog/core/telemetry/event.rb +1 -7
  82. data/lib/datadog/core/telemetry/ext.rb +1 -0
  83. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -0
  84. data/lib/datadog/core/telemetry/worker.rb +20 -0
  85. data/lib/datadog/core/utils/base64.rb +1 -1
  86. data/lib/datadog/core/utils/only_once.rb +1 -1
  87. data/lib/datadog/core/utils/spawn_monkey_patch.rb +36 -0
  88. data/lib/datadog/core/workers/async.rb +1 -1
  89. data/lib/datadog/core/workers/interval_loop.rb +13 -6
  90. data/lib/datadog/core/workers/queue.rb +0 -4
  91. data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
  92. data/lib/datadog/core.rb +0 -1
  93. data/lib/datadog/data_streams/pathway_context.rb +1 -1
  94. data/lib/datadog/data_streams/processor.rb +1 -0
  95. data/lib/datadog/di/boot.rb +3 -4
  96. data/lib/datadog/di/component.rb +20 -4
  97. data/lib/datadog/di/instrumenter.rb +20 -10
  98. data/lib/datadog/di/probe_manager.rb +79 -62
  99. data/lib/datadog/di/probe_notification_builder.rb +148 -33
  100. data/lib/datadog/di/probe_notifier_worker.rb +52 -6
  101. data/lib/datadog/di/probe_repository.rb +198 -0
  102. data/lib/datadog/di/remote.rb +5 -6
  103. data/lib/datadog/di/serializer.rb +127 -9
  104. data/lib/datadog/di/transport/http.rb +12 -3
  105. data/lib/datadog/di/transport/input.rb +46 -8
  106. data/lib/datadog/di.rb +81 -0
  107. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  108. data/lib/datadog/open_feature/configuration.rb +2 -0
  109. data/lib/datadog/open_feature/evaluation_engine.rb +1 -1
  110. data/lib/datadog/open_feature/exposures/reporter.rb +1 -1
  111. data/lib/datadog/open_feature/exposures/worker.rb +1 -1
  112. data/lib/datadog/open_feature/remote.rb +1 -1
  113. data/lib/datadog/open_feature/transport.rb +1 -1
  114. data/lib/datadog/opentelemetry/configuration/settings.rb +2 -0
  115. data/lib/datadog/profiling/collectors/code_provenance.rb +2 -3
  116. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +14 -1
  117. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  118. data/lib/datadog/profiling/component.rb +31 -1
  119. data/lib/datadog/profiling/http_transport.rb +5 -6
  120. data/lib/datadog/profiling/load_native_extension.rb +1 -1
  121. data/lib/datadog/profiling/profiler.rb +15 -12
  122. data/lib/datadog/profiling/scheduler.rb +2 -2
  123. data/lib/datadog/profiling/tasks/exec.rb +2 -2
  124. data/lib/datadog/profiling/tasks/setup.rb +2 -2
  125. data/lib/datadog/profiling.rb +1 -2
  126. data/lib/datadog/single_step_instrument.rb +1 -1
  127. data/lib/datadog/tracing/buffer.rb +3 -3
  128. data/lib/datadog/tracing/component.rb +11 -0
  129. data/lib/datadog/tracing/configuration/settings.rb +2 -1
  130. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -2
  131. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +20 -0
  132. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
  133. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  134. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  135. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  136. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  137. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  138. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  139. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  140. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  141. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  142. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  143. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
  144. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  145. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -1
  146. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  147. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
  148. data/lib/datadog/tracing/contrib/configurable.rb +18 -3
  149. data/lib/datadog/tracing/contrib/dalli/integration.rb +4 -1
  150. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
  151. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
  152. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  153. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +5 -2
  154. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  155. data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
  156. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +5 -2
  157. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  158. data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
  159. data/lib/datadog/tracing/contrib/grape/endpoint.rb +7 -7
  160. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
  161. data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
  162. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
  163. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  164. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +5 -2
  165. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  166. data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -1
  167. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +5 -2
  168. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  169. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +5 -2
  170. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  171. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -1
  172. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
  173. data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
  174. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
  175. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
  176. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  177. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +5 -1
  178. data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
  179. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +5 -2
  180. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  181. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  182. data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -1
  183. data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
  184. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
  185. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  186. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
  187. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  188. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
  189. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  190. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
  191. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  192. data/lib/datadog/tracing/contrib/status_range_matcher.rb +4 -0
  193. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  194. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +5 -1
  195. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +1 -0
  196. data/lib/datadog/tracing/distributed/datadog.rb +4 -2
  197. data/lib/datadog/tracing/event.rb +1 -1
  198. data/lib/datadog/tracing/metadata/ext.rb +4 -0
  199. data/lib/datadog/tracing/remote.rb +1 -1
  200. data/lib/datadog/tracing/sampling/ext.rb +2 -0
  201. data/lib/datadog/tracing/sampling/priority_sampler.rb +13 -0
  202. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  203. data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
  204. data/lib/datadog/tracing/sampling/span/rule_parser.rb +1 -1
  205. data/lib/datadog/tracing/span_operation.rb +1 -1
  206. data/lib/datadog/tracing/sync_writer.rb +0 -1
  207. data/lib/datadog/tracing/trace_operation.rb +50 -6
  208. data/lib/datadog/tracing/tracer.rb +25 -0
  209. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  210. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  211. data/lib/datadog/tracing/writer.rb +0 -1
  212. data/lib/datadog/version.rb +1 -1
  213. metadata +15 -8
  214. data/lib/datadog/tracing/workers/trace_writer.rb +0 -204
@@ -27,6 +27,8 @@ module Datadog
27
27
  include Metadata::Tagging
28
28
 
29
29
  DEFAULT_MAX_LENGTH = 100_000
30
+ AUTO_SAMPLING_PRIORITIES = [Sampling::Ext::Priority::AUTO_KEEP, Sampling::Ext::Priority::AUTO_REJECT].freeze
31
+ RECONSIDERABLE_DECISIONS = [Sampling::Ext::Decision::DEFAULT, Sampling::Ext::Decision::AGENT_RATE].freeze
30
32
 
31
33
  attr_accessor \
32
34
  :agent_sample_rate,
@@ -51,7 +53,6 @@ module Datadog
51
53
 
52
54
  attr_writer \
53
55
  :name,
54
- :resource,
55
56
  :sampled,
56
57
  :service
57
58
 
@@ -127,6 +128,8 @@ module Datadog
127
128
  @finished = false
128
129
  @spans = []
129
130
  @auto_finish = !!auto_finish
131
+ @flushed = false
132
+ @propagated = false
130
133
  end
131
134
 
132
135
  def full?
@@ -170,6 +173,17 @@ module Datadog
170
173
  set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, Tracing::Sampling::Ext::Decision::MANUAL)
171
174
  end
172
175
 
176
+ def resource=(value)
177
+ previous_resource = @resource
178
+ @resource = value
179
+
180
+ return if !!previous_resource || value.nil?
181
+
182
+ events.trace_resource_change.publish(self)
183
+ rescue => e
184
+ logger.debug { "Error updating trace resource: #{e} Backtrace: #{e.backtrace.first(3)}" }
185
+ end
186
+
173
187
  def name
174
188
  @name || root_span&.name
175
189
  end
@@ -208,6 +222,12 @@ module Datadog
208
222
  !@resource.nil?
209
223
  end
210
224
 
225
+ def reconsider_resource_sample?
226
+ return false if @resource.nil?
227
+
228
+ reconsider_rule_sample?
229
+ end
230
+
211
231
  def service
212
232
  @service || root_span&.service
213
233
  end
@@ -274,15 +294,15 @@ module Datadog
274
294
  parent_id = parent ? parent.id : @parent_span_id || 0
275
295
 
276
296
  # Build events
277
- events ||= SpanOperation::Events.new(logger: logger)
297
+ span_events = events || SpanOperation::Events.new(logger: logger)
278
298
 
279
299
  # Before start: activate the span, publish events.
280
- events.before_start.subscribe do |span_op|
300
+ span_events.before_start.subscribe do |span_op|
281
301
  start_span(span_op)
282
302
  end
283
303
 
284
304
  # After finish: deactivate the span, record, publish events.
285
- events.after_finish.subscribe do |span, span_op|
305
+ span_events.after_finish.subscribe do |span, span_op|
286
306
  finish_span(span, span_op, parent)
287
307
  end
288
308
 
@@ -290,7 +310,7 @@ module Datadog
290
310
  SpanOperation.new(
291
311
  op_name,
292
312
  logger: logger,
293
- events: events,
313
+ events: span_events,
294
314
  on_error: on_error,
295
315
  parent_id: parent_id,
296
316
  resource: resource || op_name,
@@ -319,6 +339,7 @@ module Datadog
319
339
  # Copy out completed spans
320
340
  spans = @spans.dup
321
341
  @spans = []
342
+ @flushed = true
322
343
 
323
344
  spans = yield(spans) if block_given?
324
345
 
@@ -359,6 +380,7 @@ module Datadog
359
380
  span_id = @active_span&.id
360
381
  span_id ||= @parent_span_id unless finished?
361
382
  # sample the trace_operation with the tracer
383
+ @propagated = true
362
384
  events.trace_propagated.publish(self)
363
385
 
364
386
  TraceDigest.new(
@@ -430,13 +452,15 @@ module Datadog
430
452
  :span_before_start,
431
453
  :span_finished,
432
454
  :trace_finished,
433
- :trace_propagated
455
+ :trace_propagated,
456
+ :trace_resource_change
434
457
 
435
458
  def initialize
436
459
  @span_before_start = SpanBeforeStart.new
437
460
  @span_finished = SpanFinished.new
438
461
  @trace_finished = TraceFinished.new
439
462
  @trace_propagated = TracePropagated.new
463
+ @trace_resource_change = TraceResourceChange.new
440
464
  end
441
465
 
442
466
  # Triggered before a span starts.
@@ -476,6 +500,14 @@ module Datadog
476
500
  subscribe(&block)
477
501
  end
478
502
  end
503
+
504
+ # Triggered when the resource name is set
505
+ # This is used to reconsider trace sampling on resource name change
506
+ class TraceResourceChange < Tracing::Event
507
+ def initialize
508
+ super(:trace_resource_change)
509
+ end
510
+ end
479
511
  end
480
512
 
481
513
  private
@@ -582,12 +614,24 @@ module Datadog
582
614
  meta.select { |name, _| name.start_with?(Metadata::Ext::Distributed::TAGS_PREFIX) }
583
615
  end
584
616
 
617
+ def reconsider_rule_sample?
618
+ decision = get_tag(Metadata::Ext::Distributed::TAG_DECISION_MAKER)
619
+
620
+ return false if remote_parent || @propagated || @flushed
621
+ return false unless AUTO_SAMPLING_PRIORITIES.include?(@sampling_priority)
622
+ return false if decision && !RECONSIDERABLE_DECISIONS.include?(decision)
623
+
624
+ true
625
+ end
626
+
585
627
  def reset
586
628
  @root_span = nil
587
629
  @active_span = nil
588
630
  @active_span_count = 0
589
631
  @finished = false
590
632
  @spans = []
633
+ @flushed = false
634
+ @propagated = false
591
635
  end
592
636
  end
593
637
  end
@@ -307,6 +307,19 @@ module Datadog
307
307
  end
308
308
  end
309
309
 
310
+ def reconsider_trace_sampling_on_resource(trace_op)
311
+ return unless trace_op.reconsider_resource_sample?
312
+ return unless @sampler.respond_to?(:reconsider_sample_resource!)
313
+
314
+ @sampler.reconsider_sample_resource!(trace_op)
315
+ rescue => e
316
+ RECONSIDER_RESOURCE_SAMPLE_TRACE_LOG_ONLY_ONCE.run do
317
+ logger.warn do
318
+ "Failed to reconsider trace sampling: #{e.class.name} #{e} at #{Array(e.backtrace).first}"
319
+ end
320
+ end
321
+ end
322
+
310
323
  # @!visibility private
311
324
  # TODO: make this private
312
325
  def trace_completed
@@ -415,6 +428,15 @@ module Datadog
415
428
  sample_span(event_trace_op, event_span)
416
429
  flush_trace(event_trace_op)
417
430
  end
431
+
432
+ # Conditionally subscribe to the less common sampling rules below, to avoid
433
+ # measurable unnecessary performance overhead when they are not present.
434
+
435
+ if @sampler.respond_to?(:resource_sampling?) && @sampler.resource_sampling?
436
+ events.trace_resource_change.subscribe do |event_trace_op|
437
+ reconsider_trace_sampling_on_resource(event_trace_op)
438
+ end
439
+ end
418
440
  end
419
441
 
420
442
  # Creates a new TraceOperation, with events bounds to this Tracer instance.
@@ -534,6 +556,9 @@ module Datadog
534
556
  SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
535
557
  private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
536
558
 
559
+ RECONSIDER_RESOURCE_SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
560
+ private_constant :RECONSIDER_RESOURCE_SAMPLE_TRACE_LOG_ONLY_ONCE
561
+
537
562
  def sample_span(trace_op, span)
538
563
  @span_sampler.sample!(trace_op, span)
539
564
  rescue => e
@@ -44,7 +44,7 @@ module Datadog
44
44
  response
45
45
  rescue => e
46
46
  message =
47
- "Internal error during IO transport request. Cause: #{e.class.name}: #{e.message} " \
47
+ "Internal error during IO transport request. Cause: #{e.class}: #{e} " \
48
48
  "Location: #{Array(e.backtrace).first}"
49
49
 
50
50
  # Log error
@@ -49,6 +49,7 @@ module Datadog
49
49
 
50
50
  tag_agent_sample_rate!
51
51
  tag_hostname!
52
+ tag_knuth_sampling_rate!
52
53
  tag_lang!
53
54
  tag_origin!
54
55
  tag_process_id!
@@ -110,6 +111,16 @@ module Datadog
110
111
  )
111
112
  end
112
113
 
114
+ def tag_knuth_sampling_rate!
115
+ rate = trace.rule_sample_rate || trace.agent_sample_rate
116
+ return unless rate
117
+
118
+ root_span.set_tag(
119
+ Tracing::Metadata::Ext::Distributed::TAG_KNUTH_SAMPLING_RATE,
120
+ format('%.6f', (rate * 1e6).round / 1e6.to_f).sub(/\.?0+\z/, '')
121
+ )
122
+ end
123
+
113
124
  def tag_lang!
114
125
  return if trace.lang.nil?
115
126
 
@@ -9,7 +9,6 @@ require_relative 'transport/http'
9
9
  module Datadog
10
10
  module Tracing
11
11
  # Processor that sends traces and metadata to the agent
12
- # DEV: Our goal is for {Datadog::Tracing::Workers::TraceWriter} to replace this class in the future
13
12
  # @public_api
14
13
  class Writer
15
14
  attr_reader \
@@ -3,7 +3,7 @@
3
3
  module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 29
6
+ MINOR = 31
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
  BUILD = nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.29.0
4
+ version: 2.31.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-20 00:00:00.000000000 Z
11
+ date: 2026-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -64,14 +64,14 @@ dependencies:
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 25.0.0.1.0
67
+ version: 30.0.0.1.0
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 25.0.0.1.0
74
+ version: 30.0.0.1.0
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: logger
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -173,6 +173,7 @@ files:
173
173
  - ext/libdatadog_api/datadog_ruby_common.c
174
174
  - ext/libdatadog_api/datadog_ruby_common.h
175
175
  - ext/libdatadog_api/ddsketch.c
176
+ - ext/libdatadog_api/di.c
176
177
  - ext/libdatadog_api/extconf.rb
177
178
  - ext/libdatadog_api/feature_flags.c
178
179
  - ext/libdatadog_api/feature_flags.h
@@ -195,6 +196,8 @@ files:
195
196
  - lib/datadog/ai_guard/contrib/ruby_llm/integration.rb
196
197
  - lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb
197
198
  - lib/datadog/ai_guard/evaluation.rb
199
+ - lib/datadog/ai_guard/evaluation/content_builder.rb
200
+ - lib/datadog/ai_guard/evaluation/content_part.rb
198
201
  - lib/datadog/ai_guard/evaluation/message.rb
199
202
  - lib/datadog/ai_guard/evaluation/no_op_result.rb
200
203
  - lib/datadog/ai_guard/evaluation/request.rb
@@ -261,6 +264,7 @@ files:
261
264
  - lib/datadog/appsec/contrib/rack/patcher.rb
262
265
  - lib/datadog/appsec/contrib/rack/request_body_middleware.rb
263
266
  - lib/datadog/appsec/contrib/rack/request_middleware.rb
267
+ - lib/datadog/appsec/contrib/rack/response_body.rb
264
268
  - lib/datadog/appsec/contrib/rails/framework.rb
265
269
  - lib/datadog/appsec/contrib/rails/gateway/request.rb
266
270
  - lib/datadog/appsec/contrib/rails/gateway/watcher.rb
@@ -338,6 +342,7 @@ files:
338
342
  - lib/datadog/core/configuration/settings.rb
339
343
  - lib/datadog/core/configuration/stable_config.rb
340
344
  - lib/datadog/core/configuration/supported_configurations.rb
345
+ - lib/datadog/core/contrib/rails/railtie.rb
341
346
  - lib/datadog/core/contrib/rails/utils.rb
342
347
  - lib/datadog/core/crashtracking/component.rb
343
348
  - lib/datadog/core/crashtracking/tag_builder.rb
@@ -413,6 +418,7 @@ files:
413
418
  - lib/datadog/core/telemetry/event/app_closing.rb
414
419
  - lib/datadog/core/telemetry/event/app_dependencies_loaded.rb
415
420
  - lib/datadog/core/telemetry/event/app_endpoints_loaded.rb
421
+ - lib/datadog/core/telemetry/event/app_extended_heartbeat.rb
416
422
  - lib/datadog/core/telemetry/event/app_heartbeat.rb
417
423
  - lib/datadog/core/telemetry/event/app_integrations_change.rb
418
424
  - lib/datadog/core/telemetry/event/app_started.rb
@@ -466,6 +472,7 @@ files:
466
472
  - lib/datadog/core/utils/only_once_successful.rb
467
473
  - lib/datadog/core/utils/safe_dup.rb
468
474
  - lib/datadog/core/utils/sequence.rb
475
+ - lib/datadog/core/utils/spawn_monkey_patch.rb
469
476
  - lib/datadog/core/utils/time.rb
470
477
  - lib/datadog/core/utils/truncation.rb
471
478
  - lib/datadog/core/utils/url.rb
@@ -520,6 +527,7 @@ files:
520
527
  - lib/datadog/di/probe_manager.rb
521
528
  - lib/datadog/di/probe_notification_builder.rb
522
529
  - lib/datadog/di/probe_notifier_worker.rb
530
+ - lib/datadog/di/probe_repository.rb
523
531
  - lib/datadog/di/proc_responder.rb
524
532
  - lib/datadog/di/redactor.rb
525
533
  - lib/datadog/di/remote.rb
@@ -1093,7 +1101,6 @@ files:
1093
1101
  - lib/datadog/tracing/transport/traces.rb
1094
1102
  - lib/datadog/tracing/utils.rb
1095
1103
  - lib/datadog/tracing/workers.rb
1096
- - lib/datadog/tracing/workers/trace_writer.rb
1097
1104
  - lib/datadog/tracing/writer.rb
1098
1105
  - lib/datadog/version.rb
1099
1106
  homepage: https://github.com/DataDog/dd-trace-rb
@@ -1102,9 +1109,9 @@ licenses:
1102
1109
  - Apache-2.0
1103
1110
  metadata:
1104
1111
  allowed_push_host: https://rubygems.org
1105
- changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.29.0/CHANGELOG.md
1106
- source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.29.0
1107
- post_install_message:
1112
+ changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.31.0/CHANGELOG.md
1113
+ source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.31.0
1114
+ post_install_message: 'JRuby support in the datadog gem is deprecated. Details: https://dtdg.co/jruby-deprecation'
1108
1115
  rdoc_options: []
1109
1116
  require_paths:
1110
1117
  - lib
@@ -1,204 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../core/worker'
4
- require_relative '../../core/workers/async'
5
- require_relative '../../core/workers/polling'
6
- require_relative '../../core/workers/queue'
7
-
8
- require_relative '../buffer'
9
- require_relative '../pipeline'
10
- require_relative '../event'
11
-
12
- require_relative '../transport/http'
13
-
14
- module Datadog
15
- module Tracing
16
- module Workers
17
- # Writes traces to transport synchronously
18
- class TraceWriter < Core::Worker
19
- attr_reader \
20
- :logger,
21
- :transport,
22
- :agent_settings
23
-
24
- # DEV-3.0: change to keyword arguments
25
- #
26
- # rubocop:disable Lint/MissingSuper
27
- def initialize(options = {})
28
- @logger = options[:logger] || Datadog.logger
29
-
30
- transport_options = options.fetch(:transport_options, {})
31
- @agent_settings = options[:agent_settings]
32
-
33
- @transport = options.fetch(:transport) do
34
- Datadog::Tracing::Transport::HTTP.default(agent_settings: agent_settings, logger: logger, **transport_options)
35
- end
36
- end
37
- # rubocop:enable Lint/MissingSuper
38
-
39
- def perform(traces)
40
- write_traces(traces)
41
- end
42
-
43
- def write(trace)
44
- write_traces([trace])
45
- end
46
-
47
- def write_traces(traces)
48
- traces = process_traces(traces)
49
- flush_traces(traces)
50
- rescue => e
51
- logger.warn(
52
- "Error while writing traces: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
53
- )
54
- end
55
-
56
- def process_traces(traces)
57
- # Run traces through the processing pipeline
58
- Pipeline.process!(traces)
59
- end
60
-
61
- def flush_traces(traces)
62
- transport.send_traces(traces).tap do |response|
63
- flush_completed.publish(response)
64
- end
65
- end
66
-
67
- # TODO: Register `Datadog::Tracing::Diagnostics::EnvironmentLogger.collect_and_log!`
68
- # TODO: as a flush_completed subscriber when the `TraceWriter`
69
- # TODO: instantiation code is implemented.
70
- def flush_completed
71
- @flush_completed ||= FlushCompleted.new
72
- end
73
-
74
- # Flush completed event for worker
75
- class FlushCompleted < Event
76
- def initialize
77
- super(:flush_completed)
78
- end
79
- end
80
- end
81
-
82
- # Writes traces to transport asynchronously,
83
- # using a thread & buffer.
84
- class AsyncTraceWriter < TraceWriter
85
- include Core::Workers::Queue
86
- include Core::Workers::Polling
87
-
88
- DEFAULT_BUFFER_MAX_SIZE = 1000
89
- FORK_POLICY_ASYNC = :async
90
- FORK_POLICY_SYNC = :sync
91
-
92
- attr_writer \
93
- :async
94
-
95
- def initialize(options = {})
96
- # Workers::TraceWriter settings
97
- super
98
-
99
- # Workers::Polling settings
100
- self.enabled = options.fetch(:enabled, true)
101
-
102
- # Workers::Async::Thread settings
103
- @async = true
104
- self.fork_policy = options.fetch(:fork_policy, FORK_POLICY_ASYNC)
105
-
106
- # Workers::IntervalLoop settings
107
- self.loop_base_interval = options[:interval] if options.key?(:interval)
108
- self.loop_back_off_ratio = options[:back_off_ratio] if options.key?(:back_off_ratio)
109
- self.loop_back_off_max = options[:back_off_max] if options.key?(:back_off_max)
110
-
111
- # Workers::Queue settings
112
- @buffer_size = options.fetch(:buffer_size, DEFAULT_BUFFER_MAX_SIZE)
113
- self.buffer = TraceBuffer.new(@buffer_size)
114
-
115
- @shutdown_timeout = options.fetch(:shutdown_timeout, Core::Workers::Polling::DEFAULT_SHUTDOWN_TIMEOUT)
116
- end
117
-
118
- # NOTE: #perform is wrapped by other modules:
119
- # Polling --> Async --> IntervalLoop --> AsyncTraceWriter --> TraceWriter
120
- #
121
- # WARNING: This method breaks the Liskov Substitution Principle -- TraceWriter#perform is spec'd to return the
122
- # result from the writer, whereas this method always returns nil.
123
- def perform(traces)
124
- super.tap do |responses|
125
- loop_back_off! if responses.find(&:server_error?)
126
- end
127
-
128
- nil
129
- end
130
-
131
- def stop(force_stop = false, timeout = @shutdown_timeout)
132
- buffer.close if running?
133
- super
134
- end
135
-
136
- def enqueue(trace)
137
- buffer.push(trace)
138
- end
139
-
140
- def dequeue
141
- # Wrap results in Array because they are
142
- # splatted as args against TraceWriter#perform.
143
- [buffer.pop]
144
- end
145
-
146
- # Are there more traces to be processed next?
147
- def work_pending?
148
- # This is the same implementation as in Queue, but it was
149
- # overwritten by IntervalLoop on its way to this worker class.
150
- # See the comments in those two methods for more info.
151
- !buffer.empty?
152
- end
153
-
154
- def async?
155
- @async == true
156
- end
157
-
158
- def fork_policy=(policy)
159
- # Translate to Workers::Async::Thread policy
160
- thread_fork_policy = case policy
161
- when Core::Workers::Async::Thread::FORK_POLICY_STOP
162
- policy
163
- when FORK_POLICY_SYNC
164
- # Stop the async thread because the writer
165
- # will bypass and run synchronously.
166
- Core::Workers::Async::Thread::FORK_POLICY_STOP
167
- else
168
- Core::Workers::Async::Thread::FORK_POLICY_RESTART
169
- end
170
-
171
- # Update thread fork policy
172
- super(thread_fork_policy)
173
-
174
- # Update local policy
175
- @writer_fork_policy = policy
176
- end
177
-
178
- def after_fork
179
- # In multiprocess environments, forks will share the same buffer until its written to.
180
- # A.K.A. copy-on-write. We don't want forks to write traces generated from another process.
181
- # Instead, we reset it after the fork. (Make sure any enqueue operations happen after this.)
182
- self.buffer = TraceBuffer.new(@buffer_size)
183
-
184
- # Switch to synchronous mode if configured to do so.
185
- # In some cases synchronous writing is preferred because the fork will be short lived.
186
- @async = false if @writer_fork_policy == FORK_POLICY_SYNC
187
- end
188
-
189
- # WARNING: This method breaks the Liskov Substitution Principle -- TraceWriter#write is spec'd to return the
190
- # result from the writer, whereas this method returns something else when running in async mode.
191
- def write(trace)
192
- # Start worker thread. If the process has forked, it will trigger #after_fork to
193
- # reconfigure the worker accordingly.
194
- # NOTE: It's important we do this before queuing or it will drop the current trace,
195
- # because #after_fork resets the buffer.
196
- perform
197
-
198
- # Queue the trace if running asynchronously, otherwise short-circuit and write it directly.
199
- async? ? enqueue(trace) : write_traces([trace])
200
- end
201
- end
202
- end
203
- end
204
- end