datadog 2.23.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -2
  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/appsec/context.rb +2 -1
  10. data/lib/datadog/appsec/remote.rb +1 -9
  11. data/lib/datadog/appsec/security_engine/result.rb +2 -1
  12. data/lib/datadog/core/configuration/config_helper.rb +1 -1
  13. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  14. data/lib/datadog/core/configuration/option_definition.rb +4 -2
  15. data/lib/datadog/core/configuration/options.rb +8 -5
  16. data/lib/datadog/core/configuration/settings.rb +14 -3
  17. data/lib/datadog/core/configuration/supported_configurations.rb +2 -1
  18. data/lib/datadog/core/environment/cgroup.rb +52 -25
  19. data/lib/datadog/core/environment/container.rb +140 -46
  20. data/lib/datadog/core/environment/ext.rb +1 -0
  21. data/lib/datadog/core/environment/process.rb +9 -1
  22. data/lib/datadog/core/rate_limiter.rb +9 -1
  23. data/lib/datadog/core/remote/client.rb +14 -6
  24. data/lib/datadog/core/remote/component.rb +6 -4
  25. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  26. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  27. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  28. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  29. data/lib/datadog/core/remote/transport/config.rb +3 -16
  30. data/lib/datadog/core/remote/transport/http/config.rb +4 -44
  31. data/lib/datadog/core/remote/transport/http/negotiation.rb +0 -39
  32. data/lib/datadog/core/remote/transport/http.rb +13 -24
  33. data/lib/datadog/core/remote/transport/negotiation.rb +7 -16
  34. data/lib/datadog/core/telemetry/component.rb +52 -13
  35. data/lib/datadog/core/telemetry/event/app_started.rb +34 -0
  36. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  37. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  38. data/lib/datadog/core/telemetry/request.rb +17 -3
  39. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -32
  40. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  41. data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -10
  42. data/lib/datadog/core/telemetry/worker.rb +88 -32
  43. data/lib/datadog/core/transport/ext.rb +2 -0
  44. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  45. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  46. data/lib/datadog/core/transport/http/builder.rb +9 -5
  47. data/lib/datadog/core/transport/http/client.rb +19 -8
  48. data/lib/datadog/core/transport/http.rb +22 -19
  49. data/lib/datadog/core/transport/response.rb +9 -0
  50. data/lib/datadog/core/transport/transport.rb +90 -0
  51. data/lib/datadog/core/utils/only_once_successful.rb +2 -0
  52. data/lib/datadog/core/utils/time.rb +1 -1
  53. data/lib/datadog/core/workers/async.rb +10 -1
  54. data/lib/datadog/core/workers/interval_loop.rb +44 -3
  55. data/lib/datadog/core/workers/polling.rb +2 -0
  56. data/lib/datadog/core/workers/queue.rb +100 -1
  57. data/lib/datadog/data_streams/processor.rb +1 -1
  58. data/lib/datadog/data_streams/transport/http/stats.rb +1 -36
  59. data/lib/datadog/data_streams/transport/http.rb +5 -6
  60. data/lib/datadog/data_streams/transport/stats.rb +3 -17
  61. data/lib/datadog/di/contrib/active_record.rb +31 -5
  62. data/lib/datadog/di/el/compiler.rb +8 -4
  63. data/lib/datadog/di/error.rb +5 -0
  64. data/lib/datadog/di/instrumenter.rb +17 -4
  65. data/lib/datadog/di/probe_builder.rb +2 -1
  66. data/lib/datadog/di/probe_manager.rb +37 -31
  67. data/lib/datadog/di/probe_notification_builder.rb +15 -2
  68. data/lib/datadog/di/remote.rb +89 -84
  69. data/lib/datadog/di/transport/diagnostics.rb +7 -35
  70. data/lib/datadog/di/transport/http/diagnostics.rb +1 -31
  71. data/lib/datadog/di/transport/http/input.rb +1 -31
  72. data/lib/datadog/di/transport/http.rb +28 -17
  73. data/lib/datadog/di/transport/input.rb +7 -34
  74. data/lib/datadog/di.rb +61 -5
  75. data/lib/datadog/open_feature/evaluation_engine.rb +2 -1
  76. data/lib/datadog/open_feature/remote.rb +3 -10
  77. data/lib/datadog/open_feature/transport.rb +9 -11
  78. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  79. data/lib/datadog/opentelemetry/configuration/settings.rb +2 -2
  80. data/lib/datadog/opentelemetry/metrics.rb +21 -14
  81. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +5 -8
  82. data/lib/datadog/profiling/collectors/code_provenance.rb +27 -2
  83. data/lib/datadog/profiling/collectors/info.rb +2 -1
  84. data/lib/datadog/profiling/component.rb +12 -11
  85. data/lib/datadog/profiling/http_transport.rb +4 -1
  86. data/lib/datadog/tracing/contrib/extensions.rb +10 -2
  87. data/lib/datadog/tracing/contrib/karafka/patcher.rb +31 -32
  88. data/lib/datadog/tracing/contrib/status_range_matcher.rb +2 -1
  89. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
  90. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +6 -3
  91. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  92. data/lib/datadog/tracing/remote.rb +1 -9
  93. data/lib/datadog/tracing/span_event.rb +2 -2
  94. data/lib/datadog/tracing/span_operation.rb +9 -4
  95. data/lib/datadog/tracing/trace_operation.rb +44 -6
  96. data/lib/datadog/tracing/tracer.rb +42 -16
  97. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  98. data/lib/datadog/tracing/transport/http.rb +15 -9
  99. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  100. data/lib/datadog/tracing/transport/traces.rb +6 -66
  101. data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
  102. data/lib/datadog/tracing/writer.rb +1 -0
  103. data/lib/datadog/version.rb +2 -2
  104. metadata +7 -13
  105. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  106. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  107. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  108. data/lib/datadog/data_streams/transport/http/api.rb +0 -33
  109. data/lib/datadog/data_streams/transport/http/client.rb +0 -21
  110. data/lib/datadog/di/transport/http/api.rb +0 -42
  111. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  112. data/lib/datadog/tracing/transport/http/api.rb +0 -44
@@ -6,8 +6,6 @@ module Datadog
6
6
  module OpenFeature
7
7
  # This module contains the remote configuration functionality for OpenFeature
8
8
  module Remote
9
- ReadError = Class.new(StandardError)
10
-
11
9
  class << self
12
10
  FFE_FLAG_CONFIGURATION_RULES = 1 << 46
13
11
  FFE_PRODUCTS = ['FFE_FLAGS'].freeze
@@ -42,8 +40,6 @@ module Datadog
42
40
  # @type var content: Core::Remote::Configuration::Content
43
41
  engine.reconfigure!(read_content(content))
44
42
  content.applied
45
- rescue ReadError => e
46
- content.errored("Error reading Remote Configuration content: #{e.message}")
47
43
  rescue EvaluationEngine::ReconfigurationError => e
48
44
  content.errored("Error applying OpenFeature configuration: #{e.message}")
49
45
  end
@@ -61,12 +57,9 @@ module Datadog
61
57
  private
62
58
 
63
59
  def read_content(content)
64
- data = content.data.read
65
- content.data.rewind
66
-
67
- raise ReadError, 'EOF reached' if data.nil?
68
-
69
- data
60
+ # Unlike all of the other remotes, this one does not JSON-parse
61
+ # the data.
62
+ content.data
70
63
  end
71
64
  end
72
65
  end
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../core/encoding'
3
4
  require_relative '../core/transport/http'
4
5
  require_relative '../core/transport/http/env'
6
+ require_relative '../core/transport/http/api/endpoint'
7
+ require_relative '../core/transport/http/api/instance'
5
8
  require_relative '../core/transport/parcel'
6
9
  require_relative '../core/transport/request'
7
10
 
@@ -17,15 +20,14 @@ module Datadog
17
20
  end
18
21
 
19
22
  class HTTP
20
- class Spec < Core::Transport::HTTP::API::Spec
23
+ class Spec
21
24
  def initialize
22
25
  @endpoint = Core::Transport::HTTP::API::Endpoint.new(
23
26
  :post, '/evp_proxy/v2/api/v2/exposures'
24
27
  )
25
-
26
- super
27
28
  end
28
29
 
30
+ # TODO rename to send_request?
29
31
  def call(env, &block)
30
32
  @endpoint.call(env) do |request_env|
31
33
  request_env.headers['Content-Type'] = Core::Encoding::JSONEncoder.content_type
@@ -37,15 +39,8 @@ module Datadog
37
39
  end
38
40
  end
39
41
 
40
- class Instance < Core::Transport::HTTP::API::Instance
41
- def send_exposures(env)
42
- @spec.call(env) { |request_env| call(request_env) }
43
- end
44
- end
45
-
46
42
  def self.build(agent_settings:, logger:)
47
43
  Core::Transport::HTTP.build(
48
- api_instance_class: HTTP::Instance,
49
44
  agent_settings: agent_settings,
50
45
  logger: logger
51
46
  ) { |t| t.api('exposures', HTTP::Spec.new) }.to_transport(self)
@@ -58,7 +53,10 @@ module Datadog
58
53
 
59
54
  def send_exposures(payload)
60
55
  request = Core::Transport::Request.new(EncodedParcel.new(payload))
61
- @api.send_exposures(Core::Transport::HTTP::Env.new(request))
56
+
57
+ @api.endpoint.call(Core::Transport::HTTP::Env.new(request)) do |env|
58
+ @api.call(env)
59
+ end
62
60
  rescue => e
63
61
  message = "Internal error during request. Cause: #{e.class.name} #{e.message} " \
64
62
  "Location: #{Array(e.backtrace).first}"
@@ -26,7 +26,7 @@ module Datadog
26
26
  # to ::OpenTelemetry::Context.current
27
27
  # @return [Context]
28
28
  def clear(context: ::OpenTelemetry::Context.current)
29
- context.ensure_trace.baggage.clear
29
+ context.ensure_trace&.baggage&.clear
30
30
  context
31
31
  end
32
32
 
@@ -140,13 +140,13 @@ module Datadog
140
140
  option :timeout_millis do |o|
141
141
  o.type :int, nilable: true
142
142
  o.env 'OTEL_EXPORTER_OTLP_METRICS_TIMEOUT'
143
- o.default nil
143
+ o.default 10000
144
144
  end
145
145
 
146
146
  option :protocol do |o|
147
147
  o.type :string, nilable: true
148
148
  o.env 'OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'
149
- o.default nil
149
+ o.default "http/protobuf"
150
150
  o.setter(&Settings.normalize_protocol('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'))
151
151
  end
152
152
  end
@@ -70,12 +70,7 @@ module Datadog
70
70
  @logger.warn("Failed to configure OTLP metrics exporter: #{e.class}: #{e}")
71
71
  end
72
72
 
73
- def resolve_metrics_endpoint
74
- metrics_config = @settings.opentelemetry.metrics
75
- exporter_config = @settings.opentelemetry.exporter
76
-
77
- return metrics_config.endpoint if metrics_config.endpoint
78
- return exporter_config.endpoint if exporter_config.endpoint
73
+ def default_metrics_endpoint
79
74
  "#{@agent_ssl ? "https" : "http"}://#{@agent_host}:4318/v1/metrics"
80
75
  end
81
76
 
@@ -84,16 +79,19 @@ module Datadog
84
79
  require_relative 'sdk/metrics_exporter'
85
80
 
86
81
  metrics_config = @settings.opentelemetry.metrics
87
- exporter_config = @settings.opentelemetry.exporter
88
- timeout = metrics_config.timeout_millis || exporter_config.timeout_millis
89
- headers = metrics_config.headers || exporter_config.headers || {}
90
-
91
- protocol = metrics_config.protocol || exporter_config.protocol
82
+ endpoint = get_metrics_config_with_fallback(
83
+ option_name: :endpoint,
84
+ computed_default: default_metrics_endpoint
85
+ )
86
+ timeout = get_metrics_config_with_fallback(option_name: :timeout_millis)
87
+ headers = get_metrics_config_with_fallback(option_name: :headers)
88
+ # OpenTelemetry SDK only supports http/protobuf protocol.
89
+ # TODO: Add support for http/json and grpc.
90
+ # protocol = get_metrics_config_with_fallback(option_name: :protocol)
92
91
  exporter = Datadog::OpenTelemetry::SDK::MetricsExporter.new(
93
- endpoint: resolve_metrics_endpoint,
92
+ endpoint: endpoint,
94
93
  timeout: timeout / 1000.0,
95
- headers: headers,
96
- protocol: protocol
94
+ headers: headers
97
95
  )
98
96
 
99
97
  reader = ::OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(
@@ -105,6 +103,15 @@ module Datadog
105
103
  rescue LoadError => e
106
104
  @logger.warn("Could not load OTLP metrics exporter: #{e.class}: #{e}")
107
105
  end
106
+
107
+ # Returns metrics config value if explicitly set, otherwise falls back to exporter config or computed default value.
108
+ def get_metrics_config_with_fallback(option_name:, computed_default: nil)
109
+ if @settings.opentelemetry.metrics.using_default?(option_name)
110
+ @settings.opentelemetry.exporter.public_send(option_name) || computed_default
111
+ else
112
+ @settings.opentelemetry.metrics.public_send(option_name)
113
+ end
114
+ end
108
115
  end
109
116
  end
110
117
  end
@@ -9,21 +9,18 @@ module Datadog
9
9
  METRIC_EXPORT_ATTEMPTS = 'otel.metrics_export_attempts'
10
10
  METRIC_EXPORT_SUCCESSES = 'otel.metrics_export_successes'
11
11
  METRIC_EXPORT_FAILURES = 'otel.metrics_export_failures'
12
-
13
- def initialize(endpoint:, timeout:, headers:, protocol:)
14
- super(endpoint: endpoint, timeout: timeout, headers: headers)
15
- @telemetry_tags = {'protocol' => protocol, 'encoding' => 'protobuf'}
16
- end
12
+ TELEMETRY_NAMESPACE = 'tracers'
13
+ TELEMETRY_TAGS = {'protocol' => "http", 'encoding' => 'protobuf'}
17
14
 
18
15
  def export(metrics, timeout: nil)
19
- telemetry&.inc('tracers', METRIC_EXPORT_ATTEMPTS, 1, tags: @telemetry_tags)
16
+ telemetry&.inc(TELEMETRY_NAMESPACE, METRIC_EXPORT_ATTEMPTS, 1, tags: TELEMETRY_TAGS)
20
17
  result = super
21
18
  metric_name = (result == 0) ? METRIC_EXPORT_SUCCESSES : METRIC_EXPORT_FAILURES
22
- telemetry&.inc('tracers', metric_name, 1, tags: @telemetry_tags)
19
+ telemetry&.inc(TELEMETRY_NAMESPACE, metric_name, 1, tags: TELEMETRY_TAGS)
23
20
  result
24
21
  rescue => e
25
22
  Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e}")
26
- telemetry&.inc('tracers', METRIC_EXPORT_FAILURES, 1, tags: @telemetry_tags)
23
+ telemetry&.inc(TELEMETRY_NAMESPACE, METRIC_EXPORT_FAILURES, 1, tags: TELEMETRY_TAGS)
27
24
  raise
28
25
  end
29
26
 
@@ -22,7 +22,7 @@ module Datadog
22
22
  @libraries_by_path = {}
23
23
  @seen_files = Set.new
24
24
  @seen_libraries = Set.new
25
- @executable_paths = [Gem.bindir, (Bundler.bin_path.to_s if defined?(Bundler))].uniq.compact.freeze
25
+ @executable_paths = [Gem.bindir, bundler_bin_path].uniq.compact.freeze
26
26
 
27
27
  record_library(
28
28
  Library.new(
@@ -116,6 +116,30 @@ module Datadog
116
116
  end
117
117
  end
118
118
 
119
+ # This is intended to mirror bundler's `Bundler.bin_path` with one key difference: the bundler version of the
120
+ # method **tries to create the path** if it doesn't exist, whereas our version doesn't.
121
+ #
122
+ # This "try to create the path" is annoying because creating the path can fail if e.g. the app doesn't have
123
+ # permissions to do that, see https://github.com/DataDog/dd-trace-rb/issues/5137.
124
+ # Thus we have our own version that a) Avoids creating the path, and b) Rescues exceptions to avoid any
125
+ # bundler complaints here impacting the application. (Bundler tends to go "something is wrong, raise!" which
126
+ # I think makes a lot of sense given how bundler is intended to be used, but for this our kind of "ask a few
127
+ # questions usage" it's not what we want.)
128
+ def bundler_bin_path
129
+ return unless defined?(Bundler)
130
+
131
+ path = Bundler.settings[:bin] || "bin"
132
+ root = Bundler.root
133
+ result = Pathname.new(path).expand_path(root).expand_path
134
+ result.to_s
135
+ rescue Exception => e # rubocop:disable Lint/RescueException
136
+ Datadog.logger.debug(
137
+ "CodeProvenance#bundler_bin_path failed. " \
138
+ "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
139
+ )
140
+ nil
141
+ end
142
+
119
143
  # Represents metadata we have for a ruby gem
120
144
  #
121
145
  # Important note: This class gets encoded to JSON with the built-in JSON gem. But, we've found that in some
@@ -137,7 +161,8 @@ module Datadog
137
161
  end
138
162
 
139
163
  def to_json(arg = nil)
140
- {kind: @kind, name: @name, version: @version, paths: @paths}.to_json(arg)
164
+ # Steep: https://github.com/ruby/rbs/pull/2691
165
+ {kind: @kind, name: @name, version: @version, paths: @paths}.to_json(arg) # steep:ignore ArgumentTypeMismatch
141
166
  end
142
167
 
143
168
  def path
@@ -16,7 +16,8 @@ module Datadog
16
16
  class Info
17
17
  def initialize(settings)
18
18
  @profiler_info = nil
19
- @info = {
19
+ # Steep: https://github.com/soutaro/steep/issues/363
20
+ @info = { # steep:ignore IncompatibleAssignment
20
21
  platform: collect_platform_info,
21
22
  runtime: collect_runtime_info,
22
23
  application: collect_application_info(settings),
@@ -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
@@ -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
@@ -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
 
@@ -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
@@ -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.
@@ -289,7 +289,8 @@ module Datadog
289
289
  def duration
290
290
  return @duration_end - @duration_start if @duration_start && @duration_end
291
291
 
292
- @end_time - @start_time if @start_time && @end_time
292
+ # Steep: https://github.com/soutaro/steep/issues/477
293
+ @end_time - @start_time if @start_time && @end_time # steep:ignore NoMethod
293
294
  end
294
295
 
295
296
  def set_error(e)
@@ -387,7 +388,8 @@ module Datadog
387
388
  class Events
388
389
  include Tracing::Events
389
390
 
390
- DEFAULT_ON_ERROR = proc { |span_op, error| span_op&.set_error(error) }
391
+ # Steep: https://github.com/soutaro/steep/issues/335
392
+ DEFAULT_ON_ERROR = proc { |span_op, error| span_op&.set_error(error) } # steep:ignore IncompatibleAssignment
391
393
 
392
394
  attr_reader \
393
395
  :logger,
@@ -395,7 +397,7 @@ module Datadog
395
397
  :after_stop,
396
398
  :before_start
397
399
 
398
- def initialize(logger: Datadog.logger, on_error: nil)
400
+ def initialize(logger: Datadog.logger)
399
401
  @logger = logger
400
402
  @after_finish = AfterFinish.new
401
403
  @after_stop = AfterStop.new
@@ -548,7 +550,10 @@ module Datadog
548
550
  # Used for serialization
549
551
  # @return [Integer] in nanoseconds since Epoch
550
552
  def start_time_nano
551
- @start_time.to_i * 1000000000 + @start_time.nsec
553
+ return 0 if @start_time.nil?
554
+
555
+ # Steep: https://github.com/soutaro/steep/issues/477
556
+ @start_time.to_i * 1000000000 + @start_time.nsec # steep:ignore NoMethod
552
557
  end
553
558
 
554
559
  # Used for serialization