datadog 2.17.0 → 2.18.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 +44 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +12 -46
- data/ext/datadog_profiling_native_extension/collectors_stack.c +227 -49
- data/ext/datadog_profiling_native_extension/collectors_stack.h +19 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +63 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +239 -363
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +1 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -3
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +2 -10
- data/ext/datadog_profiling_native_extension/stack_recorder.c +154 -57
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/library_config.c +54 -12
- data/ext/libdatadog_api/library_config.h +6 -0
- data/ext/libdatadog_api/process_discovery.c +2 -7
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/lru_cache.rb +9 -2
- data/lib/datadog/appsec/api_security/route_extractor.rb +65 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +14 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/component.rb +30 -54
- data/lib/datadog/appsec/configuration/settings.rb +60 -2
- data/lib/datadog/appsec/context.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +27 -16
- data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
- data/lib/datadog/appsec/remote.rb +15 -55
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +10 -11
- data/lib/datadog/appsec.rb +4 -7
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +1 -43
- data/lib/datadog/core/configuration/components.rb +2 -4
- data/lib/datadog/core/configuration/option.rb +9 -9
- data/lib/datadog/core/configuration/settings.rb +22 -10
- data/lib/datadog/core/configuration/stable_config.rb +1 -2
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +5 -1
- data/lib/datadog/core/remote/configuration/repository.rb +12 -0
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +1 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +129 -39
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +11 -5
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/builder.rb +2 -2
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/utils.rb +7 -0
- data/lib/datadog/di/instrumenter.rb +52 -2
- data/lib/datadog/di/probe_notification_builder.rb +31 -41
- data/lib/datadog/di/probe_notifier_worker.rb +9 -1
- data/lib/datadog/di/serializer.rb +6 -2
- data/lib/datadog/di/transport/http/input.rb +10 -0
- data/lib/datadog/di/transport/input.rb +10 -2
- data/lib/datadog/profiling/collectors/code_provenance.rb +17 -8
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +16 -1
- data/lib/datadog/profiling/component.rb +7 -9
- data/lib/datadog/profiling/ext.rb +0 -12
- data/lib/datadog/profiling/http_transport.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +2 -1
- data/lib/datadog/profiling/stack_recorder.rb +5 -5
- data/lib/datadog/profiling/tag_builder.rb +5 -37
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- data/lib/datadog/tracing/sync_writer.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +12 -4
- data/lib/datadog/tracing/tracer.rb +6 -2
- data/lib/datadog/version.rb +1 -1
- metadata +12 -10
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
- data/lib/datadog/appsec/processor.rb +0 -107
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module SecurityEngine
|
6
|
+
# SecurityEngine::Engine creates WAF builder and manages its configuration.
|
7
|
+
# It also rebuilds WAF handle from the WAF builder when configuration changes.
|
8
|
+
class Engine
|
9
|
+
DEFAULT_RULES_CONFIG_PATH = 'ASM_DD/default'
|
10
|
+
TELEMETRY_ACTIONS = %w[init update].freeze
|
11
|
+
DIAGNOSTICS_CONFIG_KEYS = %w[
|
12
|
+
rules
|
13
|
+
custom_rules
|
14
|
+
exclusions
|
15
|
+
actions
|
16
|
+
processors
|
17
|
+
scanners
|
18
|
+
rules_override
|
19
|
+
rules_data
|
20
|
+
exclusion_data
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
attr_reader :waf_addresses, :ruleset_version
|
24
|
+
|
25
|
+
def initialize(appsec_settings:, telemetry:)
|
26
|
+
@default_ruleset = appsec_settings.ruleset
|
27
|
+
|
28
|
+
# NOTE: replace appsec_settings argument with default_ruleset when removing these deprecated settings
|
29
|
+
@default_ip_denylist = appsec_settings.ip_denylist
|
30
|
+
@default_user_id_denylist = appsec_settings.user_id_denylist
|
31
|
+
@default_ip_passlist = appsec_settings.ip_passlist
|
32
|
+
|
33
|
+
@waf_builder = WAF::HandleBuilder.new(
|
34
|
+
obfuscator: {
|
35
|
+
key_regex: appsec_settings.obfuscator_key_regex,
|
36
|
+
value_regex: appsec_settings.obfuscator_value_regex
|
37
|
+
}
|
38
|
+
)
|
39
|
+
|
40
|
+
diagnostics = load_default_config(telemetry: telemetry)
|
41
|
+
report_configuration_diagnostics(diagnostics, action: 'init', telemetry: telemetry)
|
42
|
+
|
43
|
+
@waf_handle = @waf_builder.build_handle
|
44
|
+
@waf_addresses = @waf_handle.known_addresses
|
45
|
+
rescue WAF::Error => e
|
46
|
+
error_message = "AppSec security engine failed to initialize"
|
47
|
+
|
48
|
+
Datadog.logger.error("#{error_message}, error #{e.inspect}")
|
49
|
+
telemetry.report(e, description: error_message)
|
50
|
+
|
51
|
+
raise e
|
52
|
+
end
|
53
|
+
|
54
|
+
def finalize!
|
55
|
+
@waf_handle&.finalize!
|
56
|
+
@waf_builder&.finalize!
|
57
|
+
|
58
|
+
@waf_addresses = []
|
59
|
+
@ruleset_version = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def new_runner
|
63
|
+
SecurityEngine::Runner.new(@waf_handle.build_context)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_or_update_config(config, path:)
|
67
|
+
@is_ruleset_update = path.include?('ASM_DD')
|
68
|
+
|
69
|
+
# default config has to be removed when adding an ASM_DD config
|
70
|
+
remove_config_at_path(DEFAULT_RULES_CONFIG_PATH) if @is_ruleset_update
|
71
|
+
|
72
|
+
diagnostics = @waf_builder.add_or_update_config(config, path: path)
|
73
|
+
@ruleset_version = diagnostics['ruleset_version'] if diagnostics.key?('ruleset_version')
|
74
|
+
report_configuration_diagnostics(diagnostics, action: 'update', telemetry: AppSec.telemetry)
|
75
|
+
|
76
|
+
# we need to load default config if diagnostics contains top-level error for rules or processors
|
77
|
+
if @is_ruleset_update &&
|
78
|
+
(diagnostics.key?('error') ||
|
79
|
+
diagnostics.dig('rules', 'error') ||
|
80
|
+
diagnostics.dig('processors', 'errors'))
|
81
|
+
diagnostics = load_default_config(telemetry: AppSec.telemetry)
|
82
|
+
report_configuration_diagnostics(diagnostics, action: 'update', telemetry: AppSec.telemetry)
|
83
|
+
end
|
84
|
+
|
85
|
+
diagnostics
|
86
|
+
rescue WAF::Error => e
|
87
|
+
error_message = "libddwaf builder failed to add or update config at path: #{path}"
|
88
|
+
|
89
|
+
Datadog.logger.debug("#{error_message}, error: #{e.inspect}")
|
90
|
+
AppSec.telemetry.report(e, description: error_message)
|
91
|
+
end
|
92
|
+
|
93
|
+
def remove_config_at_path(path)
|
94
|
+
result = @waf_builder.remove_config_at_path(path)
|
95
|
+
|
96
|
+
if result && path != DEFAULT_RULES_CONFIG_PATH && path.include?('ASM_DD')
|
97
|
+
diagnostics = load_default_config(telemetry: AppSec.telemetry)
|
98
|
+
report_configuration_diagnostics(diagnostics, action: 'update', telemetry: AppSec.telemetry)
|
99
|
+
end
|
100
|
+
|
101
|
+
result
|
102
|
+
rescue WAF::Error => e
|
103
|
+
error_message = "libddwaf handle builder failed to remove config at path: #{path}"
|
104
|
+
|
105
|
+
Datadog.logger.error("#{error_message}, error: #{e.inspect}")
|
106
|
+
AppSec.telemetry.report(e, description: error_message)
|
107
|
+
end
|
108
|
+
|
109
|
+
def reconfigure!
|
110
|
+
old_waf_handle = @waf_handle
|
111
|
+
|
112
|
+
@waf_handle = @waf_builder.build_handle
|
113
|
+
@waf_addresses = @waf_handle.known_addresses
|
114
|
+
|
115
|
+
old_waf_handle&.finalize!
|
116
|
+
rescue WAF::Error => e
|
117
|
+
error_message = "AppSec security engine failed to reconfigure"
|
118
|
+
|
119
|
+
Datadog.logger.error("#{error_message}, error #{e.inspect}")
|
120
|
+
AppSec.telemetry.report(e, description: error_message)
|
121
|
+
|
122
|
+
if old_waf_handle
|
123
|
+
Datadog.logger.warn("Reverting to the previous configuration")
|
124
|
+
|
125
|
+
@waf_handle = old_waf_handle
|
126
|
+
@waf_addresses = old_waf_handle.known_addresses
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def load_default_config(telemetry:)
|
133
|
+
config = AppSec::Processor::RuleLoader.load_rules(telemetry: telemetry, ruleset: @default_ruleset)
|
134
|
+
|
135
|
+
# deprecated - ip and user id denylists should be configured via RC
|
136
|
+
config['rules_data'] ||= AppSec::Processor::RuleLoader.load_data(
|
137
|
+
ip_denylist: @default_ip_denylist,
|
138
|
+
user_id_denylist: @default_user_id_denylist
|
139
|
+
)
|
140
|
+
|
141
|
+
# deprecated - ip passlist should be configured via RC
|
142
|
+
config['exclusions'] ||= AppSec::Processor::RuleLoader.load_exclusions(ip_passlist: @default_ip_passlist)
|
143
|
+
|
144
|
+
diagnostics = @waf_builder.add_or_update_config(config, path: DEFAULT_RULES_CONFIG_PATH)
|
145
|
+
@ruleset_version = diagnostics['ruleset_version']
|
146
|
+
|
147
|
+
diagnostics
|
148
|
+
end
|
149
|
+
|
150
|
+
def report_configuration_diagnostics(diagnostics, action:, telemetry:)
|
151
|
+
raise ArgumentError, 'action must be one of TELEMETRY_ACTIONS' unless TELEMETRY_ACTIONS.include?(action)
|
152
|
+
|
153
|
+
common_tags = {
|
154
|
+
waf_version: Datadog::AppSec::WAF::VERSION::BASE_STRING,
|
155
|
+
event_rules_version: diagnostics.fetch('ruleset_version', @ruleset_version).to_s,
|
156
|
+
action: action
|
157
|
+
}
|
158
|
+
|
159
|
+
if diagnostics['error']
|
160
|
+
telemetry.inc(
|
161
|
+
Ext::TELEMETRY_METRICS_NAMESPACE, 'waf.config_errors', 1,
|
162
|
+
tags: common_tags.merge(scope: 'top-level')
|
163
|
+
)
|
164
|
+
|
165
|
+
telemetry.error(diagnostics['error'])
|
166
|
+
end
|
167
|
+
|
168
|
+
diagnostics.each do |config_key, config_diagnostics|
|
169
|
+
next unless DIAGNOSTICS_CONFIG_KEYS.include?(config_key)
|
170
|
+
next if !config_diagnostics.key?('error') && config_diagnostics.fetch('errors', []).empty?
|
171
|
+
|
172
|
+
if config_diagnostics['error']
|
173
|
+
telemetry.error(config_diagnostics['error'])
|
174
|
+
|
175
|
+
telemetry.inc(
|
176
|
+
Ext::TELEMETRY_METRICS_NAMESPACE, 'waf.config_errors', 1,
|
177
|
+
tags: common_tags.merge(config_key: config_key, scope: 'top-level')
|
178
|
+
)
|
179
|
+
elsif config_diagnostics['errors']
|
180
|
+
config_diagnostics['errors'].each do |error, config_ids|
|
181
|
+
telemetry.error("#{error}: [#{config_ids.join(",")}]")
|
182
|
+
end
|
183
|
+
|
184
|
+
telemetry.inc(
|
185
|
+
Ext::TELEMETRY_METRICS_NAMESPACE, 'waf.config_errors', config_diagnostics['errors'].count,
|
186
|
+
tags: common_tags.merge(config_key: config_key, scope: 'item')
|
187
|
+
)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -9,10 +9,9 @@ module Datadog
|
|
9
9
|
class Runner
|
10
10
|
SUCCESSFUL_EXECUTION_CODES = [:ok, :match].freeze
|
11
11
|
|
12
|
-
def initialize(
|
12
|
+
def initialize(waf_context)
|
13
13
|
@mutex = Mutex.new
|
14
|
-
@
|
15
|
-
@telemetry = telemetry
|
14
|
+
@waf_context = waf_context
|
16
15
|
|
17
16
|
@debug_tag = "libddwaf:#{WAF::VERSION::STRING} method:ddwaf_run"
|
18
17
|
end
|
@@ -33,7 +32,7 @@ module Datadog
|
|
33
32
|
v.nil? || v.empty?
|
34
33
|
end
|
35
34
|
|
36
|
-
|
35
|
+
result = try_run(persistent_data, ephemeral_data, timeout)
|
37
36
|
stop_ns = Core::Utils::Time.get_time(:nanosecond)
|
38
37
|
|
39
38
|
report_execution(result)
|
@@ -55,19 +54,19 @@ module Datadog
|
|
55
54
|
@mutex.unlock
|
56
55
|
end
|
57
56
|
|
58
|
-
def finalize
|
59
|
-
@
|
57
|
+
def finalize!
|
58
|
+
@waf_context.finalize!
|
60
59
|
end
|
61
60
|
|
62
61
|
private
|
63
62
|
|
64
63
|
def try_run(persistent_data, ephemeral_data, timeout)
|
65
|
-
@
|
66
|
-
rescue WAF::
|
64
|
+
@waf_context.run(persistent_data, ephemeral_data, timeout)
|
65
|
+
rescue WAF::LibDDWAFError => e
|
67
66
|
Datadog.logger.debug { "#{@debug_tag} execution error: #{e} backtrace: #{e.backtrace&.first(3)}" }
|
68
|
-
|
67
|
+
AppSec.telemetry.report(e, description: 'libddwaf-rb internal low-level error')
|
69
68
|
|
70
|
-
|
69
|
+
WAF::Result.new(:err_internal, [], 0, false, [], [])
|
71
70
|
end
|
72
71
|
|
73
72
|
def report_execution(result)
|
@@ -79,7 +78,7 @@ module Datadog
|
|
79
78
|
message = "#{@debug_tag} execution error: #{result.status.inspect}"
|
80
79
|
|
81
80
|
Datadog.logger.debug { message }
|
82
|
-
|
81
|
+
AppSec.telemetry.error(message)
|
83
82
|
end
|
84
83
|
end
|
85
84
|
end
|
data/lib/datadog/appsec.rb
CHANGED
@@ -26,15 +26,12 @@ module Datadog
|
|
26
26
|
components.appsec&.telemetry
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
components.appsec&.
|
29
|
+
def security_engine
|
30
|
+
components.appsec&.security_engine
|
31
31
|
end
|
32
32
|
|
33
|
-
def reconfigure
|
34
|
-
|
35
|
-
return unless appsec_component
|
36
|
-
|
37
|
-
appsec_component.reconfigure(ruleset: ruleset, telemetry: telemetry)
|
33
|
+
def reconfigure!
|
34
|
+
components.appsec&.reconfigure!
|
38
35
|
end
|
39
36
|
|
40
37
|
def reconfigure_lock(&block)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ext'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Core
|
7
|
+
module Configuration
|
8
|
+
# Immutable container for the resulting settings
|
9
|
+
class AgentSettings
|
10
|
+
# IPv6 regular expression from
|
11
|
+
# https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
|
12
|
+
# Does not match IPv4 addresses.
|
13
|
+
IPV6_REGEXP = /\A(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\z)/.freeze # rubocop:disable Layout/LineLength
|
14
|
+
|
15
|
+
attr_reader :adapter, :ssl, :hostname, :port, :uds_path, :timeout_seconds
|
16
|
+
|
17
|
+
def initialize(adapter: nil, ssl: nil, hostname: nil, port: nil, uds_path: nil, timeout_seconds: nil)
|
18
|
+
@adapter = adapter
|
19
|
+
@ssl = ssl
|
20
|
+
@hostname = hostname
|
21
|
+
@port = port
|
22
|
+
@uds_path = uds_path
|
23
|
+
@timeout_seconds = timeout_seconds
|
24
|
+
freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
def url
|
28
|
+
case adapter
|
29
|
+
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
30
|
+
hostname = self.hostname
|
31
|
+
hostname = "[#{hostname}]" if IPV6_REGEXP.match?(hostname)
|
32
|
+
"#{ssl ? "https" : "http"}://#{hostname}:#{port}/"
|
33
|
+
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
|
34
|
+
"unix://#{uds_path}"
|
35
|
+
else
|
36
|
+
raise ArgumentError, "Unexpected adapter: #{adapter}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
self.class == other.class &&
|
42
|
+
adapter == other.adapter &&
|
43
|
+
ssl == other.ssl &&
|
44
|
+
hostname == other.hostname &&
|
45
|
+
port == other.port &&
|
46
|
+
uds_path == other.uds_path &&
|
47
|
+
timeout_seconds == other.timeout_seconds
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -4,6 +4,7 @@ require 'uri'
|
|
4
4
|
|
5
5
|
require_relative 'settings'
|
6
6
|
require_relative 'ext'
|
7
|
+
require_relative 'agent_settings'
|
7
8
|
require_relative '../transport/ext'
|
8
9
|
|
9
10
|
module Datadog
|
@@ -19,49 +20,6 @@ module Datadog
|
|
19
20
|
# Whenever there is a conflict (different configurations are provided in different orders), it MUST warn the users
|
20
21
|
# about it and pick a value based on the following priority: code > environment variable > defaults.
|
21
22
|
class AgentSettingsResolver
|
22
|
-
# Immutable container for the resulting settings
|
23
|
-
class AgentSettings
|
24
|
-
attr_reader :adapter, :ssl, :hostname, :port, :uds_path, :timeout_seconds
|
25
|
-
|
26
|
-
def initialize(adapter: nil, ssl: nil, hostname: nil, port: nil, uds_path: nil, timeout_seconds: nil)
|
27
|
-
@adapter = adapter
|
28
|
-
@ssl = ssl
|
29
|
-
@hostname = hostname
|
30
|
-
@port = port
|
31
|
-
@uds_path = uds_path
|
32
|
-
@timeout_seconds = timeout_seconds
|
33
|
-
freeze
|
34
|
-
end
|
35
|
-
|
36
|
-
def url
|
37
|
-
case adapter
|
38
|
-
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
39
|
-
hostname = self.hostname
|
40
|
-
hostname = "[#{hostname}]" if IPV6_REGEXP.match?(hostname)
|
41
|
-
"#{ssl ? "https" : "http"}://#{hostname}:#{port}/"
|
42
|
-
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
|
43
|
-
"unix://#{uds_path}"
|
44
|
-
else
|
45
|
-
raise ArgumentError, "Unexpected adapter: #{adapter}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def ==(other)
|
50
|
-
self.class == other.class &&
|
51
|
-
adapter == other.adapter &&
|
52
|
-
ssl == other.ssl &&
|
53
|
-
hostname == other.hostname &&
|
54
|
-
port == other.port &&
|
55
|
-
uds_path == other.uds_path &&
|
56
|
-
timeout_seconds == other.timeout_seconds
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# IPv6 regular expression from
|
61
|
-
# https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
|
62
|
-
# Does not match IPv4 addresses.
|
63
|
-
IPV6_REGEXP = /\A(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\z)/.freeze # rubocop:disable Layout/LineLength
|
64
|
-
|
65
23
|
def self.call(settings, logger: Datadog.logger)
|
66
24
|
new(settings, logger: logger).send(:call)
|
67
25
|
end
|
@@ -126,8 +126,7 @@ module Datadog
|
|
126
126
|
@dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
|
127
127
|
@error_tracking = Datadog::ErrorTracking::Component.build(settings, @tracer, @logger)
|
128
128
|
@environment_logger_extra[:dynamic_instrumentation_enabled] = !!@dynamic_instrumentation
|
129
|
-
|
130
|
-
# @process_discovery_fd = Core::ProcessDiscovery.get_and_store_metadata(settings, @logger)
|
129
|
+
@process_discovery_fd = Core::ProcessDiscovery.get_and_store_metadata(settings, @logger)
|
131
130
|
|
132
131
|
self.class.configure_tracing(settings)
|
133
132
|
end
|
@@ -211,8 +210,7 @@ module Datadog
|
|
211
210
|
telemetry.emit_closing! unless replacement&.telemetry&.enabled
|
212
211
|
telemetry.shutdown!
|
213
212
|
|
214
|
-
|
215
|
-
# Core::ProcessDiscovery._native_close_tracer_memfd(@process_discovery_fd, @logger) if @process_discovery_fd
|
213
|
+
@process_discovery_fd&.shutdown!
|
216
214
|
end
|
217
215
|
|
218
216
|
# Returns the current state of various components.
|
@@ -22,7 +22,7 @@ module Datadog
|
|
22
22
|
# Represents an Option precedence level.
|
23
23
|
# Each precedence has a `numeric` value; higher values means higher precedence.
|
24
24
|
# `name` is for inspection purposes only.
|
25
|
-
Value = Struct.new(:numeric, :name) do
|
25
|
+
Value = Struct.new(:numeric, :name, :origin) do
|
26
26
|
include Comparable
|
27
27
|
|
28
28
|
def <=>(other)
|
@@ -33,22 +33,22 @@ module Datadog
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# Remote configuration provided through the Datadog app.
|
36
|
-
REMOTE_CONFIGURATION = Value.new(5, :remote_configuration).freeze
|
36
|
+
REMOTE_CONFIGURATION = Value.new(5, :remote_configuration, 'remote_config').freeze
|
37
37
|
|
38
38
|
# Configuration provided in Ruby code, in this same process
|
39
|
-
PROGRAMMATIC = Value.new(4, :programmatic).freeze
|
39
|
+
PROGRAMMATIC = Value.new(4, :programmatic, 'code').freeze
|
40
40
|
|
41
41
|
# Configuration provided by fleet managed stable config
|
42
|
-
FLEET_STABLE = Value.new(3, :fleet_stable).freeze
|
42
|
+
FLEET_STABLE = Value.new(3, :fleet_stable, 'fleet_stable_config').freeze
|
43
43
|
|
44
44
|
# Configuration provided via environment variable
|
45
|
-
ENVIRONMENT = Value.new(2, :environment).freeze
|
45
|
+
ENVIRONMENT = Value.new(2, :environment, 'env_var').freeze
|
46
46
|
|
47
47
|
# Configuration provided by local stable config file
|
48
|
-
LOCAL_STABLE = Value.new(1, :local_stable).freeze
|
48
|
+
LOCAL_STABLE = Value.new(1, :local_stable, 'local_stable_config').freeze
|
49
49
|
|
50
50
|
# Configuration that comes from default values
|
51
|
-
DEFAULT = Value.new(0, :default).freeze
|
51
|
+
DEFAULT = Value.new(0, :default, 'default').freeze
|
52
52
|
|
53
53
|
# All precedences, sorted from highest to lowest
|
54
54
|
LIST = [REMOTE_CONFIGURATION, PROGRAMMATIC, FLEET_STABLE, ENVIRONMENT, LOCAL_STABLE, DEFAULT].sort.reverse.freeze
|
@@ -309,7 +309,7 @@ module Datadog
|
|
309
309
|
end
|
310
310
|
|
311
311
|
def set_customer_stable_config_value
|
312
|
-
customer_config = StableConfig.configuration
|
312
|
+
customer_config = StableConfig.configuration.dig(:local, :config)
|
313
313
|
return if customer_config.nil?
|
314
314
|
|
315
315
|
value, resolved_env = get_value_and_resolved_env_from(customer_config, source: 'local stable config')
|
@@ -317,7 +317,7 @@ module Datadog
|
|
317
317
|
end
|
318
318
|
|
319
319
|
def set_fleet_stable_config_value
|
320
|
-
fleet_config = StableConfig.configuration
|
320
|
+
fleet_config = StableConfig.configuration.dig(:fleet, :config)
|
321
321
|
return if fleet_config.nil?
|
322
322
|
|
323
323
|
value, resolved_env = get_value_and_resolved_env_from(fleet_config, source: 'fleet stable config')
|
@@ -313,7 +313,7 @@ module Datadog
|
|
313
313
|
|
314
314
|
# Can be used to enable/disable the collection of heap profiles.
|
315
315
|
#
|
316
|
-
# This feature is
|
316
|
+
# This feature is in preview and disabled by default. Requires Ruby 3.1+.
|
317
317
|
#
|
318
318
|
# @warn To enable heap profiling you are required to also enable allocation profiling.
|
319
319
|
#
|
@@ -326,12 +326,12 @@ module Datadog
|
|
326
326
|
|
327
327
|
# Can be used to enable/disable the collection of heap size profiles.
|
328
328
|
#
|
329
|
-
# This feature is
|
329
|
+
# This feature is in preview and by default is enabled whenever heap profiling is enabled.
|
330
330
|
#
|
331
|
-
# @warn
|
331
|
+
# @warn Heap size profiling depends on allocation and heap profiling, so they must be enabled as well.
|
332
332
|
#
|
333
|
-
# @default `DD_PROFILING_EXPERIMENTAL_HEAP_SIZE_ENABLED` environment variable as a boolean, otherwise
|
334
|
-
#
|
333
|
+
# @default `DD_PROFILING_EXPERIMENTAL_HEAP_SIZE_ENABLED` environment variable as a boolean, otherwise it
|
334
|
+
# follows the value of `experimental_heap_enabled`.
|
335
335
|
option :experimental_heap_size_enabled do |o|
|
336
336
|
o.type :bool
|
337
337
|
o.env 'DD_PROFILING_EXPERIMENTAL_HEAP_SIZE_ENABLED'
|
@@ -341,17 +341,19 @@ module Datadog
|
|
341
341
|
# Can be used to configure the heap sampling rate: a heap sample will be collected for every x allocation
|
342
342
|
# samples.
|
343
343
|
#
|
344
|
-
# The
|
345
|
-
#
|
344
|
+
# The higher the value, the less accuracy in heap tracking but the smaller the overhead.
|
345
|
+
#
|
346
|
+
# If you needed to tweak this, please tell us why on <https://github.com/DataDog/dd-trace-rb/issues/new>,
|
347
|
+
# so we can fix it!
|
346
348
|
#
|
347
349
|
# The effective heap sampling rate in terms of allocations (not allocation samples) can be calculated via
|
348
350
|
# effective_heap_sample_rate = allocation_sample_rate * heap_sample_rate.
|
349
351
|
#
|
350
|
-
# @default `DD_PROFILING_EXPERIMENTAL_HEAP_SAMPLE_RATE` environment variable, otherwise `
|
352
|
+
# @default `DD_PROFILING_EXPERIMENTAL_HEAP_SAMPLE_RATE` environment variable, otherwise `1`.
|
351
353
|
option :experimental_heap_sample_rate do |o|
|
352
354
|
o.type :int
|
353
355
|
o.env 'DD_PROFILING_EXPERIMENTAL_HEAP_SAMPLE_RATE'
|
354
|
-
o.default
|
356
|
+
o.default 1
|
355
357
|
end
|
356
358
|
|
357
359
|
# Can be used to disable checking which version of `libmysqlclient` is being used by the `mysql2` gem.
|
@@ -542,6 +544,16 @@ module Datadog
|
|
542
544
|
o.env 'DD_PROFILING_HEAP_CLEAN_AFTER_GC_ENABLED'
|
543
545
|
o.default true
|
544
546
|
end
|
547
|
+
|
548
|
+
# Controls if the profiler should use native filenames for frames in stack traces for functions implemented using
|
549
|
+
# native code. Setting to `false` will make the profiler fall back to default Ruby stack trace behavior (only show .rb files).
|
550
|
+
#
|
551
|
+
# @default true
|
552
|
+
option :native_filenames_enabled do |o|
|
553
|
+
o.type :bool
|
554
|
+
o.env 'DD_PROFILING_NATIVE_FILENAMES_ENABLED'
|
555
|
+
o.default true
|
556
|
+
end
|
545
557
|
end
|
546
558
|
|
547
559
|
# @public_api
|
@@ -572,7 +584,7 @@ module Datadog
|
|
572
584
|
|
573
585
|
option :experimental_runtime_id_enabled do |o|
|
574
586
|
o.type :bool
|
575
|
-
o.env 'DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED'
|
587
|
+
o.env ['DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED', 'DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED']
|
576
588
|
o.default false
|
577
589
|
end
|
578
590
|
|
@@ -14,8 +14,7 @@ module Datadog
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.configuration
|
17
|
-
|
18
|
-
@configuration ||= {} # TODO: After libdatadog 17.1 release, delete this line
|
17
|
+
@configuration ||= StableConfig.extract_configuration
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../tag_builder'
|
3
4
|
require_relative '../utils'
|
4
|
-
require_relative '../environment/socket'
|
5
|
-
require_relative '../environment/identity'
|
6
|
-
require_relative '../environment/git'
|
7
5
|
|
8
6
|
module Datadog
|
9
7
|
module Core
|
@@ -11,27 +9,11 @@ module Datadog
|
|
11
9
|
# This module builds a hash of tags
|
12
10
|
module TagBuilder
|
13
11
|
def self.call(settings)
|
14
|
-
hash =
|
15
|
-
'host' => Environment::Socket.hostname,
|
16
|
-
'process_id' => Process.pid.to_s,
|
17
|
-
'runtime_engine' => Environment::Identity.lang_engine,
|
18
|
-
'runtime-id' => Environment::Identity.id,
|
19
|
-
'runtime_platform' => Environment::Identity.lang_platform,
|
20
|
-
'runtime_version' => Environment::Identity.lang_version,
|
21
|
-
'env' => settings.env,
|
22
|
-
'service' => settings.service,
|
23
|
-
'version' => settings.version,
|
24
|
-
'git.repository_url' => Environment::Git.git_repository_url,
|
25
|
-
'git.commit.sha' => Environment::Git.git_commit_sha,
|
12
|
+
hash = Core::TagBuilder.tags(settings).merge(
|
26
13
|
'is_crash' => 'true',
|
27
|
-
|
28
|
-
'library_version' => Core::Environment::Identity.gem_datadog_version,
|
29
|
-
}.compact
|
14
|
+
)
|
30
15
|
|
31
|
-
|
32
|
-
settings.tags.merge(hash).each_with_object({}) do |(key, value), h|
|
33
|
-
h[Utils.utf8_encode(key)] = Utils.utf8_encode(value)
|
34
|
-
end
|
16
|
+
Utils.encode_tags(hash)
|
35
17
|
end
|
36
18
|
end
|
37
19
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'datadog/core/process_discovery/tracer_memfd'
|
4
|
+
|
3
5
|
module Datadog
|
4
6
|
module Core
|
5
7
|
# Class used to store tracer metadata in a native file descriptor.
|
@@ -10,7 +12,9 @@ module Datadog
|
|
10
12
|
return
|
11
13
|
end
|
12
14
|
metadata = get_metadata(settings)
|
13
|
-
_native_store_tracer_metadata(logger, **metadata)
|
15
|
+
memfd = _native_store_tracer_metadata(logger, **metadata)
|
16
|
+
memfd.logger = logger if memfd
|
17
|
+
memfd
|
14
18
|
end
|
15
19
|
|
16
20
|
# According to the RFC, runtime_id, service_name, service_env, service_version are optional.
|
@@ -237,6 +237,10 @@ module Datadog
|
|
237
237
|
@path = path
|
238
238
|
@previous = previous
|
239
239
|
end
|
240
|
+
|
241
|
+
def type
|
242
|
+
:delete
|
243
|
+
end
|
240
244
|
end
|
241
245
|
|
242
246
|
# Insert change
|
@@ -247,6 +251,10 @@ module Datadog
|
|
247
251
|
@path = path
|
248
252
|
@content = content
|
249
253
|
end
|
254
|
+
|
255
|
+
def type
|
256
|
+
:insert
|
257
|
+
end
|
250
258
|
end
|
251
259
|
|
252
260
|
# Update change
|
@@ -258,6 +266,10 @@ module Datadog
|
|
258
266
|
@content = content
|
259
267
|
@previous = previous
|
260
268
|
end
|
269
|
+
|
270
|
+
def type
|
271
|
+
:update
|
272
|
+
end
|
261
273
|
end
|
262
274
|
end
|
263
275
|
|