datadog 2.2.0 → 2.4.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 +87 -2
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +14 -26
- data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +257 -69
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +53 -28
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +136 -81
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +661 -48
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +83 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +53 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +91 -69
- 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 +54 -12
- data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/helpers.h +6 -17
- data/ext/datadog_profiling_native_extension/http_transport.c +41 -9
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -172
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +116 -139
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +20 -11
- data/ext/datadog_profiling_native_extension/profiling.c +1 -3
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
- data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
- data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +37 -22
- data/ext/libdatadog_api/datadog_ruby_common.c +83 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +53 -0
- data/ext/libdatadog_api/extconf.rb +108 -0
- data/ext/libdatadog_api/macos_development.md +26 -0
- data/ext/libdatadog_extconf_helpers.rb +130 -0
- 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 +2 -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 +35 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +71 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +3 -6
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- 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 +36 -37
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +3 -2
- data/lib/datadog/core/configuration/components.rb +18 -15
- data/lib/datadog/core/configuration/settings.rb +135 -9
- data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
- data/lib/datadog/core/crashtracking/component.rb +111 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/execution.rb +5 -5
- 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/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +51 -2
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +37 -1
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
- data/lib/datadog/core/telemetry/http/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/transport.rb +38 -9
- data/lib/datadog/core/telemetry/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +71 -0
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/di/code_tracker.rb +168 -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/probe.rb +133 -0
- data/lib/datadog/di/probe_builder.rb +41 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +193 -0
- data/lib/datadog/di.rb +14 -0
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +28 -26
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +15 -6
- data/lib/datadog/profiling/collectors/thread_context.rb +30 -2
- data/lib/datadog/profiling/component.rb +89 -95
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +14 -7
- data/lib/datadog/profiling/load_native_extension.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +5 -8
- data/lib/datadog/profiling/scheduler.rb +33 -25
- data/lib/datadog/profiling/stack_recorder.rb +3 -0
- data/lib/datadog/profiling/tag_builder.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +5 -5
- data/lib/datadog/profiling/tasks/setup.rb +16 -35
- data/lib/datadog/profiling.rb +4 -5
- data/lib/datadog/single_step_instrument.rb +12 -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 +4 -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/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
- 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 +14 -10
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +10 -4
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +15 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -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/contrib/trilogy/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
- data/lib/datadog/tracing/distributed/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +6 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- 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 +9 -5
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
- data/lib/datadog/tracing/span.rb +9 -2
- data/lib/datadog/tracing/span_event.rb +41 -0
- data/lib/datadog/tracing/span_operation.rb +6 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +14 -12
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +46 -11
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -73,13 +73,15 @@ module Datadog
|
|
73
73
|
|
74
74
|
attr_reader :diagnostics, :addresses
|
75
75
|
|
76
|
-
def initialize(ruleset:)
|
76
|
+
def initialize(ruleset:, telemetry:)
|
77
77
|
@diagnostics = nil
|
78
78
|
@addresses = []
|
79
79
|
settings = Datadog.configuration.appsec
|
80
|
+
@telemetry = telemetry
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
# TODO: Refactor to make it easier to test
|
83
|
+
unless require_libddwaf && libddwaf_provides_waf? && create_waf_handle(settings, ruleset)
|
84
|
+
Datadog.logger.warn('AppSec is disabled, see logged errors above')
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
@@ -97,8 +99,27 @@ module Datadog
|
|
97
99
|
|
98
100
|
private
|
99
101
|
|
100
|
-
|
101
|
-
|
102
|
+
# libddwaf raises a LoadError on unsupported platforms; it may at some
|
103
|
+
# point succeed in being required yet not provide a specific needed feature.
|
104
|
+
def require_libddwaf
|
105
|
+
Datadog.logger.debug { "libddwaf platform: #{libddwaf_platform}" }
|
106
|
+
|
107
|
+
require 'libddwaf'
|
108
|
+
|
109
|
+
true
|
110
|
+
rescue LoadError => e
|
111
|
+
Datadog.logger.error do
|
112
|
+
'libddwaf failed to load,' \
|
113
|
+
"installed platform: #{libddwaf_platform} ruby platforms: #{ruby_platforms} error: #{e.inspect}"
|
114
|
+
end
|
115
|
+
@telemetry.report(e, description: 'libddwaf failed to load')
|
116
|
+
|
117
|
+
false
|
118
|
+
end
|
119
|
+
|
120
|
+
# check whether libddwaf is required *and* able to provide the needed feature
|
121
|
+
def libddwaf_provides_waf?
|
122
|
+
defined?(Datadog::AppSec::WAF) ? true : false
|
102
123
|
end
|
103
124
|
|
104
125
|
def create_waf_handle(settings, ruleset)
|
@@ -119,6 +140,7 @@ module Datadog
|
|
119
140
|
Datadog.logger.error do
|
120
141
|
"libddwaf failed to initialize, error: #{e.inspect}"
|
121
142
|
end
|
143
|
+
@telemetry.report(e, description: 'libddwaf failed to initialize')
|
122
144
|
|
123
145
|
@diagnostics = e.diagnostics if e.diagnostics
|
124
146
|
|
@@ -127,44 +149,21 @@ module Datadog
|
|
127
149
|
Datadog.logger.error do
|
128
150
|
"libddwaf failed to initialize, error: #{e.inspect}"
|
129
151
|
end
|
152
|
+
@telemetry.report(e, description: 'libddwaf failed to initialize')
|
130
153
|
|
131
154
|
false
|
132
155
|
end
|
133
156
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# libddwaf raises a LoadError on unsupported platforms; it may at some
|
141
|
-
# point succeed in being required yet not provide a specific needed feature.
|
142
|
-
def require_libddwaf
|
143
|
-
Datadog.logger.debug { "libddwaf platform: #{libddwaf_platform}" }
|
144
|
-
|
145
|
-
require 'libddwaf'
|
146
|
-
|
147
|
-
true
|
148
|
-
rescue LoadError => e
|
149
|
-
Datadog.logger.error do
|
150
|
-
'libddwaf failed to load,' \
|
151
|
-
"installed platform: #{libddwaf_platform} ruby platforms: #{ruby_platforms} error: #{e.inspect}"
|
152
|
-
end
|
153
|
-
|
154
|
-
false
|
155
|
-
end
|
156
|
-
|
157
|
-
def libddwaf_spec
|
158
|
-
Gem.loaded_specs['libddwaf']
|
159
|
-
end
|
160
|
-
|
161
|
-
def libddwaf_platform
|
162
|
-
libddwaf_spec ? libddwaf_spec.platform.to_s : 'unknown'
|
157
|
+
def libddwaf_platform
|
158
|
+
if Gem.loaded_specs['libddwaf']
|
159
|
+
Gem.loaded_specs['libddwaf'].platform.to_s
|
160
|
+
else
|
161
|
+
'unknown'
|
163
162
|
end
|
163
|
+
end
|
164
164
|
|
165
|
-
|
166
|
-
|
167
|
-
end
|
165
|
+
def ruby_platforms
|
166
|
+
Gem.platforms.map(&:to_s)
|
168
167
|
end
|
169
168
|
end
|
170
169
|
end
|
@@ -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]
|
@@ -36,7 +36,7 @@ module Datadog
|
|
36
36
|
# I rather use break to stop the execution
|
37
37
|
next if configured_response
|
38
38
|
|
39
|
-
action_configuration = AppSec::Processor::Actions.
|
39
|
+
action_configuration = AppSec::Processor::Actions.fetch_configuration(action)
|
40
40
|
next unless action_configuration
|
41
41
|
|
42
42
|
configured_response = case action_configuration['type']
|
@@ -50,6 +50,20 @@ module Datadog
|
|
50
50
|
configured_response || default_response(env)
|
51
51
|
end
|
52
52
|
|
53
|
+
def graphql_response(gateway_multiplex)
|
54
|
+
multiplex_return = []
|
55
|
+
gateway_multiplex.queries.each do |query|
|
56
|
+
# This method is only called in places where GraphQL-Ruby is already required
|
57
|
+
query_result = ::GraphQL::Query::Result.new(
|
58
|
+
query: query,
|
59
|
+
values: JSON.parse(content('application/json'))
|
60
|
+
)
|
61
|
+
multiplex_return << query_result
|
62
|
+
end
|
63
|
+
|
64
|
+
multiplex_return
|
65
|
+
end
|
66
|
+
|
53
67
|
private
|
54
68
|
|
55
69
|
def default_response(env)
|
data/lib/datadog/appsec.rb
CHANGED
@@ -23,12 +23,12 @@ module Datadog
|
|
23
23
|
appsec_component.processor if appsec_component
|
24
24
|
end
|
25
25
|
|
26
|
-
def reconfigure(ruleset:, actions:)
|
26
|
+
def reconfigure(ruleset:, actions:, telemetry:)
|
27
27
|
appsec_component = components.appsec
|
28
28
|
|
29
29
|
return unless appsec_component
|
30
30
|
|
31
|
-
appsec_component.reconfigure(ruleset: ruleset, actions: actions)
|
31
|
+
appsec_component.reconfigure(ruleset: ruleset, actions: actions, telemetry: telemetry)
|
32
32
|
end
|
33
33
|
|
34
34
|
def reconfigure_lock(&block)
|
@@ -56,5 +56,6 @@ require_relative 'appsec/contrib/rack/integration'
|
|
56
56
|
require_relative 'appsec/contrib/sinatra/integration'
|
57
57
|
require_relative 'appsec/contrib/rails/integration'
|
58
58
|
require_relative 'appsec/contrib/devise/integration'
|
59
|
+
require_relative 'appsec/contrib/graphql/integration'
|
59
60
|
|
60
61
|
require_relative 'appsec/autoload'
|
@@ -13,6 +13,7 @@ require_relative '../remote/component'
|
|
13
13
|
require_relative '../../tracing/component'
|
14
14
|
require_relative '../../profiling/component'
|
15
15
|
require_relative '../../appsec/component'
|
16
|
+
require_relative '../crashtracking/component'
|
16
17
|
|
17
18
|
module Datadog
|
18
19
|
module Core
|
@@ -56,19 +57,18 @@ module Datadog
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def build_telemetry(settings, agent_settings, logger)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
Telemetry::Component.build(settings, agent_settings, logger)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_crashtracker(settings, agent_settings, logger:)
|
64
|
+
return unless settings.crashtracking.enabled
|
65
|
+
|
66
|
+
if (libdatadog_api_failure = Datadog::Core::Crashtracking::Component::LIBDATADOG_API_FAILURE)
|
67
|
+
logger.debug("Cannot enable crashtracking: #{libdatadog_api_failure}")
|
68
|
+
return
|
63
69
|
end
|
64
70
|
|
65
|
-
|
66
|
-
enabled: enabled,
|
67
|
-
metrics_enabled: enabled && settings.telemetry.metrics_enabled,
|
68
|
-
heartbeat_interval_seconds: settings.telemetry.heartbeat_interval_seconds,
|
69
|
-
metrics_aggregation_interval_seconds: settings.telemetry.metrics_aggregation_interval_seconds,
|
70
|
-
dependency_collection: settings.telemetry.dependency_collection
|
71
|
-
)
|
71
|
+
Datadog::Core::Crashtracking::Component.build(settings, agent_settings, logger: logger)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
@@ -82,6 +82,7 @@ module Datadog
|
|
82
82
|
:runtime_metrics,
|
83
83
|
:telemetry,
|
84
84
|
:tracer,
|
85
|
+
:crashtracker,
|
85
86
|
:appsec
|
86
87
|
|
87
88
|
def initialize(settings)
|
@@ -93,20 +94,22 @@ module Datadog
|
|
93
94
|
# the Core resolver from within your product/component's namespace.
|
94
95
|
agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
|
95
96
|
|
96
|
-
@
|
97
|
+
@telemetry = self.class.build_telemetry(settings, agent_settings, @logger)
|
98
|
+
|
99
|
+
@remote = Remote::Component.build(settings, agent_settings, telemetry: telemetry)
|
97
100
|
@tracer = self.class.build_tracer(settings, agent_settings, logger: @logger)
|
101
|
+
@crashtracker = self.class.build_crashtracker(settings, agent_settings, logger: @logger)
|
98
102
|
|
99
103
|
@profiler, profiler_logger_extra = Datadog::Profiling::Component.build_profiler_component(
|
100
104
|
settings: settings,
|
101
105
|
agent_settings: agent_settings,
|
102
|
-
optional_tracer: @tracer
|
106
|
+
optional_tracer: @tracer
|
103
107
|
)
|
104
108
|
@environment_logger_extra.merge!(profiler_logger_extra) if profiler_logger_extra
|
105
109
|
|
106
110
|
@runtime_metrics = self.class.build_runtime_metrics_worker(settings)
|
107
111
|
@health_metrics = self.class.build_health_metrics(settings)
|
108
|
-
@
|
109
|
-
@appsec = Datadog::AppSec::Component.build_appsec_component(settings)
|
112
|
+
@appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
|
110
113
|
|
111
114
|
self.class.configure_tracing(settings)
|
112
115
|
end
|
@@ -301,6 +301,16 @@ module Datadog
|
|
301
301
|
o.default true
|
302
302
|
end
|
303
303
|
|
304
|
+
# Can be used to enable/disable the Datadog::Profiling.allocation_count feature.
|
305
|
+
#
|
306
|
+
# Requires allocation profiling to be enabled.
|
307
|
+
#
|
308
|
+
# @default false
|
309
|
+
option :allocation_counting_enabled do |o|
|
310
|
+
o.type :bool
|
311
|
+
o.default false
|
312
|
+
end
|
313
|
+
|
304
314
|
# Can be used to enable/disable the collection of heap profiles.
|
305
315
|
#
|
306
316
|
# This feature is alpha and disabled by default
|
@@ -400,10 +410,8 @@ module Datadog
|
|
400
410
|
# The profiler gathers data by sending `SIGPROF` unix signals to Ruby application threads.
|
401
411
|
#
|
402
412
|
# We've discovered that this can trigger a bug in a number of Ruby APIs in the `Dir` class, as
|
403
|
-
# described in https://
|
404
|
-
#
|
405
|
-
#
|
406
|
-
# (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.
|
407
415
|
#
|
408
416
|
# @default `DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED` environment variable as a boolean,
|
409
417
|
# otherwise `true`
|
@@ -441,14 +449,70 @@ module Datadog
|
|
441
449
|
o.default 60
|
442
450
|
end
|
443
451
|
|
444
|
-
#
|
445
|
-
#
|
446
|
-
# @default `DD_PROFILING_EXPERIMENTAL_CRASH_TRACKING_ENABLED` environment variable as a boolean,
|
447
|
-
# otherwise `false`
|
452
|
+
# DEV-3.0: Remove `experimental_crash_tracking_enabled` option
|
448
453
|
option :experimental_crash_tracking_enabled do |o|
|
454
|
+
o.after_set do |_, _, precedence|
|
455
|
+
unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
|
456
|
+
Core.log_deprecation(key: :experimental_crash_tracking_enabled) do
|
457
|
+
'The profiling.advanced.experimental_crash_tracking_enabled setting has been deprecated for removal '\
|
458
|
+
'and no longer does anything. Please remove it from your Datadog.configure block.'
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
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|
|
449
470
|
o.type :bool
|
450
|
-
o.env '
|
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'
|
451
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
|
452
516
|
end
|
453
517
|
end
|
454
518
|
|
@@ -618,6 +682,33 @@ module Datadog
|
|
618
682
|
end
|
619
683
|
end
|
620
684
|
|
685
|
+
# The monotonic clock time provider used by Datadog. This option is internal and is used by `datadog-ci`
|
686
|
+
# gem to avoid traces' durations being skewed by timecop.
|
687
|
+
#
|
688
|
+
# It must respect the interface of [Datadog::Core::Utils::Time#get_time] method.
|
689
|
+
#
|
690
|
+
# For [Timecop](https://rubygems.org/gems/timecop), for example,
|
691
|
+
# `->(unit = :float_second) { ::Process.clock_gettime_without_mock(::Process::CLOCK_MONOTONIC, unit) }`
|
692
|
+
# allows Datadog features to use the real monotonic time when time is frozen with
|
693
|
+
# `Timecop.mock_process_clock = true`.
|
694
|
+
#
|
695
|
+
# @default `->(unit = :float_second) { ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, unit)}`
|
696
|
+
# @return [Proc<Numeric>]
|
697
|
+
option :get_time_provider do |o|
|
698
|
+
o.default_proc { |unit = :float_second| ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, unit) }
|
699
|
+
o.type :proc
|
700
|
+
|
701
|
+
o.after_set do |get_time_provider|
|
702
|
+
Core::Utils::Time.get_time_provider = get_time_provider
|
703
|
+
end
|
704
|
+
|
705
|
+
o.resetter do |_value|
|
706
|
+
->(unit = :float_second) { ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, unit) }.tap do |default|
|
707
|
+
Core::Utils::Time.get_time_provider = default
|
708
|
+
end
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
621
712
|
# The `version` tag in Datadog. Use it to enable [Deployment Tracking](https://docs.datadoghq.com/tracing/deployment_tracking/).
|
622
713
|
# @see https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging
|
623
714
|
# @default `DD_VERSION` environment variable, otherwise `nils`
|
@@ -663,6 +754,24 @@ module Datadog
|
|
663
754
|
o.type :bool
|
664
755
|
end
|
665
756
|
|
757
|
+
# Enable agentless mode for telemetry: submit telemetry events directly to the intake without Datadog Agent.
|
758
|
+
#
|
759
|
+
# @return [Boolean]
|
760
|
+
# @!visibility private
|
761
|
+
option :agentless_enabled do |o|
|
762
|
+
o.type :bool
|
763
|
+
o.default false
|
764
|
+
end
|
765
|
+
|
766
|
+
# Overrides agentless telemetry URL. To be used internally for testing purposes only.
|
767
|
+
#
|
768
|
+
# @return [String]
|
769
|
+
# @!visibility private
|
770
|
+
option :agentless_url_override do |o|
|
771
|
+
o.type :string, nilable: true
|
772
|
+
o.env Core::Telemetry::Ext::ENV_AGENTLESS_URL_OVERRIDE
|
773
|
+
end
|
774
|
+
|
666
775
|
# Enable metrics collection for telemetry. Metrics collection only works when telemetry is enabled and
|
667
776
|
# metrics are enabled.
|
668
777
|
# @default `DD_TELEMETRY_METRICS_ENABLED` environment variable, otherwise `true`.
|
@@ -734,6 +843,14 @@ module Datadog
|
|
734
843
|
o.type :string, nilable: true
|
735
844
|
o.env Core::Telemetry::Ext::ENV_INSTALL_TIME
|
736
845
|
end
|
846
|
+
|
847
|
+
# Telemetry shutdown timeout in seconds
|
848
|
+
#
|
849
|
+
# @!visibility private
|
850
|
+
option :shutdown_timeout_seconds do |o|
|
851
|
+
o.type :float
|
852
|
+
o.default 1.0
|
853
|
+
end
|
737
854
|
end
|
738
855
|
|
739
856
|
# Remote configuration
|
@@ -794,6 +911,15 @@ module Datadog
|
|
794
911
|
option :service
|
795
912
|
end
|
796
913
|
|
914
|
+
settings :crashtracking do
|
915
|
+
# Enables reporting of information when Ruby VM crashes.
|
916
|
+
option :enabled do |o|
|
917
|
+
o.type :bool
|
918
|
+
o.default false
|
919
|
+
o.env 'DD_CRASHTRACKING_ENABLED'
|
920
|
+
end
|
921
|
+
end
|
922
|
+
|
797
923
|
# TODO: Tracing should manage its own settings.
|
798
924
|
# Keep this extension here for now to keep things working.
|
799
925
|
extend Datadog::Tracing::Configuration::Settings
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../configuration/ext'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Core
|
7
|
+
module Crashtracking
|
8
|
+
# This module provides a method to resolve the base URL of the agent
|
9
|
+
module AgentBaseUrl
|
10
|
+
def self.resolve(agent_settings)
|
11
|
+
case agent_settings.adapter
|
12
|
+
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
13
|
+
"#{agent_settings.ssl ? 'https' : 'http'}://#{agent_settings.hostname}:#{agent_settings.port}/"
|
14
|
+
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
|
15
|
+
"unix://#{agent_settings.uds_path}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'libdatadog'
|
4
|
+
|
5
|
+
require_relative 'tag_builder'
|
6
|
+
require_relative 'agent_base_url'
|
7
|
+
require_relative '../utils/only_once'
|
8
|
+
require_relative '../utils/at_fork_monkey_patch'
|
9
|
+
|
10
|
+
module Datadog
|
11
|
+
module Core
|
12
|
+
module Crashtracking
|
13
|
+
# Used to report Ruby VM crashes.
|
14
|
+
#
|
15
|
+
# NOTE: The crashtracker native state is a singleton;
|
16
|
+
# so even if you create multiple instances of `Crashtracking::Component` and start them,
|
17
|
+
# it only works as "last writer wins". Same for stop -- there's only one state, so calling stop
|
18
|
+
# on it will stop the crash tracker, regardless of which instance started it.
|
19
|
+
#
|
20
|
+
# Methods prefixed with _native_ are implemented in `crashtracker.c`
|
21
|
+
class Component
|
22
|
+
LIBDATADOG_API_FAILURE =
|
23
|
+
begin
|
24
|
+
require "libdatadog_api.#{RUBY_VERSION[/\d+.\d+/]}_#{RUBY_PLATFORM}"
|
25
|
+
nil
|
26
|
+
rescue LoadError => e
|
27
|
+
e.message
|
28
|
+
end
|
29
|
+
|
30
|
+
ONLY_ONCE = Core::Utils::OnlyOnce.new
|
31
|
+
|
32
|
+
def self.build(settings, agent_settings, logger:)
|
33
|
+
tags = TagBuilder.call(settings)
|
34
|
+
agent_base_url = AgentBaseUrl.resolve(agent_settings)
|
35
|
+
logger.warn('Missing agent base URL; cannot enable crash tracking') unless agent_base_url
|
36
|
+
|
37
|
+
ld_library_path = ::Libdatadog.ld_library_path
|
38
|
+
logger.warn('Missing ld_library_path; cannot enable crash tracking') unless ld_library_path
|
39
|
+
|
40
|
+
path_to_crashtracking_receiver_binary = ::Libdatadog.path_to_crashtracking_receiver_binary
|
41
|
+
unless path_to_crashtracking_receiver_binary
|
42
|
+
logger.warn('Missing path_to_crashtracking_receiver_binary; cannot enable crash tracking')
|
43
|
+
end
|
44
|
+
|
45
|
+
return unless agent_base_url
|
46
|
+
return unless ld_library_path
|
47
|
+
return unless path_to_crashtracking_receiver_binary
|
48
|
+
|
49
|
+
new(
|
50
|
+
tags: tags,
|
51
|
+
agent_base_url: agent_base_url,
|
52
|
+
ld_library_path: ld_library_path,
|
53
|
+
path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary,
|
54
|
+
logger: logger
|
55
|
+
).tap(&:start)
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize(tags:, agent_base_url:, ld_library_path:, path_to_crashtracking_receiver_binary:, logger:)
|
59
|
+
@tags = tags
|
60
|
+
@agent_base_url = agent_base_url
|
61
|
+
@ld_library_path = ld_library_path
|
62
|
+
@path_to_crashtracking_receiver_binary = path_to_crashtracking_receiver_binary
|
63
|
+
@logger = logger
|
64
|
+
end
|
65
|
+
|
66
|
+
def start
|
67
|
+
Utils::AtForkMonkeyPatch.apply!
|
68
|
+
|
69
|
+
start_or_update_on_fork(action: :start)
|
70
|
+
ONLY_ONCE.run do
|
71
|
+
Utils::AtForkMonkeyPatch.at_fork(:child) do
|
72
|
+
# Must NOT reference `self` here, as only the first instance will
|
73
|
+
# be captured by the ONLY_ONCE and we want to pick the latest active one
|
74
|
+
# (which may have different tags or agent config)
|
75
|
+
Datadog.send(:components).crashtracker&.update_on_fork
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def update_on_fork
|
81
|
+
start_or_update_on_fork(action: :update_on_fork)
|
82
|
+
end
|
83
|
+
|
84
|
+
def stop
|
85
|
+
self.class._native_stop
|
86
|
+
logger.debug('Crash tracking stopped successfully')
|
87
|
+
rescue => e
|
88
|
+
logger.error("Failed to stop crash tracking: #{e.message}")
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
attr_reader :tags, :agent_base_url, :ld_library_path, :path_to_crashtracking_receiver_binary, :logger
|
94
|
+
|
95
|
+
def start_or_update_on_fork(action:)
|
96
|
+
self.class._native_start_or_update_on_fork(
|
97
|
+
action: action,
|
98
|
+
agent_base_url: agent_base_url,
|
99
|
+
path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary,
|
100
|
+
ld_library_path: ld_library_path,
|
101
|
+
tags_as_array: tags.to_a,
|
102
|
+
upload_timeout_seconds: 1
|
103
|
+
)
|
104
|
+
logger.debug("Crash tracking #{action} successfully")
|
105
|
+
rescue => e
|
106
|
+
logger.error("Failed to #{action} crash tracking: #{e.message}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|