datadog 2.23.0 → 2.25.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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -1
  3. data/ext/datadog_profiling_native_extension/collectors_stack.c +17 -5
  4. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  5. data/ext/datadog_profiling_native_extension/extconf.rb +4 -1
  6. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
  7. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
  8. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  9. data/lib/datadog/ai_guard/api_client.rb +82 -0
  10. data/lib/datadog/ai_guard/component.rb +42 -0
  11. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  12. data/lib/datadog/ai_guard/configuration/settings.rb +98 -0
  13. data/lib/datadog/ai_guard/configuration.rb +11 -0
  14. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  15. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +34 -0
  16. data/lib/datadog/ai_guard/evaluation/request.rb +81 -0
  17. data/lib/datadog/ai_guard/evaluation/result.rb +43 -0
  18. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  19. data/lib/datadog/ai_guard/evaluation.rb +72 -0
  20. data/lib/datadog/ai_guard/ext.rb +16 -0
  21. data/lib/datadog/ai_guard.rb +153 -0
  22. data/lib/datadog/appsec/context.rb +2 -1
  23. data/lib/datadog/appsec/remote.rb +5 -12
  24. data/lib/datadog/appsec/security_engine/engine.rb +3 -3
  25. data/lib/datadog/appsec/security_engine/result.rb +2 -1
  26. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  27. data/lib/datadog/core/configuration/components.rb +6 -0
  28. data/lib/datadog/core/configuration/config_helper.rb +1 -1
  29. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  30. data/lib/datadog/core/configuration/option_definition.rb +4 -2
  31. data/lib/datadog/core/configuration/options.rb +8 -5
  32. data/lib/datadog/core/configuration/settings.rb +14 -3
  33. data/lib/datadog/core/configuration/supported_configurations.rb +8 -1
  34. data/lib/datadog/core/environment/cgroup.rb +52 -25
  35. data/lib/datadog/core/environment/container.rb +140 -46
  36. data/lib/datadog/core/environment/ext.rb +1 -0
  37. data/lib/datadog/core/environment/process.rb +9 -1
  38. data/lib/datadog/core/error.rb +6 -6
  39. data/lib/datadog/core/pin.rb +4 -0
  40. data/lib/datadog/core/rate_limiter.rb +9 -1
  41. data/lib/datadog/core/remote/client.rb +14 -6
  42. data/lib/datadog/core/remote/component.rb +6 -4
  43. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  44. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  45. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  46. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  47. data/lib/datadog/core/remote/transport/config.rb +3 -16
  48. data/lib/datadog/core/remote/transport/http/config.rb +4 -44
  49. data/lib/datadog/core/remote/transport/http/negotiation.rb +0 -39
  50. data/lib/datadog/core/remote/transport/http.rb +13 -24
  51. data/lib/datadog/core/remote/transport/negotiation.rb +7 -16
  52. data/lib/datadog/core/semaphore.rb +1 -4
  53. data/lib/datadog/core/telemetry/component.rb +52 -13
  54. data/lib/datadog/core/telemetry/event/app_started.rb +36 -1
  55. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  56. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  57. data/lib/datadog/core/telemetry/request.rb +17 -3
  58. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -32
  59. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  60. data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -10
  61. data/lib/datadog/core/telemetry/worker.rb +88 -32
  62. data/lib/datadog/core/transport/ext.rb +2 -0
  63. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  64. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  65. data/lib/datadog/core/transport/http/builder.rb +9 -5
  66. data/lib/datadog/core/transport/http/client.rb +19 -8
  67. data/lib/datadog/core/transport/http.rb +22 -19
  68. data/lib/datadog/core/transport/response.rb +12 -1
  69. data/lib/datadog/core/transport/transport.rb +90 -0
  70. data/lib/datadog/core/utils/only_once_successful.rb +2 -0
  71. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  72. data/lib/datadog/core/utils/sequence.rb +2 -0
  73. data/lib/datadog/core/utils/time.rb +1 -1
  74. data/lib/datadog/core/workers/async.rb +10 -1
  75. data/lib/datadog/core/workers/interval_loop.rb +44 -3
  76. data/lib/datadog/core/workers/polling.rb +2 -0
  77. data/lib/datadog/core/workers/queue.rb +100 -1
  78. data/lib/datadog/data_streams/processor.rb +1 -1
  79. data/lib/datadog/data_streams/transport/http/stats.rb +1 -36
  80. data/lib/datadog/data_streams/transport/http.rb +5 -6
  81. data/lib/datadog/data_streams/transport/stats.rb +3 -17
  82. data/lib/datadog/di/boot.rb +4 -2
  83. data/lib/datadog/di/contrib/active_record.rb +30 -5
  84. data/lib/datadog/di/el/compiler.rb +8 -4
  85. data/lib/datadog/di/error.rb +5 -0
  86. data/lib/datadog/di/instrumenter.rb +26 -7
  87. data/lib/datadog/di/logger.rb +2 -2
  88. data/lib/datadog/di/probe_builder.rb +2 -1
  89. data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
  90. data/lib/datadog/di/probe_manager.rb +37 -31
  91. data/lib/datadog/di/probe_notification_builder.rb +15 -2
  92. data/lib/datadog/di/probe_notifier_worker.rb +5 -5
  93. data/lib/datadog/di/remote.rb +89 -84
  94. data/lib/datadog/di/transport/diagnostics.rb +7 -35
  95. data/lib/datadog/di/transport/http/diagnostics.rb +1 -31
  96. data/lib/datadog/di/transport/http/input.rb +1 -31
  97. data/lib/datadog/di/transport/http.rb +28 -17
  98. data/lib/datadog/di/transport/input.rb +7 -34
  99. data/lib/datadog/di.rb +61 -5
  100. data/lib/datadog/error_tracking/filters.rb +2 -2
  101. data/lib/datadog/kit/appsec/events/v2.rb +2 -3
  102. data/lib/datadog/open_feature/evaluation_engine.rb +2 -1
  103. data/lib/datadog/open_feature/remote.rb +3 -10
  104. data/lib/datadog/open_feature/transport.rb +9 -11
  105. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  106. data/lib/datadog/opentelemetry/configuration/settings.rb +2 -2
  107. data/lib/datadog/opentelemetry/metrics.rb +21 -14
  108. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +5 -8
  109. data/lib/datadog/profiling/collectors/code_provenance.rb +27 -2
  110. data/lib/datadog/profiling/collectors/info.rb +5 -4
  111. data/lib/datadog/profiling/component.rb +12 -11
  112. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
  113. data/lib/datadog/profiling/http_transport.rb +4 -1
  114. data/lib/datadog/tracing/contrib/extensions.rb +10 -2
  115. data/lib/datadog/tracing/contrib/karafka/patcher.rb +31 -32
  116. data/lib/datadog/tracing/contrib/status_range_matcher.rb +2 -1
  117. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
  118. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +6 -3
  119. data/lib/datadog/tracing/contrib/waterdrop.rb +4 -0
  120. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  121. data/lib/datadog/tracing/distributed/baggage.rb +3 -2
  122. data/lib/datadog/tracing/remote.rb +1 -9
  123. data/lib/datadog/tracing/sampling/priority_sampler.rb +3 -1
  124. data/lib/datadog/tracing/span.rb +1 -1
  125. data/lib/datadog/tracing/span_event.rb +2 -2
  126. data/lib/datadog/tracing/span_operation.rb +20 -9
  127. data/lib/datadog/tracing/trace_operation.rb +44 -6
  128. data/lib/datadog/tracing/tracer.rb +42 -16
  129. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  130. data/lib/datadog/tracing/transport/http.rb +15 -9
  131. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  132. data/lib/datadog/tracing/transport/traces.rb +6 -66
  133. data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
  134. data/lib/datadog/tracing/writer.rb +1 -0
  135. data/lib/datadog/version.rb +2 -2
  136. data/lib/datadog.rb +1 -0
  137. metadata +24 -17
  138. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  139. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  140. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  141. data/lib/datadog/data_streams/transport/http/api.rb +0 -33
  142. data/lib/datadog/data_streams/transport/http/client.rb +0 -21
  143. data/lib/datadog/di/transport/http/api.rb +0 -42
  144. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  145. data/lib/datadog/tracing/transport/http/api.rb +0 -44
@@ -4,9 +4,6 @@ module Datadog
4
4
  module Profiling
5
5
  # Responsible for wiring up the Profiler for execution
6
6
  module Component
7
- ALLOCATION_WITH_RACTORS_ONLY_ONCE = Datadog::Core::Utils::OnlyOnce.new
8
- private_constant :ALLOCATION_WITH_RACTORS_ONLY_ONCE
9
-
10
7
  # Passing in a `nil` tracer is supported and will disable the following profiling features:
11
8
  # * Profiling in the trace viewer, as well as scoping a profile down to a span
12
9
  # * Endpoint aggregation in the profiler UX, including normalization (resource per endpoint call)
@@ -145,7 +142,7 @@ module Datadog
145
142
  logger.debug(
146
143
  "Using Ractors may result in GC profiling unexpectedly " \
147
144
  "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
148
- "application stability or performance. This does not happen if Ractors are not used."
145
+ "application stability or performance. This issue is fixed on Ruby 4."
149
146
  )
150
147
  end
151
148
 
@@ -195,13 +192,11 @@ module Datadog
195
192
  # On all known versions of Ruby 3.x, due to https://bugs.ruby-lang.org/issues/19112, when a ractor gets
196
193
  # garbage collected, Ruby will disable all active tracepoints, which this feature internally relies on.
197
194
  elsif RUBY_VERSION.start_with?("3.")
198
- ALLOCATION_WITH_RACTORS_ONLY_ONCE.run do
199
- logger.info(
200
- "Using Ractors may result in allocation profiling " \
201
- "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
202
- "application stability or performance. This does not happen if Ractors are not used."
203
- )
204
- end
195
+ logger.debug(
196
+ "Using Ractors may result in allocation profiling " \
197
+ "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
198
+ "application stability or performance. This issue is fixed on Ruby 4."
199
+ )
205
200
  end
206
201
 
207
202
  logger.debug("Enabled allocation profiling")
@@ -220,6 +215,12 @@ module Datadog
220
215
  "Please upgrade to Ruby >= 3.1 in order to use this feature. Heap profiling has been disabled."
221
216
  )
222
217
  return false
218
+ elsif RUBY_VERSION.start_with?("4.")
219
+ logger.warn(
220
+ "Datadog Ruby heap profiler is currently incompatible with Ruby 4. " \
221
+ "Heap profiling has been disabled."
222
+ )
223
+ return false
223
224
  end
224
225
 
225
226
  unless allocation_profiling_enabled
@@ -30,6 +30,10 @@ module Datadog
30
30
  if RUBY_VERSION.start_with?("2.")
31
31
  # Monkey patches for Dir.singleton_class (Ruby 2 version). See DirMonkeyPatches above for more details.
32
32
  module DirClassMonkeyPatches
33
+ # Steep: Workaround that defines args and block only for Ruby 2.x.
34
+ # @type var args: ::Array[any]
35
+ # @type var block: ^(?) -> any | nil
36
+
33
37
  def [](*args, &block)
34
38
  Datadog::Profiling::Collectors::CpuAndWallTimeWorker._native_hold_signals
35
39
  super
@@ -148,6 +152,11 @@ module Datadog
148
152
  else
149
153
  # Monkey patches for Dir.singleton_class (Ruby 3 version). See DirMonkeyPatches above for more details.
150
154
  module DirClassMonkeyPatches
155
+ # Steep: Workaround that defines args, kwargs and block only for Ruby 3.x.
156
+ # @type var args: ::Array[any]
157
+ # @type var kwargs: ::Hash[::Symbol, any]
158
+ # @type var block: ^(?) -> any | nil
159
+
151
160
  def [](*args, **kwargs, &block)
152
161
  Datadog::Profiling::Collectors::CpuAndWallTimeWorker._native_hold_signals
153
162
  super
@@ -263,6 +272,10 @@ module Datadog
263
272
  if RUBY_VERSION.start_with?("2.")
264
273
  # Monkey patches for Dir (Ruby 2 version). See DirMonkeyPatches above for more details.
265
274
  module DirInstanceMonkeyPatches
275
+ # Steep: Workaround that defines args and block only for Ruby 2.x.
276
+ # @type var args: ::Array[any]
277
+ # @type var block: ^(?) -> any | nil
278
+
266
279
  # See note on methods that yield above.
267
280
  def each(*args, &block)
268
281
  if block
@@ -336,6 +349,11 @@ module Datadog
336
349
  else
337
350
  # Monkey patches for Dir (Ruby 3 version). See DirMonkeyPatches above for more details.
338
351
  module DirInstanceMonkeyPatches
352
+ # Steep: Workaround that defines args, kwargs and block only for Ruby 3.x.
353
+ # @type var args: ::Array[any]
354
+ # @type var kwargs: ::Hash[::Symbol, any]
355
+ # @type var block: ^(?) -> any | nil
356
+
339
357
  # See note on methods that yield above.
340
358
  def each(*args, **kwargs, &block)
341
359
  if block
@@ -13,7 +13,10 @@ module Datadog
13
13
  def initialize(agent_settings:, site:, api_key:, upload_timeout_seconds:)
14
14
  @upload_timeout_milliseconds = (upload_timeout_seconds * 1_000).to_i
15
15
 
16
- @exporter_configuration =
16
+ # Steep: multiple issues here
17
+ # first https://github.com/soutaro/steep/issues/363
18
+ # then https://github.com/soutaro/steep/issues/1603 (remove the .freeze to see it)
19
+ @exporter_configuration = # steep:ignore IncompatibleAssignment
17
20
  if agentless?(site, api_key)
18
21
  [:agentless, site, api_key].freeze
19
22
  else
@@ -220,12 +220,20 @@ module Datadog
220
220
  # `@instrumented_integrations` hash.
221
221
  # @!visibility private
222
222
  def instrumented_integrations
223
- INSTRUMENTED_INTEGRATIONS_LOCK.synchronize { (@instrumented_integrations&.dup || {}).freeze }
223
+ INSTRUMENTED_INTEGRATIONS_LOCK.synchronize do
224
+ (if defined?(@instrumented_integrations)
225
+ @instrumented_integrations&.dup
226
+ end || {}).freeze
227
+ end
224
228
  end
225
229
 
226
230
  # @!visibility private
227
231
  def reset!
228
- INSTRUMENTED_INTEGRATIONS_LOCK.synchronize { @instrumented_integrations&.clear }
232
+ INSTRUMENTED_INTEGRATIONS_LOCK.synchronize do
233
+ if defined?(@instrumented_integrations)
234
+ @instrumented_integrations&.clear
235
+ end
236
+ end
229
237
  super
230
238
  end
231
239
 
@@ -25,35 +25,34 @@ module Datadog
25
25
  # @see https://github.com/karafka/karafka/blob/b06d1f7c17818e1605f80c2bb573454a33376b40/README.md?plain=1#L29-L35
26
26
  def each(&block)
27
27
  @messages_array.each do |message|
28
- if configuration[:distributed_tracing]
28
+ trace_digest = if configuration[:distributed_tracing]
29
29
  headers = if message.metadata.respond_to?(:raw_headers)
30
30
  message.metadata.raw_headers
31
31
  else
32
32
  message.metadata.headers
33
33
  end
34
- trace_digest = Karafka.extract(headers)
35
- Datadog::Tracing.continue_trace!(trace_digest) if trace_digest
34
+ Karafka.extract(headers)
36
35
  end
37
36
 
38
- if Datadog::DataStreams.enabled?
39
- begin
40
- headers = if message.metadata.respond_to?(:raw_headers)
41
- message.metadata.raw_headers
42
- else
43
- message.metadata.headers
37
+ Tracing.trace(Ext::SPAN_MESSAGE_CONSUME, continue_from: trace_digest) do |span, trace|
38
+ if Datadog::DataStreams.enabled?
39
+ begin
40
+ headers = if message.metadata.respond_to?(:raw_headers)
41
+ message.metadata.raw_headers
42
+ else
43
+ message.metadata.headers
44
+ end
45
+
46
+ Datadog::DataStreams.set_consume_checkpoint(
47
+ type: 'kafka',
48
+ source: message.topic,
49
+ auto_instrumentation: true
50
+ ) { |key| headers[key] }
51
+ rescue => e
52
+ Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
44
53
  end
45
-
46
- Datadog::DataStreams.set_consume_checkpoint(
47
- type: 'kafka',
48
- source: message.topic,
49
- auto_instrumentation: true
50
- ) { |key| headers[key] }
51
- rescue => e
52
- Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
53
54
  end
54
- end
55
55
 
56
- Tracing.trace(Ext::SPAN_MESSAGE_CONSUME) do |span|
57
56
  span.set_tag(Ext::TAG_OFFSET, message.metadata.offset)
58
57
  span.set_tag(Contrib::Ext::Messaging::TAG_DESTINATION, message.topic)
59
58
  span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Ext::TAG_SYSTEM)
@@ -66,22 +65,12 @@ module Datadog
66
65
  end
67
66
  end
68
67
 
69
- module AppPatch
70
- ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Core::Utils::OnlyOnce.new }
71
-
72
- def initialized!
73
- ONLY_ONCE_PER_APP[self].run do
74
- # Activate tracing on components related to Karafka (e.g. WaterDrop)
75
- Contrib::Karafka::Framework.setup
76
- end
77
- super
78
- end
79
- end
80
-
81
68
  # Patcher enables patching of 'karafka' module.
82
69
  module Patcher
83
70
  include Contrib::Patcher
84
71
 
72
+ ACTIVATE_FRAMEWORK_ONLY_ONCE = Core::Utils::OnlyOnce.new
73
+
85
74
  module_function
86
75
 
87
76
  def target_version
@@ -91,10 +80,20 @@ module Datadog
91
80
  def patch
92
81
  require_relative 'monitor'
93
82
  require_relative 'framework'
83
+ require_relative '../waterdrop'
94
84
 
95
85
  ::Karafka::Instrumentation::Monitor.prepend(Monitor)
96
86
  ::Karafka::Messages::Messages.prepend(MessagesPatch)
97
- ::Karafka::App.singleton_class.prepend(AppPatch)
87
+
88
+ if Contrib::WaterDrop::Integration.compatible?
89
+ ::Karafka.monitor.subscribe('app.initialized') do |event|
90
+ ACTIVATE_FRAMEWORK_ONLY_ONCE.run do
91
+ Contrib::Karafka::Framework.setup
92
+ end
93
+
94
+ Contrib::WaterDrop::Patcher.add_middleware(::Karafka.producer)
95
+ end
96
+ end
98
97
  end
99
98
  end
100
99
  end
@@ -8,7 +8,8 @@ module Datadog
8
8
  attr_reader :ranges
9
9
 
10
10
  def initialize(ranges)
11
- @ranges = Array(ranges)
11
+ # Steep: https://github.com/ruby/rbs/issues/1874
12
+ @ranges = Array(ranges) # steep:ignore IncompatibleAssignment
12
13
  end
13
14
 
14
15
  def +(other)
@@ -10,7 +10,9 @@ module Datadog
10
10
  PLACEHOLDER = '?'
11
11
  EXCLUDE_KEYS = [].freeze
12
12
  SHOW_KEYS = [].freeze
13
- DEFAULT_OPTIONS = {
13
+
14
+ # Steep: https://github.com/soutaro/steep/issues/363
15
+ DEFAULT_OPTIONS = { # steep:ignore IncompatibleAssignment
14
16
  exclude: EXCLUDE_KEYS,
15
17
  show: SHOW_KEYS,
16
18
  placeholder: PLACEHOLDER
@@ -25,9 +25,7 @@ module Datadog
25
25
  ::WaterDrop::Producer.prepend(Producer)
26
26
  ::WaterDrop.instrumentation.subscribe('producer.configured') do |event|
27
27
  producer = event[:producer]
28
-
29
- included_middlewares = producer.middleware.instance_variable_get(:@steps)
30
- producer.middleware.append(Middleware) unless included_middlewares.include?(Middleware)
28
+ add_middleware(producer)
31
29
 
32
30
  if Datadog.configuration.data_streams.enabled
33
31
  producer.monitor.subscribe('message.acknowledged') do |ack_event|
@@ -39,6 +37,11 @@ module Datadog
39
37
  end
40
38
  end
41
39
  end
40
+
41
+ def add_middleware(producer)
42
+ included_middlewares = producer.middleware.instance_variable_get(:@steps)
43
+ producer.middleware.append(Middleware) unless included_middlewares.include?(Middleware)
44
+ end
42
45
  end
43
46
  end
44
47
  end
@@ -12,12 +12,16 @@ module Datadog
12
12
  def self.inject(digest, data)
13
13
  raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
14
14
 
15
+ # Steep: https://github.com/soutaro/steep/issues/477
16
+ # @type ivar @propagation: WaterDrop::Distributed::Propagation
15
17
  @propagation.inject!(digest, data)
16
18
  end
17
19
 
18
20
  def self.extract(data)
19
21
  raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
20
22
 
23
+ # Steep: https://github.com/soutaro/steep/issues/477
24
+ # @type ivar @propagation: WaterDrop::Distributed::Propagation
21
25
  @propagation.extract(data)
22
26
  end
23
27
 
@@ -62,7 +62,7 @@ module Datadog
62
62
  # return `nil` with IO transport
63
63
  return unless transport.respond_to?(:client)
64
64
 
65
- adapter = transport.client.api.adapter
65
+ adapter = transport.client.instance.adapter
66
66
  adapter.url
67
67
  end
68
68
 
@@ -175,8 +175,9 @@ module Datadog
175
175
 
176
176
  tags = {}
177
177
 
178
- baggage_tag_keys.each do |key, _| # rubocop:disable Style/HashEachMethods
179
- value = baggage[key]
178
+ baggage_tag_keys.each do |key, _|
179
+ # Steep: https://github.com/soutaro/steep/issues/2031
180
+ value = baggage[key] # steep:ignore ArgumentTypeMismatch
180
181
  next if value.nil? || value.empty?
181
182
 
182
183
  tags["baggage.#{key}"] = value
@@ -7,8 +7,6 @@ module Datadog
7
7
  module Tracing
8
8
  # Remote configuration declaration
9
9
  module Remote
10
- class ReadError < StandardError; end
11
-
12
10
  class << self
13
11
  PRODUCT = 'APM_TRACING'
14
12
 
@@ -71,13 +69,7 @@ module Datadog
71
69
  private
72
70
 
73
71
  def parse_content(content)
74
- data = content.data.read
75
-
76
- content.data.rewind
77
-
78
- raise ReadError, 'EOF reached' if data.nil?
79
-
80
- JSON.parse(data)
72
+ JSON.parse(content.data)
81
73
  end
82
74
  end
83
75
  end
@@ -60,7 +60,9 @@ module Datadog
60
60
  ensure
61
61
  if trace.sampling_priority && trace.sampling_priority > 0
62
62
  # Don't modify decision if priority was set upstream.
63
- if !distributed_sampling_priority && !trace.has_tag?(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER)
63
+ # Steep: https://github.com/soutaro/steep/issues/1971
64
+ if !distributed_sampling_priority && # steep:ignore FallbackAny
65
+ !trace.has_tag?(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER)
64
66
  # If no sampling priority being assigned at this point, a custom
65
67
  # sampler implementation is configured: this means the user has
66
68
  # full control over the sampling decision.
@@ -80,7 +80,7 @@ module Datadog
80
80
 
81
81
  @meta = meta || {}
82
82
  @metrics = metrics || {}
83
- @metastruct = metastruct || {}
83
+ @metastruct = metastruct || Metastruct.new
84
84
  @status = status || 0
85
85
 
86
86
  # start_time and end_time track wall clock. In Ruby, wall clock
@@ -69,8 +69,8 @@ module Datadog
69
69
 
70
70
  private
71
71
 
72
- MIN_INT64_SIGNED = -2**63
73
- MAX_INT64_SIGNED = 2 << 63 - 1
72
+ MIN_INT64_SIGNED = -2 << 62
73
+ MAX_INT64_SIGNED = (2 << 62) - 1
74
74
 
75
75
  # Checks the attributes hash to ensure it only contains serializable values.
76
76
  # Invalid values are removed from the hash.
@@ -164,7 +164,9 @@ module Datadog
164
164
  # block is application code that we don't want to hinder.
165
165
  # * We don't yield during a fatal error, as the application is likely trying to
166
166
  # end its execution (either due to a system error or graceful shutdown).
167
- return_value = yield(self) unless e && !e.is_a?(StandardError)
167
+ # @type var e: Exception?
168
+ # Steep: https://github.com/soutaro/steep/issues/919
169
+ return_value = yield(self) unless e && !e.is_a?(StandardError) # steep:ignore FallbackAny
168
170
  end
169
171
  # rubocop:disable Lint/RescueException
170
172
  # Here we really want to catch *any* exception, not only StandardError,
@@ -214,9 +216,6 @@ module Datadog
214
216
  end
215
217
 
216
218
  # Mark the span stopped at the current time
217
- #
218
- # steep:ignore:start
219
- # Steep issue fixed in https://github.com/soutaro/steep/pull/1467
220
219
  def stop(stop_time = nil, exception: nil)
221
220
  # A span should not be stopped twice. Note that this is not thread-safe,
222
221
  # stop is called from multiple threads, a given span might be stopped
@@ -239,7 +238,6 @@ module Datadog
239
238
 
240
239
  self
241
240
  end
242
- # steep:ignore:end
243
241
 
244
242
  # Return whether the duration is started or not
245
243
  def started?
@@ -287,8 +285,14 @@ module Datadog
287
285
  end
288
286
 
289
287
  def duration
288
+ # Steep: https://github.com/soutaro/steep/issues/477
289
+ # @type ivar @duration_end: Time
290
+ # @type ivar @duration_start: Time
290
291
  return @duration_end - @duration_start if @duration_start && @duration_end
291
292
 
293
+ # Steep: https://github.com/soutaro/steep/issues/477
294
+ # @type ivar @end_time: Time
295
+ # @type ivar @start_time: Time
292
296
  @end_time - @start_time if @start_time && @end_time
293
297
  end
294
298
 
@@ -316,7 +320,9 @@ module Datadog
316
320
  'exception.stacktrace' => exc.backtrace,
317
321
  }
318
322
 
319
- @span_events << SpanEvent.new('exception', attributes: event_attributes.merge!(attributes)) # steep:ignore
323
+ # Steep: Caused by wrong declaration, should be the same parameters as `merge`
324
+ # https://github.com/ruby/rbs/blob/3d0fb3a7fdde60af7120e875fe3bd7237b5b6a88/core/hash.rbs#L1468
325
+ @span_events << SpanEvent.new('exception', attributes: event_attributes.merge!(attributes)) # steep:ignore ArgumentTypeMismatch
320
326
  end
321
327
 
322
328
  # Return a string representation of the span.
@@ -387,7 +393,8 @@ module Datadog
387
393
  class Events
388
394
  include Tracing::Events
389
395
 
390
- DEFAULT_ON_ERROR = proc { |span_op, error| span_op&.set_error(error) }
396
+ # Steep: https://github.com/soutaro/steep/issues/335
397
+ DEFAULT_ON_ERROR = proc { |span_op, error| span_op&.set_error(error) } # steep:ignore IncompatibleAssignment
391
398
 
392
399
  attr_reader \
393
400
  :logger,
@@ -395,7 +402,7 @@ module Datadog
395
402
  :after_stop,
396
403
  :before_start
397
404
 
398
- def initialize(logger: Datadog.logger, on_error: nil)
405
+ def initialize(logger: Datadog.logger)
399
406
  @logger = logger
400
407
  @after_finish = AfterFinish.new
401
408
  @after_stop = AfterStop.new
@@ -464,7 +471,7 @@ module Datadog
464
471
  @handler.call(*args)
465
472
  rescue => e
466
473
  logger.debug do
467
- "Error in on_error handler '#{@default}': #{e.class}: #{e} at #{Array(e.backtrace).first}"
474
+ "Error in on_error handler '#{@handler}': #{e.class}: #{e} at #{Array(e.backtrace).first}"
468
475
  end
469
476
  end
470
477
 
@@ -548,6 +555,10 @@ module Datadog
548
555
  # Used for serialization
549
556
  # @return [Integer] in nanoseconds since Epoch
550
557
  def start_time_nano
558
+ return 0 if @start_time.nil?
559
+
560
+ # Steep: https://github.com/soutaro/steep/issues/477
561
+ # @type ivar @start_time: Time
551
562
  @start_time.to_i * 1000000000 + @start_time.nsec
552
563
  end
553
564
 
@@ -55,6 +55,12 @@ module Datadog
55
55
  :sampled,
56
56
  :service
57
57
 
58
+ # Creates a new TraceOperation.
59
+ #
60
+ # @param auto_finish [Boolean] when true, automatically finishes the trace when the local root span finishes.
61
+ # When false, the trace remains unfinished until {#finish!} is called.
62
+ # This is useful when this {TraceOperation} represents the continuation of a remote {TraceDigest},
63
+ # in which case local root spans in this {TraceOperation} are children of the {TraceDigest}'s last active span.
58
64
  def initialize(
59
65
  logger: Datadog.logger,
60
66
  agent_sample_rate: nil,
@@ -80,7 +86,8 @@ module Datadog
80
86
  trace_state_unknown_fields: nil,
81
87
  remote_parent: false,
82
88
  tracer: nil, # DEV-3.0: deprecated, remove in 3.0
83
- baggage: nil
89
+ baggage: nil,
90
+ auto_finish: true
84
91
  )
85
92
  @logger = logger
86
93
 
@@ -119,6 +126,7 @@ module Datadog
119
126
  @events = events || Events.new
120
127
  @finished = false
121
128
  @spans = []
129
+ @auto_finish = !!auto_finish
122
130
  end
123
131
 
124
132
  def full?
@@ -318,6 +326,29 @@ module Datadog
318
326
  build_trace(spans, !finished)
319
327
  end
320
328
 
329
+ # When automatic context management is disabled (@auto_finish is false),
330
+ # this method finishes the trace, marking it as completed.
331
+ #
332
+ # The trace will **not** automatically finish when its local root span
333
+ # when @auto_finish is false, thus calling this method is mandatory
334
+ # in such scenario.
335
+ #
336
+ # Unfinished spans are discarded.
337
+ #
338
+ # This method is idempotent and safe to call after the trace is finished.
339
+ # It is also a no-op when @auto_finish is true, to prevent misuse.
340
+ #
341
+ # @!visibility private
342
+ def finish!
343
+ return if @auto_finish || finished?
344
+
345
+ @finished = true
346
+ @active_span = nil
347
+ @active_span_count = 0
348
+
349
+ events.trace_finished.publish(self)
350
+ end
351
+
321
352
  # Returns a set of trace headers used for continuing traces.
322
353
  # Used for propagation across execution contexts.
323
354
  # Data should reflect the active state of the trace.
@@ -460,7 +491,7 @@ module Datadog
460
491
 
461
492
  @active_span = span_op
462
493
 
463
- set_root_span!(span_op) unless root_span
494
+ set_local_root_span!(span_op)
464
495
  end
465
496
 
466
497
  def deactivate_span!(span_op)
@@ -483,6 +514,12 @@ module Datadog
483
514
  logger.debug { "Error starting span on trace: #{e} Backtrace: #{e.backtrace.first(3)}" }
484
515
  end
485
516
 
517
+ # For traces with automatic context management (auto_finish),
518
+ # when the local root span finishes, the trace also finishes.
519
+ # The trace cannot receive new spans after finished.
520
+ #
521
+ # Without auto_finish, the trace can still receive spans
522
+ # until explicitly finished.
486
523
  def finish_span(span, span_op, parent)
487
524
  # Save finished span & root span
488
525
  @spans << span unless span.nil?
@@ -490,8 +527,9 @@ module Datadog
490
527
  # Deactivate the span, re-activate parent.
491
528
  deactivate_span!(span_op)
492
529
 
493
- # Set finished, to signal root span has completed.
494
- @finished = true if span_op == root_span
530
+ # Finish if the local root span is finished and automatic
531
+ # context management is enabled.
532
+ @finished = true if span_op == root_span && @auto_finish
495
533
 
496
534
  # Update active span count
497
535
  @active_span_count -= 1
@@ -505,8 +543,8 @@ module Datadog
505
543
  logger.debug { "Error finishing span on trace: #{e} Backtrace: #{e.backtrace.first(3)}" }
506
544
  end
507
545
 
508
- # Track the root span
509
- def set_root_span!(span)
546
+ # Track the root {SpanOperation} object from the current execution context.
547
+ def set_local_root_span!(span)
510
548
  return if span.nil? || root_span
511
549
 
512
550
  @root_span = span