datadog 2.44.0 → 2.46.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +114 -141
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -5
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +0 -2
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +13 -13
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +5 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +1 -0
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +106 -103
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +3 -3
- data/ext/datadog_profiling_native_extension/extconf.rb +2 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +2 -2
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +102 -54
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +7 -2
- data/ext/datadog_profiling_native_extension/profiling.c +27 -23
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +3 -1
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -0
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +0 -2
- data/ext/datadog_profiling_native_extension/stack_recorder.c +6 -24
- data/ext/datadog_profiling_native_extension/stack_recorder.h +0 -1
- data/ext/datadog_profiling_native_extension/time_helpers.c +2 -4
- data/ext/datadog_profiling_native_extension/time_helpers.h +10 -11
- data/ext/libdatadog_api/di.c +30 -5
- data/ext/libdatadog_api/extconf.rb +2 -0
- data/ext/libdatadog_api/otel_thread_context.c +20 -14
- data/ext/libdatadog_api/process_discovery.c +15 -1
- data/ext/libdatadog_api/trace_exporter.c +182 -36
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/core/configuration/components.rb +29 -8
- data/lib/datadog/core/configuration/supported_configurations.rb +5 -2
- data/lib/datadog/core/process_discovery.rb +5 -1
- data/lib/datadog/core/remote/client/capabilities.rb +34 -29
- data/lib/datadog/core/remote/component.rb +28 -12
- data/lib/datadog/core/remote/dispatcher.rb +13 -3
- data/lib/datadog/di/boot.rb +1 -0
- data/lib/datadog/di/capture_expression_evaluator/result.rb +30 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +39 -9
- data/lib/datadog/di/component.rb +38 -3
- data/lib/datadog/di/configuration.rb +53 -2
- data/lib/datadog/di/context.rb +7 -2
- data/lib/datadog/di/contrib/active_record.rb +8 -2
- data/lib/datadog/di/evaluation_failure.rb +28 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +87 -0
- data/lib/datadog/di/guardrails_telemetry.rb +203 -0
- data/lib/datadog/di/instrumenter.rb +65 -15
- data/lib/datadog/di/logger.rb +30 -8
- data/lib/datadog/di/probe_manager.rb +48 -5
- data/lib/datadog/di/probe_notification_builder.rb +28 -26
- data/lib/datadog/di/probe_notifier_worker.rb +56 -6
- data/lib/datadog/di/serializer.rb +130 -54
- data/lib/datadog/di/snapshot_event.rb +38 -0
- data/lib/datadog/di/transport/http.rb +13 -3
- data/lib/datadog/di/transport/input.rb +32 -7
- data/lib/datadog/open_feature/activation.rb +268 -0
- data/lib/datadog/open_feature/component.rb +31 -15
- data/lib/datadog/open_feature/provider.rb +282 -5
- data/lib/datadog/open_feature.rb +31 -1
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -0
- data/lib/datadog/profiling/component.rb +2 -3
- data/lib/datadog/profiling/exporter.rb +7 -5
- data/lib/datadog/tracing/component.rb +15 -1
- data/lib/datadog/tracing/configuration/settings.rb +6 -3
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +6 -3
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -0
- data/lib/datadog/tracing/otel_thread_context.rb +3 -5
- data/lib/datadog/tracing/transport/http/telemetry.rb +94 -0
- data/lib/datadog/tracing/transport/http/traces.rb +2 -0
- data/lib/datadog/tracing/transport/native/telemetry.rb +17 -0
- data/lib/datadog/tracing/transport/native.rb +38 -22
- data/lib/datadog/tracing/transport/telemetry.rb +62 -0
- data/lib/datadog/tracing/transport/traces.rb +82 -15
- data/lib/datadog/version.rb +1 -1
- metadata +16 -7
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "ext"
|
|
4
|
+
require_relative "../open_feature"
|
|
4
5
|
require_relative "../core/utils/time"
|
|
5
6
|
require "open_feature/sdk"
|
|
6
7
|
|
|
7
8
|
module Datadog
|
|
8
9
|
module OpenFeature
|
|
9
|
-
# OpenFeature feature flagging provider backed by Datadog
|
|
10
|
+
# OpenFeature feature flagging provider backed by Datadog configuration delivery.
|
|
10
11
|
#
|
|
11
12
|
# Requires openfeature-sdk >= 0.5.1 for flag evaluation metrics and EVP hook support.
|
|
12
13
|
#
|
|
@@ -24,13 +25,14 @@ module Datadog
|
|
|
24
25
|
#
|
|
25
26
|
# Example:
|
|
26
27
|
#
|
|
27
|
-
#
|
|
28
|
+
# Feature Flags use agentless configuration delivery by default. To use
|
|
29
|
+
# Remote Configuration delivery instead, configure the source explicitly.
|
|
28
30
|
#
|
|
29
31
|
# ```ruby
|
|
30
32
|
# # FILE: initializers/datadog.rb
|
|
31
33
|
# Datadog.configure do |config|
|
|
32
34
|
# config.remote.enabled = true
|
|
33
|
-
# config.
|
|
35
|
+
# config.feature_flags.configuration_source = "remote_config"
|
|
34
36
|
# end
|
|
35
37
|
# ```
|
|
36
38
|
#
|
|
@@ -58,20 +60,110 @@ module Datadog
|
|
|
58
60
|
# # => 'Welcome back!'
|
|
59
61
|
# ```
|
|
60
62
|
class Provider
|
|
63
|
+
include ::OpenFeature::SDK::Provider::EventEmitter
|
|
64
|
+
|
|
61
65
|
NAME = "Datadog Feature Flagging Provider"
|
|
66
|
+
INITIALIZATION_CANCELLED_MESSAGE = "Feature Flags provider initialization was cancelled by shutdown"
|
|
62
67
|
|
|
63
68
|
attr_reader :metadata
|
|
64
69
|
|
|
65
70
|
def initialize
|
|
66
71
|
@metadata = ::OpenFeature::SDK::Provider::ProviderMetadata.new(name: NAME).freeze
|
|
72
|
+
@initialization_mutex = Mutex.new
|
|
73
|
+
@initializing = false
|
|
74
|
+
@initialization_thread = nil
|
|
75
|
+
@awaiting_ready_after_fork = false
|
|
76
|
+
@initialization_failed = false
|
|
77
|
+
@provider_error_observed = false
|
|
78
|
+
@ready_pending = false
|
|
79
|
+
@ready_dispatch_claimed = false
|
|
80
|
+
@stale_emitted = false
|
|
81
|
+
@stale_pending = false
|
|
82
|
+
@error_handler = nil
|
|
83
|
+
@initialization_ready_handler = nil
|
|
84
|
+
@waiting_component = nil
|
|
85
|
+
@shutdown = false
|
|
67
86
|
end
|
|
68
87
|
|
|
69
88
|
def init
|
|
70
|
-
|
|
89
|
+
@initialization_mutex.synchronize do
|
|
90
|
+
raise INITIALIZATION_CANCELLED_MESSAGE if @shutdown
|
|
91
|
+
|
|
92
|
+
@initializing = true
|
|
93
|
+
@initialization_thread = Thread.current
|
|
94
|
+
@awaiting_ready_after_fork = false
|
|
95
|
+
@initialization_failed = false
|
|
96
|
+
@provider_error_observed = false
|
|
97
|
+
@ready_pending = false
|
|
98
|
+
@ready_dispatch_claimed = false
|
|
99
|
+
@stale_emitted = false
|
|
100
|
+
@stale_pending = false
|
|
101
|
+
end
|
|
102
|
+
ready_handler_installed = install_initialization_ready_handler
|
|
103
|
+
|
|
104
|
+
component, failure = OpenFeature.activate_provider(self)
|
|
105
|
+
cancel_initialization_if_shutdown!
|
|
106
|
+
fail_initialization(component, failure || "Feature Flags component could not be activated") unless component
|
|
107
|
+
|
|
108
|
+
@initialization_mutex.synchronize do
|
|
109
|
+
raise INITIALIZATION_CANCELLED_MESSAGE if @shutdown
|
|
110
|
+
|
|
111
|
+
@waiting_component = component
|
|
112
|
+
end
|
|
113
|
+
# Shutdown publishes this flag through the component lock; taking our mutex here would invert lock order.
|
|
114
|
+
wait_result = component.wait_for_configuration { @shutdown }
|
|
115
|
+
cancel_initialization_if_shutdown!
|
|
116
|
+
|
|
117
|
+
case wait_result
|
|
118
|
+
when Component::CONFIGURATION_READY
|
|
119
|
+
@initialization_mutex.synchronize { @initializing = false } unless ready_handler_installed
|
|
120
|
+
when Component::CONFIGURATION_TIMEOUT
|
|
121
|
+
message = "Feature Flags provider initialization timed out while waiting for configuration"
|
|
122
|
+
Datadog.logger.error(message)
|
|
123
|
+
fail_initialization(component, message)
|
|
124
|
+
else
|
|
125
|
+
fail_initialization(component, "Feature Flags provider initialization stopped before configuration arrived")
|
|
126
|
+
end
|
|
127
|
+
rescue
|
|
128
|
+
prepare_initialization_failure(component) if @initialization_mutex.synchronize { @initializing }
|
|
129
|
+
raise
|
|
130
|
+
ensure
|
|
131
|
+
@initialization_mutex.synchronize do
|
|
132
|
+
@waiting_component = nil
|
|
133
|
+
# The SDK still owes READY after init returns; the initializing thread owns that dispatch.
|
|
134
|
+
@initialization_thread = nil unless @initializing
|
|
135
|
+
end
|
|
71
136
|
end
|
|
72
137
|
|
|
73
138
|
def shutdown
|
|
74
|
-
|
|
139
|
+
configuration = @configuration
|
|
140
|
+
# @type var error_handler: Provider::provider_event_handler?
|
|
141
|
+
error_handler = nil
|
|
142
|
+
# @type var initialization_ready_handler: Provider::provider_event_handler?
|
|
143
|
+
initialization_ready_handler = nil
|
|
144
|
+
waiting_component = nil #: Component?
|
|
145
|
+
@initialization_mutex.synchronize do
|
|
146
|
+
return if @shutdown
|
|
147
|
+
|
|
148
|
+
@shutdown = true
|
|
149
|
+
@initializing = false
|
|
150
|
+
@initialization_thread = nil
|
|
151
|
+
error_handler = @error_handler
|
|
152
|
+
initialization_ready_handler = @initialization_ready_handler
|
|
153
|
+
waiting_component = @waiting_component
|
|
154
|
+
@error_handler = nil
|
|
155
|
+
@initialization_ready_handler = nil
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
waiting_component&.wake_configuration_waiters
|
|
159
|
+
configuration&.remove_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_ERROR, error_handler) if error_handler
|
|
160
|
+
if initialization_ready_handler
|
|
161
|
+
configuration&.remove_handler(
|
|
162
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_READY,
|
|
163
|
+
initialization_ready_handler,
|
|
164
|
+
)
|
|
165
|
+
end
|
|
166
|
+
OpenFeature.deactivate_provider(self)
|
|
75
167
|
end
|
|
76
168
|
|
|
77
169
|
def hooks
|
|
@@ -108,6 +200,191 @@ module Datadog
|
|
|
108
200
|
|
|
109
201
|
private
|
|
110
202
|
|
|
203
|
+
def after_fork(component)
|
|
204
|
+
handler = @initialization_mutex.synchronize do
|
|
205
|
+
return if @shutdown || !@initializing || @initialization_thread&.alive?
|
|
206
|
+
|
|
207
|
+
@initializing = false
|
|
208
|
+
@initialization_thread = nil
|
|
209
|
+
@waiting_component = nil
|
|
210
|
+
@awaiting_ready_after_fork = true
|
|
211
|
+
@stale_pending = false
|
|
212
|
+
previous_handler = @initialization_ready_handler
|
|
213
|
+
@initialization_ready_handler = nil
|
|
214
|
+
previous_handler
|
|
215
|
+
end
|
|
216
|
+
if handler
|
|
217
|
+
@configuration&.remove_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY, handler)
|
|
218
|
+
end
|
|
219
|
+
configuration_changed(Component::CONFIGURATION_READY) if component&.configuration_received?
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def fail_initialization(component, message)
|
|
223
|
+
prepare_initialization_failure(component)
|
|
224
|
+
cancel_initialization_if_shutdown!
|
|
225
|
+
raise message.to_s
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def prepare_initialization_failure(component)
|
|
229
|
+
cancelled, initialization_ready_handler = @initialization_mutex.synchronize do
|
|
230
|
+
handler = @initialization_ready_handler
|
|
231
|
+
@initialization_ready_handler = nil
|
|
232
|
+
@stale_pending = false
|
|
233
|
+
@initializing = false
|
|
234
|
+
@initialization_thread = nil
|
|
235
|
+
if @shutdown
|
|
236
|
+
[true, handler]
|
|
237
|
+
else
|
|
238
|
+
@initialization_failed = true
|
|
239
|
+
@ready_pending ||= !!component&.configuration_received?
|
|
240
|
+
[false, handler]
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
if initialization_ready_handler
|
|
244
|
+
@configuration&.remove_handler(
|
|
245
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_READY,
|
|
246
|
+
initialization_ready_handler,
|
|
247
|
+
)
|
|
248
|
+
end
|
|
249
|
+
return if cancelled
|
|
250
|
+
|
|
251
|
+
install_error_handler
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def cancel_initialization_if_shutdown!
|
|
255
|
+
cancelled = @initialization_mutex.synchronize do
|
|
256
|
+
@initializing = false if @shutdown
|
|
257
|
+
@shutdown
|
|
258
|
+
end
|
|
259
|
+
raise INITIALIZATION_CANCELLED_MESSAGE if cancelled
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def shutdown?
|
|
263
|
+
@initialization_mutex.synchronize { @shutdown }
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def install_initialization_ready_handler
|
|
267
|
+
configuration = @configuration
|
|
268
|
+
return false unless configuration
|
|
269
|
+
|
|
270
|
+
handler = @initialization_mutex.synchronize do
|
|
271
|
+
return false if @shutdown
|
|
272
|
+
return true if @initialization_ready_handler
|
|
273
|
+
|
|
274
|
+
@initialization_ready_handler = ->(details) { provider_ready(details) }
|
|
275
|
+
end
|
|
276
|
+
configuration.add_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY, handler)
|
|
277
|
+
|
|
278
|
+
cancelled = @initialization_mutex.synchronize { @shutdown }
|
|
279
|
+
configuration.remove_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY, handler) if cancelled
|
|
280
|
+
return false if cancelled
|
|
281
|
+
|
|
282
|
+
true
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def install_error_handler
|
|
286
|
+
configuration = @configuration
|
|
287
|
+
return unless configuration
|
|
288
|
+
|
|
289
|
+
handler = @initialization_mutex.synchronize do
|
|
290
|
+
return if @shutdown
|
|
291
|
+
|
|
292
|
+
@error_handler ||= ->(details) { provider_error(details) }
|
|
293
|
+
end
|
|
294
|
+
configuration.add_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_ERROR, handler)
|
|
295
|
+
|
|
296
|
+
cancelled = @initialization_mutex.synchronize { @shutdown }
|
|
297
|
+
configuration.remove_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_ERROR, handler) if cancelled
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def provider_error(_details)
|
|
301
|
+
configuration = @configuration
|
|
302
|
+
return unless configuration
|
|
303
|
+
return unless configuration.send(:provider_state, self) == ::OpenFeature::SDK::ProviderState::ERROR
|
|
304
|
+
|
|
305
|
+
emit_ready = @initialization_mutex.synchronize do
|
|
306
|
+
if @shutdown
|
|
307
|
+
false
|
|
308
|
+
else
|
|
309
|
+
@provider_error_observed = true
|
|
310
|
+
if @ready_pending && !@ready_dispatch_claimed
|
|
311
|
+
@ready_dispatch_claimed = true
|
|
312
|
+
else
|
|
313
|
+
false
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
emit_event(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY) if emit_ready
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def provider_ready(_details)
|
|
321
|
+
configuration = @configuration
|
|
322
|
+
return unless configuration
|
|
323
|
+
return unless configuration.send(:provider_state, self) == ::OpenFeature::SDK::ProviderState::READY
|
|
324
|
+
|
|
325
|
+
handler, emit_stale = @initialization_mutex.synchronize do
|
|
326
|
+
handler = @initialization_ready_handler
|
|
327
|
+
@initialization_ready_handler = nil
|
|
328
|
+
@initializing = false
|
|
329
|
+
@initialization_thread = nil
|
|
330
|
+
if @stale_pending && !@shutdown
|
|
331
|
+
@stale_pending = false
|
|
332
|
+
@stale_emitted = true
|
|
333
|
+
[handler, true]
|
|
334
|
+
else
|
|
335
|
+
[handler, false]
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
configuration.remove_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY, handler) if handler
|
|
339
|
+
emit_event(::OpenFeature::SDK::ProviderEvent::PROVIDER_STALE) if emit_stale
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def configuration_changed(event)
|
|
343
|
+
event_type = @initialization_mutex.synchronize do
|
|
344
|
+
if @shutdown
|
|
345
|
+
nil
|
|
346
|
+
elsif event == Component::CONFIGURATION_READY
|
|
347
|
+
if @initializing
|
|
348
|
+
@ready_pending = true
|
|
349
|
+
@stale_pending = false
|
|
350
|
+
nil
|
|
351
|
+
elsif @awaiting_ready_after_fork
|
|
352
|
+
@awaiting_ready_after_fork = false
|
|
353
|
+
@stale_emitted = false
|
|
354
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_READY
|
|
355
|
+
elsif @initialization_failed && !@provider_error_observed
|
|
356
|
+
@stale_emitted = false
|
|
357
|
+
@ready_pending = true
|
|
358
|
+
nil
|
|
359
|
+
elsif @stale_emitted
|
|
360
|
+
@stale_emitted = false
|
|
361
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_READY
|
|
362
|
+
elsif @initialization_failed
|
|
363
|
+
if @provider_error_observed && !@ready_dispatch_claimed
|
|
364
|
+
@ready_dispatch_claimed = true
|
|
365
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_READY
|
|
366
|
+
else
|
|
367
|
+
@ready_pending = true
|
|
368
|
+
nil
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
elsif event == Component::CONFIGURATION_CHANGED && !@initializing
|
|
372
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_CONFIGURATION_CHANGED
|
|
373
|
+
elsif event == Component::CONFIGURATION_LOST
|
|
374
|
+
@ready_pending = false
|
|
375
|
+
if @initializing
|
|
376
|
+
@stale_pending = true
|
|
377
|
+
nil
|
|
378
|
+
else
|
|
379
|
+
@stale_emitted = true
|
|
380
|
+
::OpenFeature::SDK::ProviderEvent::PROVIDER_STALE
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
emit_event(event_type) if event_type
|
|
386
|
+
end
|
|
387
|
+
|
|
111
388
|
def evaluate(flag_key, default_value:, expected_type:, evaluation_context:)
|
|
112
389
|
# Stamp evaluation entry time once, here on the eval thread. The EVP path uses this for
|
|
113
390
|
# accurate first/last_evaluation bounds instead of a later hook-fire clock read.
|
data/lib/datadog/open_feature.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "core/configuration"
|
|
4
4
|
require_relative "open_feature/configuration"
|
|
5
|
+
require_relative "open_feature/configuration/source"
|
|
5
6
|
|
|
6
7
|
module Datadog
|
|
7
8
|
# A namespace for the OpenFeature component.
|
|
@@ -9,11 +10,40 @@ module Datadog
|
|
|
9
10
|
Core::Configuration::Settings.extend(Configuration::Settings)
|
|
10
11
|
|
|
11
12
|
def self.enabled?
|
|
12
|
-
Datadog.configuration.
|
|
13
|
+
Configuration::Source.resolve(Datadog.configuration).enabled?
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def self.engine
|
|
16
17
|
Datadog.send(:components).open_feature&.engine
|
|
17
18
|
end
|
|
19
|
+
|
|
20
|
+
def self.activate_provider(provider)
|
|
21
|
+
# Initialize the component tree before taking its reconfiguration lock.
|
|
22
|
+
Datadog.send(:components)
|
|
23
|
+
Datadog.send(:safely_synchronize) do
|
|
24
|
+
return [nil, nil] if provider.send(:shutdown?)
|
|
25
|
+
|
|
26
|
+
components = Datadog.send(:components, allow_initialization: false)
|
|
27
|
+
activation = components&.send(:open_feature_activation)
|
|
28
|
+
providers = @adopted_providers ||= {}.compare_by_identity
|
|
29
|
+
providers[provider] = true
|
|
30
|
+
[activation&.activate(provider), activation&.failure]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.deactivate_provider(provider)
|
|
35
|
+
Datadog.send(:safely_synchronize) do
|
|
36
|
+
@adopted_providers&.delete(provider)
|
|
37
|
+
components = Datadog.send(:components, allow_initialization: false)
|
|
38
|
+
components&.send(:open_feature_activation)&.deactivate(provider)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Components startup already holds the non-reentrant reconfiguration lock.
|
|
43
|
+
def self.reattach(activation)
|
|
44
|
+
providers = @adopted_providers&.keys || []
|
|
45
|
+
providers.each { |provider| activation.activate(provider) }
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
18
48
|
end
|
|
19
49
|
end
|
|
@@ -147,6 +147,11 @@ module Datadog
|
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
+
# @rbs return: Datadog::Profiling::StackRecorder
|
|
151
|
+
def prepare_serialize
|
|
152
|
+
self.class._native_prepare_serialize(self)
|
|
153
|
+
end
|
|
154
|
+
|
|
150
155
|
#: () -> true
|
|
151
156
|
def reset_after_fork
|
|
152
157
|
self.class._native_reset_after_fork(self)
|
|
@@ -73,7 +73,7 @@ module Datadog
|
|
|
73
73
|
heap_sample_every: heap_sample_every,
|
|
74
74
|
}.freeze
|
|
75
75
|
|
|
76
|
-
exporter = build_profiler_exporter(settings,
|
|
76
|
+
exporter = build_profiler_exporter(settings, worker, internal_metadata: internal_metadata)
|
|
77
77
|
transport = build_profiler_transport(settings, agent_settings)
|
|
78
78
|
scheduler = Profiling::Scheduler.new(exporter: exporter, transport: transport, interval: upload_period_seconds)
|
|
79
79
|
profiler = Profiling::Profiler.new(worker: worker, scheduler: scheduler)
|
|
@@ -109,13 +109,12 @@ module Datadog
|
|
|
109
109
|
)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
private_class_method def self.build_profiler_exporter(settings,
|
|
112
|
+
private_class_method def self.build_profiler_exporter(settings, worker, internal_metadata:)
|
|
113
113
|
info_collector = Profiling::Collectors::Info.new(settings)
|
|
114
114
|
code_provenance_collector =
|
|
115
115
|
(Profiling::Collectors::CodeProvenance.new if settings.profiling.advanced.code_provenance_enabled)
|
|
116
116
|
|
|
117
117
|
Profiling::Exporter.new(
|
|
118
|
-
pprof_recorder: recorder,
|
|
119
118
|
worker: worker,
|
|
120
119
|
info_collector: info_collector,
|
|
121
120
|
code_provenance_collector: code_provenance_collector,
|
|
@@ -20,7 +20,6 @@ module Datadog
|
|
|
20
20
|
|
|
21
21
|
private
|
|
22
22
|
|
|
23
|
-
attr_reader :pprof_recorder #: Datadog::Profiling::StackRecorder
|
|
24
23
|
# The code provenance collector acts both as collector and as a recorder
|
|
25
24
|
attr_reader :code_provenance_collector #: Datadog::Profiling::Collectors::CodeProvenance?
|
|
26
25
|
attr_reader :minimum_duration_seconds #: ::Integer
|
|
@@ -33,7 +32,6 @@ module Datadog
|
|
|
33
32
|
|
|
34
33
|
public
|
|
35
34
|
|
|
36
|
-
# @rbs pprof_recorder: Datadog::Profiling::StackRecorder
|
|
37
35
|
# @rbs worker: Datadog::Profiling::Collectors::CpuAndWallTimeWorker
|
|
38
36
|
# @rbs info_collector: Datadog::Profiling::Collectors::Info
|
|
39
37
|
# @rbs code_provenance_collector: Datadog::Profiling::Collectors::CodeProvenance?
|
|
@@ -43,7 +41,6 @@ module Datadog
|
|
|
43
41
|
# @rbs sequence_tracker: singleton(Datadog::Profiling::SequenceTracker)
|
|
44
42
|
# @rbs return: void
|
|
45
43
|
def initialize(
|
|
46
|
-
pprof_recorder:,
|
|
47
44
|
worker:,
|
|
48
45
|
info_collector:,
|
|
49
46
|
code_provenance_collector:,
|
|
@@ -52,7 +49,6 @@ module Datadog
|
|
|
52
49
|
time_provider: Time,
|
|
53
50
|
sequence_tracker: Datadog::Profiling::SequenceTracker
|
|
54
51
|
)
|
|
55
|
-
@pprof_recorder = pprof_recorder
|
|
56
52
|
@worker = worker
|
|
57
53
|
@code_provenance_collector = code_provenance_collector
|
|
58
54
|
@minimum_duration_seconds = minimum_duration_seconds
|
|
@@ -68,6 +64,7 @@ module Datadog
|
|
|
68
64
|
|
|
69
65
|
#: () -> Datadog::Profiling::Flush?
|
|
70
66
|
def flush
|
|
67
|
+
pprof_recorder = @worker.prepare_serialize
|
|
71
68
|
worker_stats = @worker.stats_and_reset_not_thread_safe
|
|
72
69
|
serialization_result = pprof_recorder.serialize
|
|
73
70
|
return if serialization_result.nil?
|
|
@@ -111,7 +108,7 @@ module Datadog
|
|
|
111
108
|
worker_stats: worker_stats,
|
|
112
109
|
profile_stats: profile_stats,
|
|
113
110
|
recorder_stats: pprof_recorder.stats,
|
|
114
|
-
gc:
|
|
111
|
+
gc: gc_stats,
|
|
115
112
|
}
|
|
116
113
|
),
|
|
117
114
|
info_json: info_json,
|
|
@@ -131,6 +128,11 @@ module Datadog
|
|
|
131
128
|
|
|
132
129
|
private
|
|
133
130
|
|
|
131
|
+
# @rbs return: Hash[Symbol, Integer | bool]
|
|
132
|
+
def gc_stats
|
|
133
|
+
GC.stat.merge(auto_compact: GC.respond_to?(:auto_compact) && GC.auto_compact)
|
|
134
|
+
end
|
|
135
|
+
|
|
134
136
|
#: (::Time, ::Time) -> bool
|
|
135
137
|
def duration_below_threshold?(start, finish)
|
|
136
138
|
(finish - start) < minimum_duration_seconds
|
|
@@ -62,6 +62,20 @@ module Datadog
|
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
+
def bind_transport_telemetry(tracer, telemetry)
|
|
66
|
+
return unless tracer.is_a?(Tracing::Tracer)
|
|
67
|
+
|
|
68
|
+
writer = tracer.writer
|
|
69
|
+
return unless writer.respond_to?(:transport)
|
|
70
|
+
|
|
71
|
+
transport = writer.transport
|
|
72
|
+
if transport.is_a?(Transport::Traces::Transport) ||
|
|
73
|
+
(defined?(Transport::Native::Transport) && transport.is_a?(Transport::Native::Transport))
|
|
74
|
+
transport.telemetry = telemetry
|
|
75
|
+
end
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
65
79
|
def build_sampler(settings)
|
|
66
80
|
# A custom sampler is provided
|
|
67
81
|
if (sampler = settings.tracing.sampler)
|
|
@@ -106,7 +120,7 @@ module Datadog
|
|
|
106
120
|
return writer
|
|
107
121
|
end
|
|
108
122
|
|
|
109
|
-
if settings.tracing.native_transport && (transport = build_native_transport(agent_settings))
|
|
123
|
+
if !options.key?(:transport) && settings.tracing.native_transport && (transport = build_native_transport(agent_settings))
|
|
110
124
|
options = options.merge(transport: transport)
|
|
111
125
|
end
|
|
112
126
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../../tracing/configuration/ext"
|
|
4
4
|
require_relative "../../core/environment/variable_helpers"
|
|
5
|
+
require_relative "../../ruby_version"
|
|
5
6
|
require_relative "../contrib/status_range_matcher"
|
|
6
7
|
require_relative "../contrib/status_range_env_parser"
|
|
7
8
|
require_relative "http"
|
|
@@ -257,7 +258,9 @@ module Datadog
|
|
|
257
258
|
|
|
258
259
|
option :otel_thread_context_enabled do |o|
|
|
259
260
|
o.env Tracing::Configuration::Ext::ENV_OTEL_CONTEXT_ENABLED
|
|
260
|
-
o.default
|
|
261
|
+
o.default do
|
|
262
|
+
RUBY_ENGINE == "ruby" && RUBY_PLATFORM.include?("linux")
|
|
263
|
+
end
|
|
261
264
|
o.type :bool
|
|
262
265
|
end
|
|
263
266
|
|
|
@@ -496,11 +499,11 @@ module Datadog
|
|
|
496
499
|
#
|
|
497
500
|
# This option is recommended for internal use only.
|
|
498
501
|
#
|
|
499
|
-
# @default `false`
|
|
502
|
+
# @default `true` on CRuby 4.0.0 and later, otherwise `false`
|
|
500
503
|
# @return [Boolean]
|
|
501
504
|
option :native_transport do |o|
|
|
502
505
|
o.env Configuration::Ext::ENV_EXPERIMENTAL_NATIVE_TRANSPORT_ENABLED
|
|
503
|
-
o.default
|
|
506
|
+
o.default { RUBY_ENGINE == "ruby" && RubyVersion.is?(">= 4.0.0") }
|
|
504
507
|
o.type :bool
|
|
505
508
|
end
|
|
506
509
|
|
|
@@ -60,6 +60,8 @@ module Datadog
|
|
|
60
60
|
def query(query, options = {})
|
|
61
61
|
query!(query, options)
|
|
62
62
|
rescue
|
|
63
|
+
return "" if options && options[:obfuscate]
|
|
64
|
+
|
|
63
65
|
options[:placeholder] || PLACEHOLDER
|
|
64
66
|
end
|
|
65
67
|
|
|
@@ -136,7 +138,7 @@ module Datadog
|
|
|
136
138
|
(?:"|%22)?
|
|
137
139
|
)
|
|
138
140
|
(?: # common keys
|
|
139
|
-
(?:old[-_]?|
|
|
141
|
+
(?:old[-_]?|new[-_]?)?p(?:ass)?w(?:or)?d(?:1|2)? # pw, password variants
|
|
140
142
|
|pass(?:[-_]?phrase)? # pass, passphrase variants
|
|
141
143
|
|secret
|
|
142
144
|
|(?: # key, key_id variants
|
|
@@ -145,6 +147,7 @@ module Datadog
|
|
|
145
147
|
|public[-_]?
|
|
146
148
|
|access[-_]?
|
|
147
149
|
|secret[-_]?
|
|
150
|
+
|app(?:lication)?[-_]?
|
|
148
151
|
)key(?:[-_]?id)?
|
|
149
152
|
|token
|
|
150
153
|
|consumer[-_]?(?:id|key|secret)
|
|
@@ -165,9 +168,9 @@ module Datadog
|
|
|
165
168
|
bearer(?:\s|%20)+[a-z0-9._-]+
|
|
166
169
|
|token(?::|%3A)[a-z0-9]{13}
|
|
167
170
|
|gh[opsu]_[0-9a-zA-Z]{36}
|
|
168
|
-
|ey[I-L]
|
|
171
|
+
|(?:^|[^\w%-]|%[0-9a-f]{2})ey[I-L][\w-]+(?:=|%3D)*\.ey[I-L][\w-]+(?:=|%3D)*(?:\.(?:[\w.+/=-]|%3D|%2F|%2B)+)?
|
|
169
172
|
|-{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY-{5}[^-]+-{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY(?:-{5})?(?:\n|%0A)?
|
|
170
|
-
|(?:ssh-(?:rsa|dss)|ecdsa-[a-z0-9]+-[a-z0-9]+)(?:\s|%20)
|
|
173
|
+
|(?:ssh-(?:rsa|dss)|ecdsa-[a-z0-9]+-[a-z0-9]+)(?:\s|%20|%09)+(?:[a-z0-9/.+]|%2F|%5C|%2B){100,}(?:=|%3D)*(?:(?:\s|%20|%09)+[a-z0-9._-]+)?
|
|
171
174
|
)
|
|
172
175
|
}ix.freeze
|
|
173
176
|
# rubocop:enable Layout/LineLength
|
|
@@ -60,6 +60,7 @@ module Datadog
|
|
|
60
60
|
def agent_url
|
|
61
61
|
# Retrieve the effect agent URL, regardless of how it was configured
|
|
62
62
|
transport = Tracing.send(:tracer).writer.transport
|
|
63
|
+
return transport.url if transport.respond_to?(:url)
|
|
63
64
|
|
|
64
65
|
# return `nil` with IO transport
|
|
65
66
|
return unless transport.respond_to?(:client)
|
|
@@ -14,9 +14,11 @@ module Datadog
|
|
|
14
14
|
|
|
15
15
|
def self.build(tracing_settings)
|
|
16
16
|
return unless tracing_settings.otel_thread_context_enabled
|
|
17
|
+
return unless Datadog::Core::LIBDATADOG_API_FAILURE.nil?
|
|
17
18
|
|
|
18
19
|
instance = new
|
|
19
|
-
instance
|
|
20
|
+
instance._native_enable
|
|
21
|
+
instance
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
def initialize
|
|
@@ -65,10 +67,6 @@ module Datadog
|
|
|
65
67
|
false
|
|
66
68
|
end
|
|
67
69
|
|
|
68
|
-
def supported?
|
|
69
|
-
Datadog::Core::LIBDATADOG_API_FAILURE.nil? && _native_supported?
|
|
70
|
-
end
|
|
71
|
-
|
|
72
70
|
def update_from_trace_op(trace_op)
|
|
73
71
|
active_span = trace_op.active_span
|
|
74
72
|
|