datadog 2.22.0 → 2.24.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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +100 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +1 -58
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +21 -5
  5. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  6. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
  7. data/ext/datadog_profiling_native_extension/extconf.rb +9 -4
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  9. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
  11. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  12. data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
  13. data/ext/libdatadog_api/feature_flags.c +554 -0
  14. data/ext/libdatadog_api/feature_flags.h +5 -0
  15. data/ext/libdatadog_api/init.c +2 -0
  16. data/ext/libdatadog_api/library_config.c +12 -11
  17. data/ext/libdatadog_extconf_helpers.rb +1 -1
  18. data/lib/datadog/appsec/api_security/route_extractor.rb +23 -6
  19. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  20. data/lib/datadog/appsec/assets/blocked.html +8 -0
  21. data/lib/datadog/appsec/assets/blocked.json +1 -1
  22. data/lib/datadog/appsec/assets/blocked.text +3 -1
  23. data/lib/datadog/appsec/assets.rb +1 -1
  24. data/lib/datadog/appsec/context.rb +2 -1
  25. data/lib/datadog/appsec/remote.rb +5 -9
  26. data/lib/datadog/appsec/response.rb +18 -4
  27. data/lib/datadog/appsec/security_engine/result.rb +2 -1
  28. data/lib/datadog/core/configuration/components.rb +30 -3
  29. data/lib/datadog/core/configuration/config_helper.rb +2 -2
  30. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  31. data/lib/datadog/core/configuration/option_definition.rb +4 -2
  32. data/lib/datadog/core/configuration/options.rb +8 -5
  33. data/lib/datadog/core/configuration/settings.rb +28 -3
  34. data/lib/datadog/core/configuration/supported_configurations.rb +332 -302
  35. data/lib/datadog/core/ddsketch.rb +0 -2
  36. data/lib/datadog/core/environment/cgroup.rb +52 -25
  37. data/lib/datadog/core/environment/container.rb +140 -46
  38. data/lib/datadog/core/environment/ext.rb +7 -0
  39. data/lib/datadog/core/environment/process.rb +87 -0
  40. data/lib/datadog/core/feature_flags.rb +61 -0
  41. data/lib/datadog/core/rate_limiter.rb +9 -1
  42. data/lib/datadog/core/remote/client/capabilities.rb +7 -0
  43. data/lib/datadog/core/remote/client.rb +14 -6
  44. data/lib/datadog/core/remote/component.rb +6 -4
  45. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  46. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  47. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  48. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  49. data/lib/datadog/core/remote/transport/config.rb +4 -25
  50. data/lib/datadog/core/remote/transport/http/config.rb +10 -50
  51. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  52. data/lib/datadog/core/remote/transport/http.rb +15 -24
  53. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  54. data/lib/datadog/core/remote/worker.rb +25 -37
  55. data/lib/datadog/core/tag_builder.rb +0 -4
  56. data/lib/datadog/core/tag_normalizer.rb +84 -0
  57. data/lib/datadog/core/telemetry/component.rb +59 -16
  58. data/lib/datadog/core/telemetry/event/app_started.rb +86 -49
  59. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  60. data/lib/datadog/core/telemetry/logger.rb +2 -2
  61. data/lib/datadog/core/telemetry/logging.rb +2 -8
  62. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  63. data/lib/datadog/core/telemetry/request.rb +17 -3
  64. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +3 -34
  65. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  66. data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -11
  67. data/lib/datadog/core/telemetry/worker.rb +88 -32
  68. data/lib/datadog/core/transport/ext.rb +2 -0
  69. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  70. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  71. data/lib/datadog/core/transport/http/builder.rb +9 -5
  72. data/lib/datadog/core/transport/http/client.rb +80 -0
  73. data/lib/datadog/core/transport/http.rb +22 -19
  74. data/lib/datadog/core/transport/response.rb +9 -0
  75. data/lib/datadog/core/transport/transport.rb +90 -0
  76. data/lib/datadog/core/utils/array.rb +29 -0
  77. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  78. data/lib/datadog/core/utils/network.rb +3 -1
  79. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  80. data/lib/datadog/core/utils/time.rb +1 -1
  81. data/lib/datadog/core/utils.rb +2 -0
  82. data/lib/datadog/core/workers/async.rb +10 -1
  83. data/lib/datadog/core/workers/interval_loop.rb +44 -3
  84. data/lib/datadog/core/workers/polling.rb +2 -0
  85. data/lib/datadog/core/workers/queue.rb +100 -1
  86. data/lib/datadog/data_streams/configuration/settings.rb +49 -0
  87. data/lib/datadog/data_streams/configuration.rb +11 -0
  88. data/lib/datadog/data_streams/ext.rb +11 -0
  89. data/lib/datadog/data_streams/extensions.rb +16 -0
  90. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  91. data/lib/datadog/data_streams/processor.rb +509 -0
  92. data/lib/datadog/data_streams/transport/http/stats.rb +52 -0
  93. data/lib/datadog/data_streams/transport/http.rb +40 -0
  94. data/lib/datadog/data_streams/transport/stats.rb +46 -0
  95. data/lib/datadog/data_streams.rb +100 -0
  96. data/lib/datadog/di/component.rb +0 -16
  97. data/lib/datadog/di/contrib/active_record.rb +31 -5
  98. data/lib/datadog/di/el/compiler.rb +8 -4
  99. data/lib/datadog/di/el/evaluator.rb +1 -1
  100. data/lib/datadog/di/error.rb +9 -0
  101. data/lib/datadog/di/instrumenter.rb +93 -34
  102. data/lib/datadog/di/probe.rb +20 -0
  103. data/lib/datadog/di/probe_builder.rb +2 -1
  104. data/lib/datadog/di/probe_manager.rb +47 -33
  105. data/lib/datadog/di/probe_notification_builder.rb +77 -25
  106. data/lib/datadog/di/proc_responder.rb +32 -0
  107. data/lib/datadog/di/remote.rb +89 -84
  108. data/lib/datadog/di/transport/diagnostics.rb +8 -36
  109. data/lib/datadog/di/transport/http/diagnostics.rb +1 -33
  110. data/lib/datadog/di/transport/http/input.rb +1 -33
  111. data/lib/datadog/di/transport/http.rb +32 -17
  112. data/lib/datadog/di/transport/input.rb +67 -34
  113. data/lib/datadog/di.rb +61 -5
  114. data/lib/datadog/open_feature/component.rb +60 -0
  115. data/lib/datadog/open_feature/configuration.rb +27 -0
  116. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  117. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  118. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  119. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  120. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  121. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  122. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  123. data/lib/datadog/open_feature/ext.rb +14 -0
  124. data/lib/datadog/open_feature/native_evaluator.rb +38 -0
  125. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  126. data/lib/datadog/open_feature/provider.rb +141 -0
  127. data/lib/datadog/open_feature/remote.rb +67 -0
  128. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  129. data/lib/datadog/open_feature/transport.rb +70 -0
  130. data/lib/datadog/open_feature.rb +19 -0
  131. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  132. data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
  133. data/lib/datadog/opentelemetry/metrics.rb +117 -0
  134. data/lib/datadog/opentelemetry/sdk/configurator.rb +25 -1
  135. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +35 -0
  136. data/lib/datadog/opentelemetry.rb +3 -0
  137. data/lib/datadog/profiling/collectors/code_provenance.rb +41 -7
  138. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +1 -1
  139. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  140. data/lib/datadog/profiling/collectors/info.rb +2 -1
  141. data/lib/datadog/profiling/component.rb +12 -11
  142. data/lib/datadog/profiling/http_transport.rb +4 -1
  143. data/lib/datadog/profiling/profiler.rb +4 -0
  144. data/lib/datadog/profiling/tag_builder.rb +36 -3
  145. data/lib/datadog/profiling.rb +1 -2
  146. data/lib/datadog/single_step_instrument.rb +1 -1
  147. data/lib/datadog/tracing/configuration/ext.rb +9 -0
  148. data/lib/datadog/tracing/configuration/settings.rb +74 -0
  149. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
  150. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  151. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  152. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  153. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
  154. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
  155. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
  156. data/lib/datadog/tracing/contrib/extensions.rb +10 -2
  157. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
  158. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  159. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +22 -17
  160. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
  161. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
  162. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
  163. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  164. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  165. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  166. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  167. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  168. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  169. data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
  170. data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
  171. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  172. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  173. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
  174. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
  175. data/lib/datadog/tracing/contrib/status_range_matcher.rb +9 -1
  176. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
  177. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
  178. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
  179. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
  180. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  181. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  182. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  183. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  184. data/lib/datadog/tracing/contrib/waterdrop.rb +37 -0
  185. data/lib/datadog/tracing/contrib.rb +1 -0
  186. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  187. data/lib/datadog/tracing/metadata/ext.rb +1 -1
  188. data/lib/datadog/tracing/remote.rb +1 -9
  189. data/lib/datadog/tracing/span_event.rb +2 -2
  190. data/lib/datadog/tracing/span_operation.rb +9 -4
  191. data/lib/datadog/tracing/trace_operation.rb +44 -6
  192. data/lib/datadog/tracing/tracer.rb +42 -16
  193. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  194. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  195. data/lib/datadog/tracing/transport/http.rb +15 -9
  196. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  197. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  198. data/lib/datadog/tracing/transport/traces.rb +9 -71
  199. data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
  200. data/lib/datadog/tracing/writer.rb +1 -0
  201. data/lib/datadog/version.rb +2 -2
  202. data/lib/datadog.rb +2 -0
  203. metadata +78 -21
  204. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  205. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  206. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  207. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  208. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  209. data/lib/datadog/di/transport/http/api.rb +0 -42
  210. data/lib/datadog/di/transport/http/client.rb +0 -47
  211. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  212. data/lib/datadog/tracing/transport/http/api.rb +0 -44
@@ -13,6 +13,9 @@ module Datadog
13
13
  ENV_BAGGAGE_TAG_KEYS = 'DD_TRACE_BAGGAGE_TAG_KEYS'
14
14
  ENV_TRACE_ID_128_BIT_GENERATION_ENABLED = 'DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED'
15
15
  ENV_NATIVE_SPAN_EVENTS = 'DD_TRACE_NATIVE_SPAN_EVENTS'
16
+ ENV_RESOURCE_RENAMING_ENABLED = 'DD_TRACE_RESOURCE_RENAMING_ENABLED'
17
+ ENV_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT = 'DD_TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT'
18
+ ENV_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED = 'DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED'
16
19
 
17
20
  # @public_api
18
21
  module SpanAttributeSchema
@@ -104,6 +107,12 @@ module Datadog
104
107
  ENV_ENABLED = 'DD_TRACE_CLIENT_IP_ENABLED'
105
108
  ENV_HEADER_NAME = 'DD_TRACE_CLIENT_IP_HEADER'
106
109
  end
110
+
111
+ # @public_api
112
+ module HTTPErrorStatuses
113
+ ENV_SERVER_ERROR_STATUSES = 'DD_TRACE_HTTP_SERVER_ERROR_STATUSES'
114
+ ENV_CLIENT_ERROR_STATUSES = 'DD_TRACE_HTTP_CLIENT_ERROR_STATUSES'
115
+ end
107
116
  end
108
117
  end
109
118
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require_relative '../../tracing/configuration/ext'
4
4
  require_relative '../../core/environment/variable_helpers'
5
+ require_relative '../contrib/status_range_matcher'
6
+ require_relative '../contrib/status_range_env_parser'
5
7
  require_relative 'http'
6
8
 
7
9
  module Datadog
@@ -272,6 +274,38 @@ module Datadog
272
274
  o.type :bool
273
275
  end
274
276
 
277
+ settings :resource_renaming do
278
+ # Whether resource renaming is enabled. When enabled, http.endpoint tag
279
+ # containing a route will be reported in traces. If AppSec is enabled,
280
+ # this feature will be enabled by default.
281
+ #
282
+ # For web applications built with instrumented frameworks, http.endpoint tag
283
+ # will contain the route as it is defined in the application.
284
+ # For basic Rack applications, or applications that are mounted and are not instrumented,
285
+ # the route will be inferred from the request path.
286
+ #
287
+ # @default `DD_TRACE_RESOURCE_RENAMING_ENABLED` environment variable, otherwise `false`.
288
+ # @return [Boolean]
289
+ option :enabled do |o|
290
+ o.type :bool, nilable: false
291
+ o.env Configuration::Ext::ENV_RESOURCE_RENAMING_ENABLED
292
+ o.default false
293
+ end
294
+
295
+ # When set to true, http.endoint is always inferred from path,
296
+ # instead of using http.route value when it is set.
297
+ #
298
+ # This is useful for testing purposes.
299
+ #
300
+ # @default false
301
+ # @return [Boolean]
302
+ option :always_simplified_endpoint do |o|
303
+ o.type :bool, nilable: false
304
+ o.env Configuration::Ext::ENV_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT
305
+ o.default false
306
+ end
307
+ end
308
+
275
309
  # Forces the tracer to always send span events with the native span events format
276
310
  # regardless of the agent support. This is useful in agent-less setups.
277
311
  #
@@ -490,6 +524,46 @@ module Datadog
490
524
  o.env Tracing::Configuration::Ext::Distributed::ENV_X_DATADOG_TAGS_MAX_LENGTH
491
525
  o.default 512
492
526
  end
527
+
528
+ # HTTP error statuses configuration
529
+ # @public_api
530
+ settings :http_error_statuses do
531
+ # Defines the range of status codes to be considered errors on http.server span kinds.
532
+ # Once set, only the values within the specified range are considered errors.
533
+ #
534
+ # Format of env var: comma-separated list of values like 500,501,502 or ranges like 500-599 (e.g. `500,502,504-510`)
535
+ #
536
+ # @default `DD_TRACE_HTTP_SERVER_ERROR_STATUSES` environment variable, otherwise `500..599`.
537
+ # @return [Tracing::Contrib::StatusRangeMatcher]
538
+ option :server do |o|
539
+ o.env Tracing::Configuration::Ext::HTTPErrorStatuses::ENV_SERVER_ERROR_STATUSES
540
+ o.default 500..599
541
+ o.setter do |v|
542
+ Tracing::Contrib::StatusRangeMatcher.new(v) if v
543
+ end
544
+ o.env_parser do |values|
545
+ Tracing::Contrib::StatusRangeEnvParser.call(values)
546
+ end
547
+ end
548
+
549
+ # Defines the range of status codes to be considered errors on http.client span kinds.
550
+ # Once set, only the values within the specified range are considered errors.
551
+ #
552
+ # Format of env var: comma-separated list of values like 400,401,402 or ranges like 400-499 (e.g. `400,402,404-410`)
553
+ #
554
+ # @default `DD_TRACE_HTTP_CLIENT_ERROR_STATUSES` environment variable, otherwise `400..499`.
555
+ # @return [Tracing::Contrib::StatusRangeMatcher]
556
+ option :client do |o|
557
+ o.env Tracing::Configuration::Ext::HTTPErrorStatuses::ENV_CLIENT_ERROR_STATUSES
558
+ o.default 400..499
559
+ o.setter do |v|
560
+ Tracing::Contrib::StatusRangeMatcher.new(v) if v
561
+ end
562
+ o.env_parser do |values|
563
+ Tracing::Contrib::StatusRangeEnvParser.call(values)
564
+ end
565
+ end
566
+ end
493
567
  end
494
568
  end
495
569
  end
@@ -77,10 +77,10 @@ module Datadog
77
77
 
78
78
  exception = payload[:exception_object]
79
79
  if exception.nil?
80
- # [christian] in some cases :status is not defined,
81
- # rather than firing an error, simply acknowledge we don't know it.
82
- status = payload.fetch(:status, '?').to_s
83
- span.status = 1 if status.start_with?('5')
80
+ status = payload[:status]
81
+ if status && Datadog.configuration.tracing.http_error_statuses.server.include?(status)
82
+ span.status = Tracing::Metadata::Ext::Errors::STATUS
83
+ end
84
84
  elsif Utils.exception_is_error?(exception)
85
85
  span.set_error(exception)
86
86
  end
@@ -13,8 +13,7 @@ module Datadog
13
13
  # Gets the equivalent status code for the exception (not all are 5XX)
14
14
  # You can add custom errors via `config.action_dispatch.rescue_responses`
15
15
  status = ::ActionDispatch::ExceptionWrapper.status_code_for_exception(exception.class.name)
16
- # Only 5XX exceptions are actually errors (e.g. don't flag 404s)
17
- status.to_s.start_with?('5')
16
+ Datadog.configuration.tracing.http_error_statuses.server.include?(status)
18
17
  else
19
18
  true
20
19
  end
@@ -6,17 +6,31 @@ module Datadog
6
6
  module ActiveJob
7
7
  # Active Job log injection wrapped around job execution
8
8
  module LogInjection
9
- def self.included(base)
10
- base.class_eval do
11
- around_perform do |_, block|
12
- if Datadog.configuration.tracing.log_injection && logger.respond_to?(:tagged)
13
- logger.tagged(Tracing.log_correlation, &block)
14
- else
15
- block.call
9
+ # Active Job 4 / 5 don't execute `perform_now` at the right point, so we do best effort log correlation tagging
10
+ module AroundPerformPatch
11
+ def self.included(base)
12
+ base.class_eval do
13
+ around_perform do |_, block|
14
+ if Datadog.configuration.tracing.log_injection && logger.respond_to?(:tagged)
15
+ logger.tagged(Tracing.log_correlation, &block)
16
+ else
17
+ block.call
18
+ end
16
19
  end
17
20
  end
18
21
  end
19
22
  end
23
+
24
+ # Active Job 6+ executes `perform_now` at the right point, so we can provide better log correlation tagging
25
+ module PerformNowPatch
26
+ def perform_now
27
+ if Datadog.configuration.tracing.log_injection && logger.respond_to?(:tagged)
28
+ logger.tagged(Tracing.log_correlation) { super }
29
+ else
30
+ super
31
+ end
32
+ end
33
+ end
20
34
  end
21
35
  end
22
36
  end
@@ -26,7 +26,11 @@ module Datadog
26
26
 
27
27
  def inject_log_correlation
28
28
  ::ActiveSupport.on_load(:active_job) do
29
- include LogInjection
29
+ if ::ActiveJob.gem_version < Gem::Version.new('6.0.0')
30
+ include LogInjection::AroundPerformPatch
31
+ else
32
+ include LogInjection::PerformNowPatch
33
+ end
30
34
  end
31
35
  end
32
36
  end
@@ -36,8 +36,10 @@ module Datadog
36
36
  span.name = Ext::SPAN_COMMAND
37
37
  span.resource = context.safely(:resource)
38
38
 
39
- # Set error on the span if the Response Status Code is in error range
40
- if Tracing::Metadata::Ext::HTTP::ERROR_RANGE.cover?(context.safely(:status_code))
39
+ # DEV-3.0: This was previously checking against a 500..599 range.
40
+ # To not introduce breaking change, this was changed to use `http_error_statuses.server`,
41
+ # but `aws` is a client library, this check should use `http_error_statuses.client` instead.
42
+ if Datadog.configuration.tracing.http_error_statuses.server.include?(context.safely(:status_code))
41
43
  # At this point we do not have any additional diagnostics
42
44
  # besides the HTTP status code which is recorded in the span tags
43
45
  # later in this method.
@@ -57,7 +57,10 @@ module Datadog
57
57
  set_span_error_message("Request has failed: #{message}")
58
58
  else
59
59
  @datadog_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response_code)
60
- if Tracing::Metadata::Ext::HTTP::ERROR_RANGE.cover?(response_code)
60
+ # DEV-3.0: This was previously checking against a 500..599 range.
61
+ # To not introduce breaking change, this was changed to use `http_error_statuses.server`,
62
+ # but `ethon` is a client library, this check should use `http_error_statuses.client` instead.
63
+ if Datadog.configuration.tracing.http_error_statuses.server.include?(response_code)
61
64
  set_span_error_message("Request has failed with HTTP error: #{response_code}")
62
65
  end
63
66
  end
@@ -41,9 +41,17 @@ module Datadog
41
41
 
42
42
  option :error_status_codes do |o|
43
43
  o.env Ext::ENV_ERROR_STATUS_CODES
44
- o.default 400...600
45
- o.setter do |v|
46
- Tracing::Contrib::StatusRangeMatcher.new(v) if v
44
+ o.setter do |value|
45
+ if value.nil?
46
+ # Fallback to global config, which is defaulted to client (400..499) + server (500..599)
47
+ # DEV-3.0: `excon` is a client library, this should fall back to `http_error_statuses.client` only.
48
+ # We cannot change it without causing a breaking change.
49
+ client_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.client
50
+ server_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.server
51
+ client_global_error_statuses + server_global_error_statuses
52
+ else
53
+ Tracing::Contrib::StatusRangeMatcher.new(value)
54
+ end
47
55
  end
48
56
  o.env_parser do |v|
49
57
  Tracing::Contrib::StatusRangeEnvParser.call(v) if v
@@ -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
 
@@ -13,10 +13,6 @@ module Datadog
13
13
  # Custom settings for the Faraday integration
14
14
  # @public_api
15
15
  class Settings < Contrib::Configuration::Settings
16
- DEFAULT_ERROR_HANDLER = lambda do |env|
17
- Tracing::Metadata::Ext::HTTP::ERROR_RANGE.cover?(env[:status])
18
- end
19
-
20
16
  option :enabled do |o|
21
17
  o.type :bool
22
18
  o.env Ext::ENV_ENABLED
@@ -44,9 +40,17 @@ module Datadog
44
40
 
45
41
  option :error_status_codes do |o|
46
42
  o.env Ext::ENV_ERROR_STATUS_CODES
47
- o.default 400...600
48
- o.setter do |v|
49
- Tracing::Contrib::StatusRangeMatcher.new(v) if v
43
+ o.setter do |value|
44
+ if value.nil?
45
+ # Fallback to global config, which is defaulted to client (400..499) + server (500..599)
46
+ # DEV-3.0: `faraday` is a client library, this should fall back to `http_error_statuses.client` only.
47
+ # We cannot change it without causing a breaking change.
48
+ client_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.client
49
+ server_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.server
50
+ client_global_error_statuses + server_global_error_statuses
51
+ else
52
+ Tracing::Contrib::StatusRangeMatcher.new(value)
53
+ end
50
54
  end
51
55
  o.env_parser do |v|
52
56
  Tracing::Contrib::StatusRangeEnvParser.call(v) if v
@@ -39,9 +39,13 @@ module Datadog
39
39
 
40
40
  option :error_status_codes do |o|
41
41
  o.env Ext::ENV_ERROR_STATUS_CODES
42
- o.default 500...600
43
- o.setter do |v|
44
- Tracing::Contrib::StatusRangeMatcher.new(v) if v
42
+ o.setter do |value|
43
+ if value.nil?
44
+ # Fallback to global config, which is defaulted to server (500..599)
45
+ Datadog.configuration.tracing.http_error_statuses.server
46
+ else
47
+ Tracing::Contrib::StatusRangeMatcher.new(value)
48
+ end
45
49
  end
46
50
  o.env_parser do |v|
47
51
  Tracing::Contrib::StatusRangeEnvParser.call(v) if v
@@ -176,6 +176,26 @@ module Datadog
176
176
  "#{type.graphql_name}.resolve_type"
177
177
  end
178
178
 
179
+ # Serialize error's `locations` array as an array of Strings, given
180
+ # Span Events do not support hashes nested inside arrays.
181
+ #
182
+ # Here's an example in which `locations`:
183
+ # [
184
+ # {"line" => 3, "column" => 10},
185
+ # {"line" => 7, "column" => 8},
186
+ # ]
187
+ # is serialized as:
188
+ # ["3:10", "7:8"]
189
+ def self.serialize_error_locations(locations)
190
+ # locations are only provided by the `graphql` library when the error can
191
+ # be associated to a particular point in the query.
192
+ return [] if locations.nil?
193
+
194
+ locations.map do |location|
195
+ "#{location["line"]}:#{location["column"]}"
196
+ end
197
+ end
198
+
179
199
  private
180
200
 
181
201
  # Traces the given callable with the given trace key, resource, and kwargs.
@@ -268,28 +288,13 @@ module Datadog
268
288
  @type_key => parsed_error.type,
269
289
  @stacktrace_key => parsed_error.backtrace,
270
290
  @message_key => graphql_error['message'],
271
- @locations_key => serialize_error_locations(graphql_error['locations']),
291
+ @locations_key =>
292
+ Datadog::Tracing::Contrib::GraphQL::UnifiedTrace.serialize_error_locations(graphql_error['locations']),
272
293
  @path_key => graphql_error['path'],
273
294
  )
274
295
  )
275
296
  end
276
297
  end
277
-
278
- # Serialize error's `locations` array as an array of Strings, given
279
- # Span Events do not support hashes nested inside arrays.
280
- #
281
- # Here's an example in which `locations`:
282
- # [
283
- # {"line" => 3, "column" => 10},
284
- # {"line" => 7, "column" => 8},
285
- # ]
286
- # is serialized as:
287
- # ["3:10", "7:8"]
288
- def serialize_error_locations(locations)
289
- locations.map do |location|
290
- "#{location["line"]}:#{location["column"]}"
291
- end
292
- end
293
298
  end
294
299
  end
295
300
  end
@@ -46,9 +46,17 @@ module Datadog
46
46
 
47
47
  option :error_status_codes do |o|
48
48
  o.env Ext::ENV_ERROR_STATUS_CODES
49
- o.default 400...600
50
- o.setter do |v|
51
- Tracing::Contrib::StatusRangeMatcher.new(v) if v
49
+ o.setter do |value|
50
+ if value.nil?
51
+ # Fallback to global config, which is defaulted to client (400..499) + server (500..599)
52
+ # DEV-3.0: `http` is a client library, this should fall back to `http_error_statuses.client` only.
53
+ # We cannot change it without causing a breaking change.
54
+ client_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.client
55
+ server_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.server
56
+ client_global_error_statuses + server_global_error_statuses
57
+ else
58
+ Tracing::Contrib::StatusRangeMatcher.new(value)
59
+ end
52
60
  end
53
61
  o.env_parser do |v|
54
62
  Tracing::Contrib::StatusRangeEnvParser.call(v) if v
@@ -45,9 +45,17 @@ module Datadog
45
45
 
46
46
  option :error_status_codes do |o|
47
47
  o.env Ext::ENV_ERROR_STATUS_CODES
48
- o.default 400...600
49
- o.setter do |v|
50
- Tracing::Contrib::StatusRangeMatcher.new(v) if v
48
+ o.setter do |value|
49
+ if value.nil?
50
+ # Fallback to global config, which is defaulted to client (400..499) + server (500..599)
51
+ # DEV-3.0: `httpclient` is a client library, this should fall back to `http_error_statuses.client` only.
52
+ # We cannot change it without causing a breaking change.
53
+ client_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.client
54
+ server_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.server
55
+ client_global_error_statuses + server_global_error_statuses
56
+ else
57
+ Tracing::Contrib::StatusRangeMatcher.new(value)
58
+ end
51
59
  end
52
60
  o.env_parser do |v|
53
61
  Tracing::Contrib::StatusRangeEnvParser.call(v) if v
@@ -45,9 +45,17 @@ module Datadog
45
45
 
46
46
  option :error_status_codes do |o|
47
47
  o.env Ext::ENV_ERROR_STATUS_CODES
48
- o.default 400...600
49
- o.setter do |v|
50
- Tracing::Contrib::StatusRangeMatcher.new(v) if v
48
+ o.setter do |value|
49
+ if value.nil?
50
+ # Fallback to global config, which is defaulted to client (400..499) + server (500..599)
51
+ # DEV-3.0: `httprb` is a client library, this should fall back to `http_error_statuses.client` only.
52
+ # We cannot change it without causing a breaking change.
53
+ client_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.client
54
+ server_global_error_statuses = Datadog.configuration.tracing.http_error_statuses.server
55
+ client_global_error_statuses + server_global_error_statuses
56
+ else
57
+ Tracing::Contrib::StatusRangeMatcher.new(value)
58
+ end
51
59
  end
52
60
  o.env_parser do |v|
53
61
  Tracing::Contrib::StatusRangeEnvParser.call(v) if v
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Kafka
7
+ module Instrumentation
8
+ # Instrumentation for Kafka::Consumer
9
+ module Consumer
10
+ def self.prepended(base)
11
+ base.prepend(InstanceMethods)
12
+ end
13
+
14
+ # Instance methods for consumer instrumentation
15
+ module InstanceMethods
16
+ def each_message(**kwargs, &block)
17
+ return super unless Datadog::DataStreams.enabled?
18
+
19
+ wrapped_block = proc do |message|
20
+ Datadog.logger.debug { "Kafka each_message: DSM enabled for topic #{message.topic}" }
21
+
22
+ begin
23
+ headers = message.headers || {}
24
+ Datadog::DataStreams.set_consume_checkpoint(
25
+ type: 'kafka',
26
+ source: message.topic,
27
+ auto_instrumentation: true
28
+ ) { |key| headers[key] }
29
+ rescue => e
30
+ Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
31
+ end
32
+
33
+ yield(message) if block
34
+ end
35
+
36
+ super(**kwargs, &wrapped_block)
37
+ end
38
+
39
+ def each_batch(**kwargs, &block)
40
+ return super unless Datadog::DataStreams.enabled?
41
+
42
+ wrapped_block = proc do |batch|
43
+ Datadog.logger.debug { "Kafka each_batch: DSM enabled for topic #{batch.topic}" }
44
+
45
+ begin
46
+ Datadog::DataStreams.set_consume_checkpoint(
47
+ type: 'kafka',
48
+ source: batch.topic,
49
+ auto_instrumentation: true
50
+ )
51
+ rescue => e
52
+ Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
53
+ end
54
+
55
+ yield(batch) if block
56
+ end
57
+
58
+ super(**kwargs, &wrapped_block)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Kafka
7
+ module Instrumentation
8
+ # Instrumentation for Kafka::Producer
9
+ module Producer
10
+ def self.prepended(base)
11
+ base.prepend(InstanceMethods)
12
+ end
13
+
14
+ module InstanceMethods
15
+ def deliver_messages(**kwargs)
16
+ if Datadog::DataStreams.enabled?
17
+ begin
18
+ pending_messages = instance_variable_get(:@pending_message_queue)
19
+
20
+ if pending_messages && !pending_messages.empty?
21
+ pending_messages.each do |message|
22
+ message.headers ||= {}
23
+ Datadog::DataStreams.set_produce_checkpoint(
24
+ type: 'kafka',
25
+ destination: message.topic,
26
+ auto_instrumentation: true
27
+ ) do |key, value|
28
+ message.headers[key] = value
29
+ end
30
+ end
31
+ end
32
+ rescue => e
33
+ Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
34
+ end
35
+ end
36
+
37
+ super
38
+ end
39
+
40
+ def send_messages(messages, **kwargs)
41
+ if Datadog::DataStreams.enabled?
42
+ begin
43
+ messages.each do |message|
44
+ message[:headers] ||= {}
45
+ Datadog::DataStreams.set_produce_checkpoint(
46
+ type: 'kafka',
47
+ destination: message[:topic],
48
+ auto_instrumentation: true
49
+ ) do |key, value|
50
+ message[:headers][key] = value
51
+ end
52
+ end
53
+ rescue => e
54
+ Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
55
+ end
56
+ end
57
+
58
+ super
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -21,6 +21,20 @@ module Datadog
21
21
  def patch
22
22
  # Subscribe to Kafka events
23
23
  Events.subscribe!
24
+
25
+ # Apply monkey patches for additional instrumentation (e.g., DSM)
26
+ patch_producer if defined?(::Kafka::Producer)
27
+ patch_consumer if defined?(::Kafka::Consumer)
28
+ end
29
+
30
+ def patch_producer
31
+ require_relative 'instrumentation/producer'
32
+ ::Kafka::Producer.prepend(Instrumentation::Producer)
33
+ end
34
+
35
+ def patch_consumer
36
+ require_relative 'instrumentation/consumer'
37
+ ::Kafka::Consumer.prepend(Instrumentation::Consumer)
24
38
  end
25
39
  end
26
40
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Karafka
7
+ # Karafka framework code, used to essentially:
8
+ # - handle configuration entries which are specific to Datadog tracing
9
+ # - instrument parts of the framework when needed
10
+ module Framework
11
+ def self.setup
12
+ Datadog.configure do |datadog_config|
13
+ karafka_config = datadog_config.tracing[:karafka]
14
+ activate_waterdrop!(datadog_config, karafka_config)
15
+ end
16
+ end
17
+
18
+ # Apply relevant configuration from Karafka to WaterDrop
19
+ def self.activate_waterdrop!(datadog_config, karafka_config)
20
+ datadog_config.tracing.instrument(
21
+ :waterdrop,
22
+ service_name: karafka_config[:service_name],
23
+ distributed_tracing: karafka_config[:distributed_tracing],
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -47,6 +47,17 @@ module Datadog
47
47
  span.set_tag(Ext::TAG_CONSUMER, consumer)
48
48
  span.set_tag(Contrib::Ext::Messaging::TAG_DESTINATION, job.executor.topic.name)
49
49
  span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Ext::TAG_SYSTEM)
50
+
51
+ # DSM: Track consumer offset stats for batch processing
52
+ if Datadog.configuration.data_streams.enabled
53
+ job.messages.each do |message|
54
+ Datadog::DataStreams.track_kafka_consume(
55
+ job.executor.topic.name,
56
+ job.executor.partition,
57
+ message.metadata.offset
58
+ )
59
+ end
60
+ end
50
61
  end
51
62
 
52
63
  super