datadog 2.3.0 → 2.5.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 +64 -2
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +10 -22
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +3 -3
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +198 -41
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
- data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +645 -107
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +15 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
- data/ext/datadog_profiling_native_extension/extconf.rb +42 -25
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +194 -34
- data/ext/datadog_profiling_native_extension/heap_recorder.h +11 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +1 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +53 -2
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +14 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +58 -22
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/libdatadog_api/crashtracker.c +20 -18
- data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
- data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
- data/lib/datadog/appsec/component.rb +29 -8
- data/lib/datadog/appsec/configuration/settings.rb +10 -2
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +14 -15
- data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +7 -20
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -15
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +6 -18
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +7 -20
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +5 -18
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -5
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +5 -18
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -10
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +7 -20
- data/lib/datadog/appsec/event.rb +25 -1
- data/lib/datadog/appsec/ext.rb +4 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -5
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +7 -20
- data/lib/datadog/appsec/processor/context.rb +109 -0
- data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
- data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
- data/lib/datadog/appsec/processor.rb +42 -107
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec/scope.rb +1 -4
- data/lib/datadog/appsec/utils/trace_operation.rb +15 -0
- data/lib/datadog/appsec/utils.rb +2 -0
- data/lib/datadog/appsec.rb +3 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +26 -25
- data/lib/datadog/core/configuration/components.rb +4 -3
- data/lib/datadog/core/configuration/settings.rb +96 -5
- data/lib/datadog/core/configuration.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +9 -6
- data/lib/datadog/core/environment/execution.rb +5 -5
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/metrics/client.rb +7 -0
- data/lib/datadog/core/rate_limiter.rb +183 -0
- data/lib/datadog/core/remote/client/capabilities.rb +4 -3
- data/lib/datadog/core/remote/component.rb +4 -2
- data/lib/datadog/core/remote/negotiation.rb +4 -4
- data/lib/datadog/core/remote/tie.rb +2 -0
- data/lib/datadog/core/remote/transport/http.rb +5 -0
- data/lib/datadog/core/remote/worker.rb +1 -1
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +5 -1
- data/lib/datadog/core/semaphore.rb +35 -0
- data/lib/datadog/core/telemetry/component.rb +2 -0
- data/lib/datadog/core/telemetry/event.rb +12 -7
- data/lib/datadog/core/telemetry/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +50 -14
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/transport/ext.rb +1 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/di/code_tracker.rb +166 -0
- data/lib/datadog/di/configuration/settings.rb +163 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/error.rb +31 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/instrumenter.rb +301 -0
- data/lib/datadog/di/probe.rb +162 -0
- data/lib/datadog/di/probe_builder.rb +47 -0
- data/lib/datadog/di/probe_notification_builder.rb +207 -0
- data/lib/datadog/di/probe_notifier_worker.rb +244 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +215 -0
- data/lib/datadog/di/transport.rb +67 -0
- data/lib/datadog/di/utils.rb +39 -0
- data/lib/datadog/di.rb +57 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
- data/lib/datadog/profiling/collectors/info.rb +12 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +32 -8
- data/lib/datadog/profiling/component.rb +21 -4
- data/lib/datadog/profiling/http_transport.rb +6 -1
- data/lib/datadog/profiling/scheduler.rb +2 -0
- data/lib/datadog/profiling/stack_recorder.rb +40 -9
- data/lib/datadog/single_step_instrument.rb +12 -0
- data/lib/datadog/tracing/component.rb +13 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +12 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +24 -2
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +9 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +22 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +9 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +3 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
- data/lib/datadog/tracing/distributed/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/ext.rb +2 -0
- data/lib/datadog/tracing/remote.rb +5 -2
- data/lib/datadog/tracing/sampling/matcher.rb +6 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +2 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +15 -9
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +29 -22
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/http.rb +4 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +2 -2
- data/lib/datadog/tracing/writer.rb +26 -28
- data/lib/datadog/version.rb +1 -1
- metadata +40 -15
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -1,60 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../core/rate_limiter'
|
4
|
+
|
3
5
|
module Datadog
|
4
6
|
module AppSec
|
5
|
-
#
|
6
|
-
#
|
7
|
+
# Per-thread rate limiter based on token bucket rate limiter.
|
8
|
+
#
|
9
|
+
# Since AppSec marks sampling to keep on a security event, this limits
|
10
|
+
# the flood of egress traces involving AppSec
|
7
11
|
class RateLimiter
|
8
|
-
|
9
|
-
@rate = rate
|
10
|
-
@timestamps = []
|
11
|
-
end
|
12
|
-
|
13
|
-
def limit
|
14
|
-
now = Time.now.to_f
|
15
|
-
|
16
|
-
loop do
|
17
|
-
oldest = @timestamps.first
|
18
|
-
|
19
|
-
break if oldest.nil? || now - oldest < 1
|
20
|
-
|
21
|
-
@timestamps.shift
|
22
|
-
end
|
23
|
-
|
24
|
-
@timestamps << now
|
25
|
-
|
26
|
-
if (count = @timestamps.count) <= @rate
|
27
|
-
yield
|
28
|
-
else
|
29
|
-
Datadog.logger.debug { "Rate limit hit: #{count}/#{@rate} AppSec traces/second" }
|
30
|
-
end
|
31
|
-
end
|
12
|
+
THREAD_KEY = :datadog_security_appsec_rate_limiter
|
32
13
|
|
33
14
|
class << self
|
34
|
-
def
|
35
|
-
rate_limiter
|
15
|
+
def thread_local
|
16
|
+
rate_limiter = Thread.current.thread_variable_get(THREAD_KEY)
|
17
|
+
return rate_limiter unless rate_limiter.nil?
|
18
|
+
|
19
|
+
Thread.current.thread_variable_set(THREAD_KEY, new(trace_rate_limit))
|
36
20
|
end
|
37
21
|
|
38
22
|
# reset a rate limiter: used for testing
|
39
|
-
def reset!
|
40
|
-
Thread.current
|
23
|
+
def reset!
|
24
|
+
Thread.current.thread_variable_set(THREAD_KEY, nil)
|
41
25
|
end
|
42
26
|
|
43
|
-
|
44
|
-
|
45
|
-
def rate_limiter(name)
|
46
|
-
case name
|
47
|
-
when :traces
|
48
|
-
Thread.current[:datadog_security_trace_rate_limiter] ||= RateLimiter.new(trace_rate_limit)
|
49
|
-
else
|
50
|
-
raise "unsupported rate limiter: #{name.inspect}"
|
51
|
-
end
|
52
|
-
end
|
27
|
+
private
|
53
28
|
|
54
29
|
def trace_rate_limit
|
55
30
|
Datadog.configuration.appsec.trace_rate_limit
|
56
31
|
end
|
57
32
|
end
|
33
|
+
|
34
|
+
def initialize(rate)
|
35
|
+
@rate_limiter = Core::TokenBucket.new(rate)
|
36
|
+
end
|
37
|
+
|
38
|
+
def limit
|
39
|
+
return yield if @rate_limiter.allow?
|
40
|
+
|
41
|
+
Datadog.logger.debug { "Rate limit hit: #{@rate_limiter.current_window_rate} AppSec traces/second" }
|
42
|
+
end
|
58
43
|
end
|
59
44
|
end
|
60
45
|
end
|
@@ -53,7 +53,7 @@ module Datadog
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# rubocop:disable Metrics/MethodLength
|
56
|
-
def receivers
|
56
|
+
def receivers(telemetry)
|
57
57
|
return [] unless remote_features_enabled?
|
58
58
|
|
59
59
|
matcher = Core::Remote::Dispatcher::Matcher::Product.new(ASM_PRODUCTS)
|
@@ -86,7 +86,10 @@ module Datadog
|
|
86
86
|
end
|
87
87
|
|
88
88
|
if rules.empty?
|
89
|
-
settings_rules = AppSec::Processor::RuleLoader.load_rules(
|
89
|
+
settings_rules = AppSec::Processor::RuleLoader.load_rules(
|
90
|
+
telemetry: telemetry,
|
91
|
+
ruleset: Datadog.configuration.appsec.ruleset
|
92
|
+
)
|
90
93
|
|
91
94
|
raise NoRulesError, 'no default rules available' unless settings_rules
|
92
95
|
|
@@ -99,9 +102,10 @@ module Datadog
|
|
99
102
|
overrides: overrides,
|
100
103
|
exclusions: exclusions,
|
101
104
|
custom_rules: custom_rules,
|
105
|
+
telemetry: telemetry
|
102
106
|
)
|
103
107
|
|
104
|
-
Datadog::AppSec.reconfigure(ruleset: ruleset, actions: actions)
|
108
|
+
Datadog::AppSec.reconfigure(ruleset: ruleset, actions: actions, telemetry: telemetry)
|
105
109
|
end
|
106
110
|
|
107
111
|
[receiver]
|
data/lib/datadog/appsec/scope.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'processor'
|
4
|
-
|
5
3
|
module Datadog
|
6
4
|
module AppSec
|
7
5
|
# Capture context essential to consistently call processor and report via traces
|
@@ -22,8 +20,7 @@ module Datadog
|
|
22
20
|
def activate_scope(trace, service_entry_span, processor)
|
23
21
|
raise ActiveScopeError, 'another scope is active, nested scopes are not supported' if active_scope
|
24
22
|
|
25
|
-
context =
|
26
|
-
|
23
|
+
context = processor.new_context
|
27
24
|
self.active_scope = new(trace, service_entry_span, context)
|
28
25
|
end
|
29
26
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module Utils
|
6
|
+
# Utility class to to AppSec-specific trace operations
|
7
|
+
class TraceOperation
|
8
|
+
def self.appsec_standalone_reject?(trace)
|
9
|
+
Datadog.configuration.appsec.standalone.enabled &&
|
10
|
+
(trace.nil? || trace.get_tag(Datadog::AppSec::Ext::TAG_DISTRIBUTED_APPSEC_EVENT) != '1')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/datadog/appsec/utils.rb
CHANGED
data/lib/datadog/appsec.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative 'appsec/configuration'
|
|
4
4
|
require_relative 'appsec/extensions'
|
5
5
|
require_relative 'appsec/scope'
|
6
6
|
require_relative 'appsec/ext'
|
7
|
+
require_relative 'appsec/utils'
|
7
8
|
|
8
9
|
module Datadog
|
9
10
|
# Namespace for Datadog AppSec instrumentation
|
@@ -23,12 +24,12 @@ module Datadog
|
|
23
24
|
appsec_component.processor if appsec_component
|
24
25
|
end
|
25
26
|
|
26
|
-
def reconfigure(ruleset:, actions:)
|
27
|
+
def reconfigure(ruleset:, actions:, telemetry:)
|
27
28
|
appsec_component = components.appsec
|
28
29
|
|
29
30
|
return unless appsec_component
|
30
31
|
|
31
|
-
appsec_component.reconfigure(ruleset: ruleset, actions: actions)
|
32
|
+
appsec_component.reconfigure(ruleset: ruleset, actions: actions, telemetry: telemetry)
|
32
33
|
end
|
33
34
|
|
34
35
|
def reconfigure_lock(&block)
|
@@ -232,7 +232,32 @@ module Datadog
|
|
232
232
|
end
|
233
233
|
|
234
234
|
def should_use_uds?
|
235
|
-
|
235
|
+
# When we have mixed settings for http/https and uds, we print a warning
|
236
|
+
# and use the uds settings.
|
237
|
+
mixed_http_and_uds
|
238
|
+
can_use_uds?
|
239
|
+
end
|
240
|
+
|
241
|
+
def mixed_http_and_uds
|
242
|
+
return @mixed_http_and_uds if defined?(@mixed_http_and_uds)
|
243
|
+
|
244
|
+
@mixed_http_and_uds = (configured_hostname || configured_port) && can_use_uds?
|
245
|
+
if @mixed_http_and_uds
|
246
|
+
warn_if_configuration_mismatch(
|
247
|
+
[
|
248
|
+
DetectedConfiguration.new(
|
249
|
+
friendly_name: 'configuration for unix domain socket',
|
250
|
+
value: parsed_url.to_s,
|
251
|
+
),
|
252
|
+
DetectedConfiguration.new(
|
253
|
+
friendly_name: 'configuration of hostname/port for http/https use',
|
254
|
+
value: "hostname: '#{hostname}', port: '#{port}'",
|
255
|
+
),
|
256
|
+
]
|
257
|
+
)
|
258
|
+
end
|
259
|
+
|
260
|
+
@mixed_http_and_uds
|
236
261
|
end
|
237
262
|
|
238
263
|
def can_use_uds?
|
@@ -307,30 +332,6 @@ module Datadog
|
|
307
332
|
uri.scheme == 'unix'
|
308
333
|
end
|
309
334
|
|
310
|
-
# When we have mixed settings for http/https and uds, we print a warning and ignore the uds settings
|
311
|
-
def mixed_http_and_uds?
|
312
|
-
return @mixed_http_and_uds if defined?(@mixed_http_and_uds)
|
313
|
-
|
314
|
-
@mixed_http_and_uds = (configured_hostname || configured_port) && can_use_uds?
|
315
|
-
|
316
|
-
if @mixed_http_and_uds
|
317
|
-
warn_if_configuration_mismatch(
|
318
|
-
[
|
319
|
-
DetectedConfiguration.new(
|
320
|
-
friendly_name: 'configuration of hostname/port for http/https use',
|
321
|
-
value: "hostname: '#{hostname}', port: '#{port}'",
|
322
|
-
),
|
323
|
-
DetectedConfiguration.new(
|
324
|
-
friendly_name: 'configuration for unix domain socket',
|
325
|
-
value: parsed_url.to_s,
|
326
|
-
),
|
327
|
-
]
|
328
|
-
)
|
329
|
-
end
|
330
|
-
|
331
|
-
@mixed_http_and_uds
|
332
|
-
end
|
333
|
-
|
334
335
|
# Represents a given configuration value and where we got it from
|
335
336
|
class DetectedConfiguration
|
336
337
|
attr_reader :friendly_name, :value
|
@@ -94,7 +94,9 @@ module Datadog
|
|
94
94
|
# the Core resolver from within your product/component's namespace.
|
95
95
|
agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
|
96
96
|
|
97
|
-
@
|
97
|
+
@telemetry = self.class.build_telemetry(settings, agent_settings, @logger)
|
98
|
+
|
99
|
+
@remote = Remote::Component.build(settings, agent_settings, telemetry: telemetry)
|
98
100
|
@tracer = self.class.build_tracer(settings, agent_settings, logger: @logger)
|
99
101
|
@crashtracker = self.class.build_crashtracker(settings, agent_settings, logger: @logger)
|
100
102
|
|
@@ -107,8 +109,7 @@ module Datadog
|
|
107
109
|
|
108
110
|
@runtime_metrics = self.class.build_runtime_metrics_worker(settings)
|
109
111
|
@health_metrics = self.class.build_health_metrics(settings)
|
110
|
-
@
|
111
|
-
@appsec = Datadog::AppSec::Component.build_appsec_component(settings)
|
112
|
+
@appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
|
112
113
|
|
113
114
|
self.class.configure_tracing(settings)
|
114
115
|
end
|
@@ -410,10 +410,8 @@ module Datadog
|
|
410
410
|
# The profiler gathers data by sending `SIGPROF` unix signals to Ruby application threads.
|
411
411
|
#
|
412
412
|
# We've discovered that this can trigger a bug in a number of Ruby APIs in the `Dir` class, as
|
413
|
-
# described in https://
|
414
|
-
#
|
415
|
-
#
|
416
|
-
# (In the future, once a fix lands upstream, we'll disable this workaround for Rubies that don't need it)
|
413
|
+
# described in https://bugs.ruby-lang.org/issues/20586 .
|
414
|
+
# This was fixed for Ruby 3.4+, and this setting is a no-op for those versions.
|
417
415
|
#
|
418
416
|
# @default `DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED` environment variable as a boolean,
|
419
417
|
# otherwise `true`
|
@@ -462,6 +460,72 @@ module Datadog
|
|
462
460
|
end
|
463
461
|
end
|
464
462
|
end
|
463
|
+
|
464
|
+
# Enables GVL profiling. This will show when threads are waiting for GVL in the timeline view.
|
465
|
+
#
|
466
|
+
# This is a preview feature and disabled by default. It requires Ruby 3.2+.
|
467
|
+
#
|
468
|
+
# @default `DD_PROFILING_PREVIEW_GVL_ENABLED` environment variable as a boolean, otherwise `false`
|
469
|
+
option :preview_gvl_enabled do |o|
|
470
|
+
o.type :bool
|
471
|
+
o.env 'DD_PROFILING_PREVIEW_GVL_ENABLED'
|
472
|
+
o.default false
|
473
|
+
end
|
474
|
+
|
475
|
+
# Controls the smallest time period the profiler will report a thread waiting for the GVL.
|
476
|
+
#
|
477
|
+
# The default value was set to minimize overhead. Periods smaller than the set value will not be reported (e.g.
|
478
|
+
# the thread will be reported as whatever it was doing before it waited for the GVL).
|
479
|
+
#
|
480
|
+
# We do not recommend setting this to less than 1ms. Tweaking this value can increase application latency and
|
481
|
+
# memory use.
|
482
|
+
#
|
483
|
+
# @default 10_000_000 (10ms)
|
484
|
+
option :waiting_for_gvl_threshold_ns do |o|
|
485
|
+
o.type :int
|
486
|
+
o.default 10_000_000
|
487
|
+
end
|
488
|
+
|
489
|
+
# Controls if the profiler should attempt to read context from the otel library
|
490
|
+
#
|
491
|
+
# @default false
|
492
|
+
option :preview_otel_context_enabled do |o|
|
493
|
+
o.env 'DD_PROFILING_PREVIEW_OTEL_CONTEXT_ENABLED'
|
494
|
+
o.default false
|
495
|
+
o.env_parser do |value|
|
496
|
+
if value
|
497
|
+
value = value.strip.downcase
|
498
|
+
if ['only', 'both'].include?(value)
|
499
|
+
value
|
500
|
+
elsif ['true', '1'].include?(value)
|
501
|
+
'both'
|
502
|
+
else
|
503
|
+
'false'
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
o.setter do |value|
|
508
|
+
if value == true
|
509
|
+
:both
|
510
|
+
elsif ['only', 'both', :only, :both].include?(value)
|
511
|
+
value.to_sym
|
512
|
+
else
|
513
|
+
false
|
514
|
+
end
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
# Controls if the heap profiler should attempt to clean young objects after GC, rather than just at
|
519
|
+
# serialization time. This lowers memory usage and high percentile latency.
|
520
|
+
#
|
521
|
+
# Only takes effect when used together with `gc_enabled: true` and `experimental_heap_enabled: true`.
|
522
|
+
#
|
523
|
+
# @default false
|
524
|
+
option :heap_clean_after_gc_enabled do |o|
|
525
|
+
o.type :bool
|
526
|
+
o.env 'DD_PROFILING_HEAP_CLEAN_AFTER_GC_ENABLED'
|
527
|
+
o.default false
|
528
|
+
end
|
465
529
|
end
|
466
530
|
|
467
531
|
# @public_api
|
@@ -630,6 +694,33 @@ module Datadog
|
|
630
694
|
end
|
631
695
|
end
|
632
696
|
|
697
|
+
# The monotonic clock time provider used by Datadog. This option is internal and is used by `datadog-ci`
|
698
|
+
# gem to avoid traces' durations being skewed by timecop.
|
699
|
+
#
|
700
|
+
# It must respect the interface of [Datadog::Core::Utils::Time#get_time] method.
|
701
|
+
#
|
702
|
+
# For [Timecop](https://rubygems.org/gems/timecop), for example,
|
703
|
+
# `->(unit = :float_second) { ::Process.clock_gettime_without_mock(::Process::CLOCK_MONOTONIC, unit) }`
|
704
|
+
# allows Datadog features to use the real monotonic time when time is frozen with
|
705
|
+
# `Timecop.mock_process_clock = true`.
|
706
|
+
#
|
707
|
+
# @default `->(unit = :float_second) { ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, unit)}`
|
708
|
+
# @return [Proc<Numeric>]
|
709
|
+
option :get_time_provider do |o|
|
710
|
+
o.default_proc { |unit = :float_second| ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, unit) }
|
711
|
+
o.type :proc
|
712
|
+
|
713
|
+
o.after_set do |get_time_provider|
|
714
|
+
Core::Utils::Time.get_time_provider = get_time_provider
|
715
|
+
end
|
716
|
+
|
717
|
+
o.resetter do |_value|
|
718
|
+
->(unit = :float_second) { ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, unit) }.tap do |default|
|
719
|
+
Core::Utils::Time.get_time_provider = default
|
720
|
+
end
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
633
724
|
# The `version` tag in Datadog. Use it to enable [Deployment Tracking](https://docs.datadoghq.com/tracing/deployment_tracking/).
|
634
725
|
# @see https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging
|
635
726
|
# @default `DD_VERSION` environment variable, otherwise `nils`
|
@@ -836,7 +927,7 @@ module Datadog
|
|
836
927
|
# Enables reporting of information when Ruby VM crashes.
|
837
928
|
option :enabled do |o|
|
838
929
|
o.type :bool
|
839
|
-
o.default
|
930
|
+
o.default false
|
840
931
|
o.env 'DD_CRASHTRACKING_ENABLED'
|
841
932
|
end
|
842
933
|
end
|
@@ -278,9 +278,7 @@ module Datadog
|
|
278
278
|
def handle_interrupt_shutdown!
|
279
279
|
logger = Datadog.logger
|
280
280
|
shutdown_thread = Thread.new { shutdown! }
|
281
|
-
|
282
|
-
shutdown_thread.name = Datadog::Core::Configuration.name
|
283
|
-
end
|
281
|
+
shutdown_thread.name = Datadog::Core::Configuration.name
|
284
282
|
|
285
283
|
print_message_treshold_seconds = 0.2
|
286
284
|
|
@@ -66,7 +66,8 @@ module Datadog
|
|
66
66
|
def start
|
67
67
|
Utils::AtForkMonkeyPatch.apply!
|
68
68
|
|
69
|
-
start_or_update_on_fork(action: :start)
|
69
|
+
start_or_update_on_fork(action: :start, tags: tags)
|
70
|
+
|
70
71
|
ONLY_ONCE.run do
|
71
72
|
Utils::AtForkMonkeyPatch.at_fork(:child) do
|
72
73
|
# Must NOT reference `self` here, as only the first instance will
|
@@ -77,8 +78,10 @@ module Datadog
|
|
77
78
|
end
|
78
79
|
end
|
79
80
|
|
80
|
-
def update_on_fork
|
81
|
-
|
81
|
+
def update_on_fork(settings: Datadog.configuration)
|
82
|
+
# Here we pick up the latest settings, so that we pick up any tags that change after forking
|
83
|
+
# such as the pid or runtime-id
|
84
|
+
start_or_update_on_fork(action: :update_on_fork, tags: TagBuilder.call(settings))
|
82
85
|
end
|
83
86
|
|
84
87
|
def stop
|
@@ -92,16 +95,16 @@ module Datadog
|
|
92
95
|
|
93
96
|
attr_reader :tags, :agent_base_url, :ld_library_path, :path_to_crashtracking_receiver_binary, :logger
|
94
97
|
|
95
|
-
def start_or_update_on_fork(action:)
|
98
|
+
def start_or_update_on_fork(action:, tags:)
|
96
99
|
self.class._native_start_or_update_on_fork(
|
97
100
|
action: action,
|
98
|
-
|
101
|
+
agent_base_url: agent_base_url,
|
99
102
|
path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary,
|
100
103
|
ld_library_path: ld_library_path,
|
101
104
|
tags_as_array: tags.to_a,
|
102
105
|
upload_timeout_seconds: 1
|
103
106
|
)
|
104
|
-
logger.debug("Crash tracking #{action}
|
107
|
+
logger.debug("Crash tracking action: #{action} successful")
|
105
108
|
rescue => e
|
106
109
|
logger.error("Failed to #{action} crash tracking: #{e.message}")
|
107
110
|
end
|
@@ -25,9 +25,9 @@ module Datadog
|
|
25
25
|
# 2. Checking if `Net::HTTP` is referring to the original one
|
26
26
|
# => ::Net::HTTP.equal?(::WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP)
|
27
27
|
def webmock_enabled?
|
28
|
-
defined?(::WebMock::HttpLibAdapters::NetHttpAdapter) &&
|
28
|
+
!!(defined?(::WebMock::HttpLibAdapters::NetHttpAdapter) &&
|
29
29
|
defined?(::Net::HTTP) &&
|
30
|
-
::Net::HTTP.equal?(::WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get(:@webMockNetHTTP))
|
30
|
+
::Net::HTTP.equal?(::WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get(:@webMockNetHTTP)))
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
@@ -68,7 +68,7 @@ module Datadog
|
|
68
68
|
|
69
69
|
# Check if we are running from `bin/cucumber` or `cucumber/rake/task`.
|
70
70
|
def cucumber?
|
71
|
-
defined?(::Cucumber::Cli)
|
71
|
+
!!defined?(::Cucumber::Cli)
|
72
72
|
end
|
73
73
|
|
74
74
|
# If this is a Rails application, use different heuristics to detect
|
@@ -80,7 +80,7 @@ module Datadog
|
|
80
80
|
# detecting its presence is enough to deduct if this is a development environment.
|
81
81
|
#
|
82
82
|
# @see https://github.com/rails/spring/blob/48b299348ace2188444489a0c216a6f3e9687281/README.md?plain=1#L204-L207
|
83
|
-
defined?(::Spring) || rails_env_development?
|
83
|
+
!!defined?(::Spring) || rails_env_development?
|
84
84
|
end
|
85
85
|
|
86
86
|
RAILS_ENV_DEVELOPMENT = Set['development', 'test'].freeze
|
@@ -94,7 +94,7 @@ module Datadog
|
|
94
94
|
# it's common to have a custom "staging" environment, and such environment normally want to run as close
|
95
95
|
# to production as possible.
|
96
96
|
def rails_env_development?
|
97
|
-
defined?(::Rails.env) && RAILS_ENV_DEVELOPMENT.include?(::Rails.env)
|
97
|
+
!!defined?(::Rails.env) && RAILS_ENV_DEVELOPMENT.include?(::Rails.env)
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
@@ -52,6 +52,11 @@ module Datadog
|
|
52
52
|
::RubyVM::YJIT.runtime_stats[:yjit_alloc_size]
|
53
53
|
end
|
54
54
|
|
55
|
+
# Ratio of YJIT-executed instructions
|
56
|
+
def ratio_in_yjit
|
57
|
+
::RubyVM::YJIT.runtime_stats[:ratio_in_yjit]
|
58
|
+
end
|
59
|
+
|
55
60
|
def available?
|
56
61
|
defined?(::RubyVM::YJIT) \
|
57
62
|
&& ::RubyVM::YJIT.enabled? \
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../utils/time'
|
4
4
|
require_relative '../utils/only_once'
|
5
|
+
require_relative '../telemetry/logger'
|
5
6
|
require_relative '../configuration/ext'
|
6
7
|
|
7
8
|
require_relative 'ext'
|
@@ -100,6 +101,7 @@ module Datadog
|
|
100
101
|
Datadog.logger.error(
|
101
102
|
"Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
102
103
|
)
|
104
|
+
Telemetry::Logger.report(e, description: 'Failed to send count stat')
|
103
105
|
end
|
104
106
|
|
105
107
|
def distribution(stat, value = nil, options = nil, &block)
|
@@ -113,6 +115,7 @@ module Datadog
|
|
113
115
|
Datadog.logger.error(
|
114
116
|
"Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
115
117
|
)
|
118
|
+
Telemetry::Logger.report(e, description: 'Failed to send distribution stat')
|
116
119
|
end
|
117
120
|
|
118
121
|
def increment(stat, options = nil)
|
@@ -125,6 +128,7 @@ module Datadog
|
|
125
128
|
Datadog.logger.error(
|
126
129
|
"Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
127
130
|
)
|
131
|
+
Telemetry::Logger.report(e, description: 'Failed to send increment stat')
|
128
132
|
end
|
129
133
|
|
130
134
|
def gauge(stat, value = nil, options = nil, &block)
|
@@ -138,6 +142,7 @@ module Datadog
|
|
138
142
|
Datadog.logger.error(
|
139
143
|
"Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
140
144
|
)
|
145
|
+
Telemetry::Logger.report(e, description: 'Failed to send gauge stat')
|
141
146
|
end
|
142
147
|
|
143
148
|
def time(stat, options = nil)
|
@@ -153,9 +158,11 @@ module Datadog
|
|
153
158
|
distribution(stat, ((finished - start) * 1000), options)
|
154
159
|
end
|
155
160
|
rescue StandardError => e
|
161
|
+
# TODO: Likely to be redundant, since `distribution` handles its own errors.
|
156
162
|
Datadog.logger.error(
|
157
163
|
"Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
158
164
|
)
|
165
|
+
Telemetry::Logger.report(e, description: 'Failed to send time stat')
|
159
166
|
end
|
160
167
|
end
|
161
168
|
|