datadog 2.22.0 → 2.26.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 (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +140 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +1 -58
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +93 -23
  5. data/ext/datadog_profiling_native_extension/collectors_stack.c +21 -5
  6. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  7. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
  8. data/ext/datadog_profiling_native_extension/extconf.rb +9 -4
  9. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  10. data/ext/datadog_profiling_native_extension/http_transport.c +1 -0
  11. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
  12. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
  13. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  14. data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
  15. data/ext/libdatadog_api/feature_flags.c +554 -0
  16. data/ext/libdatadog_api/feature_flags.h +5 -0
  17. data/ext/libdatadog_api/init.c +2 -0
  18. data/ext/libdatadog_api/library_config.c +12 -11
  19. data/ext/libdatadog_extconf_helpers.rb +1 -1
  20. data/lib/datadog/ai_guard/api_client.rb +82 -0
  21. data/lib/datadog/ai_guard/component.rb +42 -0
  22. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  23. data/lib/datadog/ai_guard/configuration/settings.rb +98 -0
  24. data/lib/datadog/ai_guard/configuration.rb +11 -0
  25. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  26. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +34 -0
  27. data/lib/datadog/ai_guard/evaluation/request.rb +81 -0
  28. data/lib/datadog/ai_guard/evaluation/result.rb +43 -0
  29. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  30. data/lib/datadog/ai_guard/evaluation.rb +72 -0
  31. data/lib/datadog/ai_guard/ext.rb +16 -0
  32. data/lib/datadog/ai_guard.rb +153 -0
  33. data/lib/datadog/appsec/api_security/route_extractor.rb +23 -6
  34. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  35. data/lib/datadog/appsec/assets/blocked.html +8 -0
  36. data/lib/datadog/appsec/assets/blocked.json +1 -1
  37. data/lib/datadog/appsec/assets/blocked.text +3 -1
  38. data/lib/datadog/appsec/assets.rb +1 -1
  39. data/lib/datadog/appsec/context.rb +2 -1
  40. data/lib/datadog/appsec/remote.rb +9 -12
  41. data/lib/datadog/appsec/response.rb +18 -4
  42. data/lib/datadog/appsec/security_engine/engine.rb +3 -3
  43. data/lib/datadog/appsec/security_engine/result.rb +2 -1
  44. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  45. data/lib/datadog/core/configuration/components.rb +37 -3
  46. data/lib/datadog/core/configuration/config_helper.rb +2 -2
  47. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  48. data/lib/datadog/core/configuration/option_definition.rb +4 -2
  49. data/lib/datadog/core/configuration/options.rb +8 -5
  50. data/lib/datadog/core/configuration/settings.rb +28 -3
  51. data/lib/datadog/core/configuration/supported_configurations.rb +338 -302
  52. data/lib/datadog/core/ddsketch.rb +0 -2
  53. data/lib/datadog/core/environment/cgroup.rb +52 -25
  54. data/lib/datadog/core/environment/container.rb +140 -46
  55. data/lib/datadog/core/environment/ext.rb +7 -0
  56. data/lib/datadog/core/environment/process.rb +87 -0
  57. data/lib/datadog/core/error.rb +6 -6
  58. data/lib/datadog/core/feature_flags.rb +61 -0
  59. data/lib/datadog/core/pin.rb +4 -0
  60. data/lib/datadog/core/rate_limiter.rb +9 -1
  61. data/lib/datadog/core/remote/client/capabilities.rb +7 -0
  62. data/lib/datadog/core/remote/client.rb +14 -6
  63. data/lib/datadog/core/remote/component.rb +6 -4
  64. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  65. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  66. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  67. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  68. data/lib/datadog/core/remote/transport/config.rb +4 -25
  69. data/lib/datadog/core/remote/transport/http/config.rb +10 -50
  70. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  71. data/lib/datadog/core/remote/transport/http.rb +15 -24
  72. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  73. data/lib/datadog/core/remote/worker.rb +25 -37
  74. data/lib/datadog/core/runtime/metrics.rb +11 -1
  75. data/lib/datadog/core/semaphore.rb +1 -4
  76. data/lib/datadog/core/tag_builder.rb +0 -4
  77. data/lib/datadog/core/tag_normalizer.rb +84 -0
  78. data/lib/datadog/core/telemetry/component.rb +59 -16
  79. data/lib/datadog/core/telemetry/event/app_started.rb +88 -50
  80. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  81. data/lib/datadog/core/telemetry/logger.rb +2 -2
  82. data/lib/datadog/core/telemetry/logging.rb +2 -8
  83. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  84. data/lib/datadog/core/telemetry/request.rb +17 -3
  85. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +3 -34
  86. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  87. data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -11
  88. data/lib/datadog/core/telemetry/worker.rb +88 -32
  89. data/lib/datadog/core/transport/ext.rb +2 -0
  90. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  91. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  92. data/lib/datadog/core/transport/http/builder.rb +9 -5
  93. data/lib/datadog/core/transport/http/client.rb +80 -0
  94. data/lib/datadog/core/transport/http.rb +22 -19
  95. data/lib/datadog/core/transport/response.rb +12 -1
  96. data/lib/datadog/core/transport/transport.rb +90 -0
  97. data/lib/datadog/core/utils/array.rb +29 -0
  98. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  99. data/lib/datadog/core/utils/network.rb +3 -1
  100. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  101. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  102. data/lib/datadog/core/utils/sequence.rb +2 -0
  103. data/lib/datadog/core/utils/time.rb +1 -1
  104. data/lib/datadog/core/utils.rb +2 -0
  105. data/lib/datadog/core/workers/async.rb +10 -1
  106. data/lib/datadog/core/workers/interval_loop.rb +44 -3
  107. data/lib/datadog/core/workers/polling.rb +2 -0
  108. data/lib/datadog/core/workers/queue.rb +100 -1
  109. data/lib/datadog/data_streams/configuration/settings.rb +49 -0
  110. data/lib/datadog/data_streams/configuration.rb +11 -0
  111. data/lib/datadog/data_streams/ext.rb +11 -0
  112. data/lib/datadog/data_streams/extensions.rb +16 -0
  113. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  114. data/lib/datadog/data_streams/processor.rb +509 -0
  115. data/lib/datadog/data_streams/transport/http/stats.rb +52 -0
  116. data/lib/datadog/data_streams/transport/http.rb +40 -0
  117. data/lib/datadog/data_streams/transport/stats.rb +46 -0
  118. data/lib/datadog/data_streams.rb +100 -0
  119. data/lib/datadog/di/boot.rb +4 -2
  120. data/lib/datadog/di/component.rb +0 -16
  121. data/lib/datadog/di/contrib/active_record.rb +30 -5
  122. data/lib/datadog/di/el/compiler.rb +8 -4
  123. data/lib/datadog/di/el/evaluator.rb +1 -1
  124. data/lib/datadog/di/error.rb +9 -0
  125. data/lib/datadog/di/instrumenter.rb +102 -37
  126. data/lib/datadog/di/logger.rb +2 -2
  127. data/lib/datadog/di/probe.rb +20 -0
  128. data/lib/datadog/di/probe_builder.rb +2 -1
  129. data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
  130. data/lib/datadog/di/probe_manager.rb +47 -33
  131. data/lib/datadog/di/probe_notification_builder.rb +77 -25
  132. data/lib/datadog/di/probe_notifier_worker.rb +5 -5
  133. data/lib/datadog/di/proc_responder.rb +32 -0
  134. data/lib/datadog/di/remote.rb +89 -84
  135. data/lib/datadog/di/transport/diagnostics.rb +8 -36
  136. data/lib/datadog/di/transport/http/diagnostics.rb +1 -33
  137. data/lib/datadog/di/transport/http/input.rb +1 -33
  138. data/lib/datadog/di/transport/http.rb +32 -17
  139. data/lib/datadog/di/transport/input.rb +67 -34
  140. data/lib/datadog/di.rb +61 -5
  141. data/lib/datadog/error_tracking/filters.rb +2 -2
  142. data/lib/datadog/kit/appsec/events/v2.rb +2 -3
  143. data/lib/datadog/open_feature/component.rb +60 -0
  144. data/lib/datadog/open_feature/configuration.rb +27 -0
  145. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  146. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  147. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  148. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  149. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  150. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  151. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  152. data/lib/datadog/open_feature/ext.rb +14 -0
  153. data/lib/datadog/open_feature/native_evaluator.rb +38 -0
  154. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  155. data/lib/datadog/open_feature/provider.rb +141 -0
  156. data/lib/datadog/open_feature/remote.rb +67 -0
  157. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  158. data/lib/datadog/open_feature/transport.rb +70 -0
  159. data/lib/datadog/open_feature.rb +19 -0
  160. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  161. data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
  162. data/lib/datadog/opentelemetry/metrics.rb +117 -0
  163. data/lib/datadog/opentelemetry/sdk/configurator.rb +25 -1
  164. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +35 -0
  165. data/lib/datadog/opentelemetry.rb +3 -0
  166. data/lib/datadog/profiling/collectors/code_provenance.rb +41 -7
  167. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -2
  168. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  169. data/lib/datadog/profiling/collectors/info.rb +5 -4
  170. data/lib/datadog/profiling/component.rb +12 -11
  171. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
  172. data/lib/datadog/profiling/http_transport.rb +4 -1
  173. data/lib/datadog/profiling/profiler.rb +4 -0
  174. data/lib/datadog/profiling/tag_builder.rb +36 -3
  175. data/lib/datadog/profiling.rb +1 -2
  176. data/lib/datadog/single_step_instrument.rb +1 -1
  177. data/lib/datadog/tracing/configuration/ext.rb +9 -0
  178. data/lib/datadog/tracing/configuration/settings.rb +74 -0
  179. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
  180. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  181. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  182. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  183. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
  184. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
  185. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
  186. data/lib/datadog/tracing/contrib/extensions.rb +10 -2
  187. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
  188. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  189. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +22 -17
  190. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
  191. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
  192. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
  193. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  194. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  195. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  196. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  197. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  198. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  199. data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
  200. data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
  201. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  202. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  203. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
  204. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
  205. data/lib/datadog/tracing/contrib/status_range_matcher.rb +9 -1
  206. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
  207. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
  208. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
  209. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
  210. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  211. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  212. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  213. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  214. data/lib/datadog/tracing/contrib/waterdrop.rb +41 -0
  215. data/lib/datadog/tracing/contrib.rb +1 -0
  216. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  217. data/lib/datadog/tracing/distributed/baggage.rb +3 -2
  218. data/lib/datadog/tracing/metadata/ext.rb +1 -1
  219. data/lib/datadog/tracing/remote.rb +1 -9
  220. data/lib/datadog/tracing/sampling/priority_sampler.rb +3 -1
  221. data/lib/datadog/tracing/span.rb +1 -1
  222. data/lib/datadog/tracing/span_event.rb +2 -2
  223. data/lib/datadog/tracing/span_operation.rb +20 -9
  224. data/lib/datadog/tracing/trace_operation.rb +44 -6
  225. data/lib/datadog/tracing/tracer.rb +42 -16
  226. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  227. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  228. data/lib/datadog/tracing/transport/http.rb +15 -9
  229. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  230. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  231. data/lib/datadog/tracing/transport/traces.rb +9 -71
  232. data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
  233. data/lib/datadog/tracing/writer.rb +1 -0
  234. data/lib/datadog/version.rb +2 -2
  235. data/lib/datadog.rb +3 -0
  236. metadata +93 -23
  237. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  238. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  239. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  240. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  241. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  242. data/lib/datadog/di/transport/http/api.rb +0 -42
  243. data/lib/datadog/di/transport/http/client.rb +0 -47
  244. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  245. data/lib/datadog/tracing/transport/http/api.rb +0 -44
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Contrib
8
+ module WaterDrop
9
+ # Producer integration for WaterDrop
10
+ module Producer
11
+ %i[
12
+ produce_many_sync
13
+ produce_many_async
14
+ produce_sync
15
+ produce_async
16
+ ].each do |method|
17
+ define_method(method) do |messages|
18
+ Datadog::Tracing.trace(Ext::SPAN_PRODUCER, resource: "waterdrop.#{__method__}") do
19
+ extract_span_tags(messages)
20
+ super(messages)
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def extract_span_tags(messages)
28
+ messages = [messages] if messages.is_a?(Hash)
29
+ span = Datadog::Tracing.active_span
30
+ return unless span
31
+
32
+ topics = []
33
+ partitions = []
34
+ messages.each do |message|
35
+ topics << message[:topic]
36
+ partitions << message[:partition] if message.key?(:partition)
37
+ end
38
+
39
+ span.set_tag(Ext::TAG_PRODUCER, id)
40
+ span.set_tag(Contrib::Karafka::Ext::TAG_MESSAGE_COUNT, messages.size)
41
+ span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Contrib::Karafka::Ext::TAG_SYSTEM)
42
+
43
+ span.set_tag(Contrib::Ext::Messaging::TAG_DESTINATION, topics.uniq.sort.join(','))
44
+ span.set_tag(Contrib::Karafka::Ext::TAG_PARTITION, partitions.uniq.sort.join(',')) if partitions.any?
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'component'
4
+ require_relative 'waterdrop/integration'
5
+ require_relative 'waterdrop/distributed/propagation'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ # `WaterDrop` integration public API
11
+ module WaterDrop
12
+ def self.inject(digest, data)
13
+ raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
14
+
15
+ # Steep: https://github.com/soutaro/steep/issues/477
16
+ # @type ivar @propagation: WaterDrop::Distributed::Propagation
17
+ @propagation.inject!(digest, data)
18
+ end
19
+
20
+ def self.extract(data)
21
+ raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
22
+
23
+ # Steep: https://github.com/soutaro/steep/issues/477
24
+ # @type ivar @propagation: WaterDrop::Distributed::Propagation
25
+ @propagation.extract(data)
26
+ end
27
+
28
+ Contrib::Component.register('waterdrop') do |config|
29
+ tracing = config.tracing
30
+ tracing.propagation_style
31
+
32
+ @propagation = WaterDrop::Distributed::Propagation.new(
33
+ propagation_style_inject: tracing.propagation_style_inject,
34
+ propagation_style_extract: tracing.propagation_style_extract,
35
+ propagation_extract_first: tracing.propagation_extract_first
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -55,6 +55,7 @@ require_relative 'contrib/httpclient/integration'
55
55
  require_relative 'contrib/httprb/integration'
56
56
  require_relative 'contrib/integration'
57
57
  require_relative 'contrib/kafka/integration'
58
+ require_relative 'contrib/waterdrop'
58
59
  require_relative 'contrib/karafka'
59
60
  require_relative 'contrib/lograge/integration'
60
61
  require_relative 'contrib/mongodb/integration'
@@ -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
@@ -94,8 +94,8 @@ module Datadog
94
94
 
95
95
  # @public_api
96
96
  module HTTP
97
- ERROR_RANGE = (500...600).freeze
98
97
  TAG_BASE_URL = 'http.base_url'
98
+ TAG_ENDPOINT = 'http.endpoint'
99
99
  TAG_METHOD = 'http.method'
100
100
  TAG_STATUS_CODE = 'http.status_code'
101
101
  TAG_USER_AGENT = 'http.useragent'
@@ -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
@@ -129,7 +129,6 @@ module Datadog
129
129
  # @yield Optional block where new newly created {Datadog::Tracing::SpanOperation} captures the execution.
130
130
  # @yieldparam [Datadog::Tracing::SpanOperation] span_op the newly created and active [Datadog::Tracing::SpanOperation]
131
131
  # @yieldparam [Datadog::Tracing::TraceOperation] trace_op the active [Datadog::Tracing::TraceOperation]
132
- # rubocop:disable Metrics/MethodLength
133
132
  def trace(
134
133
  name,
135
134
  continue_from: nil,
@@ -241,10 +240,21 @@ module Datadog
241
240
  trace.to_correlation
242
241
  end
243
242
 
244
- # Setup a new trace to continue from where another
243
+ # Setup a new trace execution context to continue from where another
245
244
  # trace left off.
245
+ # This is useful to continue distributed or async traces.
246
246
  #
247
- # Used to continue distributed or async traces.
247
+ # The first span created in the restored context is a direct child of the
248
+ # active span from when the {Datadog::Tracing::TraceDigest} was created.
249
+ #
250
+ # When no block is given, the trace context is restored in the current thread.
251
+ # It remains active until the first span created in this restored context is finished.
252
+ # After that, if a new span is created, it start a new, unrelated trace.
253
+ #
254
+ # When a block is given, the trace context is restored inside the block execution.
255
+ # It remains active until the block ends, even when the first span created inside
256
+ # the block finishes. This means that multiple spans can be direct children of the
257
+ # active span from when the {Datadog::Tracing::TraceDigest} was created.
248
258
  #
249
259
  # @param [Datadog::Tracing::TraceDigest] digest continue from the {Datadog::Tracing::TraceDigest}.
250
260
  # @param [Thread] key Thread to retrieve trace from. Defaults to current thread. For internal use only.
@@ -260,13 +270,32 @@ module Datadog
260
270
  # Start a new trace from the digest
261
271
  context = call_context(key)
262
272
  original_trace = active_trace(key)
263
- trace = start_trace(continue_from: digest)
273
+ # When we want the trace to be bound to a block, we cannot let
274
+ # it auto finish when the local root span finishes. This would
275
+ # create mutiple traces inside the block. Instead, we'll
276
+ # expliclity finish the trace after the block finishes.
277
+ auto_finish = !block
278
+
279
+ trace = start_trace(continue_from: digest, auto_finish: auto_finish)
264
280
 
265
281
  # If block hasn't been given; we need to manually deactivate
266
282
  # this trace. Subscribe to the trace finished event to do this.
267
283
  subscribe_trace_deactivation!(context, trace, original_trace) unless block
268
284
 
269
- context.activate!(trace, &block)
285
+ if block
286
+ # When a block is given, the trace will be active until the block finishes.
287
+ context.activate!(trace) do
288
+ yield
289
+ ensure # We have to flush even when an error occurs
290
+ # On block completion, force the trace to finish and flush its finished spans.
291
+ # Unfinished spans are lost as the {TraceOperation} has ended.
292
+ trace.finish!
293
+ flush_trace(trace)
294
+ end
295
+ else
296
+ # Otherwise, the trace will be bound to the current thread after this point
297
+ context.activate!(trace)
298
+ end
270
299
  end
271
300
 
272
301
  # Sample a span, tagging the trace as appropriate.
@@ -329,7 +358,7 @@ module Datadog
329
358
  @provider.context(key)
330
359
  end
331
360
 
332
- def build_trace(digest = nil)
361
+ def build_trace(digest, auto_finish)
333
362
  # Resolve hostname if configured
334
363
  hostname = Core::Environment::Socket.hostname if Datadog.configuration.tracing.report_hostname
335
364
  hostname = (hostname && !hostname.empty?) ? hostname : nil
@@ -353,7 +382,8 @@ module Datadog
353
382
  trace_state_unknown_fields: digest.trace_state_unknown_fields,
354
383
  remote_parent: digest.span_remote,
355
384
  tracer: self,
356
- baggage: digest.baggage
385
+ baggage: digest.baggage,
386
+ auto_finish: auto_finish
357
387
  )
358
388
  else
359
389
  TraceOperation.new(
@@ -362,13 +392,12 @@ module Datadog
362
392
  profiling_enabled: profiling_enabled,
363
393
  apm_tracing_enabled: apm_tracing_enabled,
364
394
  remote_parent: false,
365
- tracer: self
395
+ tracer: self,
396
+ auto_finish: auto_finish
366
397
  )
367
398
  end
368
399
  end
369
- # rubocop:enable Metrics/MethodLength
370
400
 
371
- # rubocop:disable Metrics/MethodLength
372
401
  def bind_trace_events!(trace_op)
373
402
  events = trace_op.send(:events)
374
403
 
@@ -387,13 +416,12 @@ module Datadog
387
416
  flush_trace(event_trace_op)
388
417
  end
389
418
  end
390
- # rubocop:enable Metrics/MethodLength
391
419
 
392
420
  # Creates a new TraceOperation, with events bounds to this Tracer instance.
393
421
  # @return [TraceOperation]
394
- def start_trace(continue_from: nil)
422
+ def start_trace(continue_from: nil, auto_finish: true)
395
423
  # Build a new trace using digest if provided.
396
- trace = build_trace(continue_from)
424
+ trace = build_trace(continue_from, auto_finish)
397
425
 
398
426
  # Bind trace events: sample trace, set default service, flush spans.
399
427
  bind_trace_events!(trace)
@@ -402,7 +430,6 @@ module Datadog
402
430
  end
403
431
 
404
432
  # rubocop:disable Lint/UnderscorePrefixedVariableName
405
- # rubocop:disable Metrics/MethodLength
406
433
  def start_span(
407
434
  name,
408
435
  continue_from: nil,
@@ -454,9 +481,8 @@ module Datadog
454
481
  span
455
482
  end
456
483
  end
457
- # rubocop:enable Lint/UnderscorePrefixedVariableName
458
- # rubocop:enable Metrics/MethodLength
459
484
 
485
+ # rubocop:enable Lint/UnderscorePrefixedVariableName
460
486
  def resolve_tags(tags, service)
461
487
  merged_tags = if @tags.any? && tags
462
488
  # Combine default tags with provided tags,
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'statistics'
4
+ require_relative '../../../core/transport/http/client'
4
5
  require_relative '../../../core/transport/http/env'
5
6
  require_relative '../../../core/transport/http/response'
6
7
 
@@ -9,33 +10,24 @@ module Datadog
9
10
  module Transport
10
11
  module HTTP
11
12
  # Routes, encodes, and sends tracer data to the trace agent via HTTP.
12
- class Client
13
+ class Client < Core::Transport::HTTP::Client
13
14
  include Datadog::Tracing::Transport::HTTP::Statistics
14
15
 
15
- attr_reader :api, :logger
16
+ private
16
17
 
17
- def initialize(api, logger: Datadog.logger)
18
- @api = api
19
- @logger = logger
20
- end
21
-
22
- def send_request(request, &block)
23
- # Build request into env
24
- env = build_env(request)
25
-
26
- # Get responses from API
27
- response = yield(api, env)
18
+ def on_response(response)
19
+ super
28
20
 
29
21
  # Update statistics
30
22
  update_stats_from_response!(response)
23
+ end
31
24
 
32
- response
33
- rescue => e
34
- message =
35
- "Internal error during #{self.class.name} request. Cause: #{e.class.name} #{e.message} " \
36
- "Location: #{Array(e.backtrace).first}"
25
+ def on_exception(exception)
26
+ # Note: this method does NOT call super - it has replacement
27
+ # logic for how to log the exception.
28
+
29
+ message = build_exception_message(exception)
37
30
 
38
- # Log error
39
31
  if stats.consecutive_errors > 0
40
32
  logger.debug(message)
41
33
  else
@@ -44,13 +36,7 @@ module Datadog
44
36
  end
45
37
 
46
38
  # Update statistics
47
- update_stats_from_exception!(e)
48
-
49
- Datadog::Core::Transport::InternalErrorResponse.new(e)
50
- end
51
-
52
- def build_env(request)
53
- Datadog::Core::Transport::HTTP::Env.new(request)
39
+ update_stats_from_exception!(exception)
54
40
  end
55
41
  end
56
42
  end
@@ -2,12 +2,10 @@
2
2
 
3
3
  require 'json'
4
4
 
5
- require_relative '../traces'
6
- require_relative 'client'
7
5
  require_relative '../../../core/transport/http/response'
8
6
  require_relative '../../../core/transport/http/api/endpoint'
9
- require_relative '../../../core/transport/http/api/spec'
10
7
  require_relative '../../../core/transport/http/api/instance'
8
+ require_relative '../traces'
11
9
 
12
10
  module Datadog
13
11
  module Tracing
@@ -27,58 +25,15 @@ module Datadog
27
25
  end
28
26
  end
29
27
 
30
- # Extensions for HTTP client
31
- module Client
32
- def send_traces_payload(request)
33
- send_request(request) do |api, env|
34
- api.send_traces(env)
35
- end
36
- end
37
- end
38
-
39
28
  module API
40
- # HTTP API Spec
41
- class Spec < Core::Transport::HTTP::API::Spec
42
- attr_accessor :traces
43
-
44
- def send_traces(env, &block)
45
- raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('traces', self) if traces.nil?
46
-
47
- traces.call(env, &block)
48
- end
49
-
50
- def encoder
51
- traces.encoder
52
- end
53
- end
54
-
55
- # HTTP API Instance
56
- class Instance < Core::Transport::HTTP::API::Instance
57
- def send_traces(env)
58
- unless spec.is_a?(Traces::API::Spec)
59
- raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new(
60
- 'traces', self
61
- )
62
- end
63
-
64
- spec.send_traces(env) do |request_env|
65
- call(request_env)
66
- end
67
- end
68
- end
69
-
70
29
  # Endpoint for submitting trace data
71
30
  class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
72
31
  HEADER_CONTENT_TYPE = 'Content-Type'
73
32
  HEADER_TRACE_COUNT = 'X-Datadog-Trace-Count'
74
33
  SERVICE_RATE_KEY = 'rate_by_service'
75
34
 
76
- attr_reader \
77
- :encoder
78
-
79
35
  def initialize(path, encoder, options = {})
80
- super(:post, path)
81
- @encoder = encoder
36
+ super(:post, path, encoder: encoder)
82
37
  @service_rates = options.fetch(:service_rates, false)
83
38
  end
84
39
 
@@ -111,9 +66,6 @@ module Datadog
111
66
  end
112
67
  end
113
68
  end
114
-
115
- # Add traces behavior to transport components
116
- HTTP::Client.include(Traces::Client)
117
69
  end
118
70
  end
119
71
  end