datadog 2.14.0 → 2.16.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 +67 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +7 -6
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +69 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.h +7 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +3 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +8 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +25 -32
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +22 -21
- data/ext/libdatadog_api/crashtracker.c +1 -9
- data/ext/libdatadog_api/crashtracker.h +5 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/init.c +15 -0
- data/ext/libdatadog_api/library_config.c +122 -0
- data/ext/libdatadog_api/library_config.h +19 -0
- data/ext/libdatadog_api/process_discovery.c +117 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/lib/datadog/appsec/actions_handler.rb +3 -2
- data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
- data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +29 -20
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +31 -18
- data/lib/datadog/appsec/context.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +10 -12
- data/lib/datadog/appsec/contrib/active_record/integration.rb +2 -2
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +22 -22
- data/lib/datadog/appsec/contrib/devise/data_extractor.rb +2 -3
- data/lib/datadog/appsec/contrib/devise/ext.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patcher.rb +3 -5
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +17 -4
- data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +9 -10
- data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +8 -9
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +8 -9
- data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +22 -32
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +16 -16
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +11 -13
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +21 -21
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +10 -11
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -23
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/event.rb +95 -134
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +5 -2
- data/lib/datadog/appsec/metrics/telemetry.rb +1 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +42 -12
- data/lib/datadog/appsec/processor/rule_loader.rb +26 -28
- data/lib/datadog/appsec/processor/rule_merger.rb +5 -5
- data/lib/datadog/appsec/processor.rb +1 -1
- data/lib/datadog/appsec/remote.rb +16 -11
- data/lib/datadog/appsec/response.rb +6 -6
- data/lib/datadog/appsec/security_engine/runner.rb +1 -1
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +19 -10
- data/lib/datadog/core/configuration/option.rb +61 -25
- data/lib/datadog/core/configuration/settings.rb +10 -0
- data/lib/datadog/core/configuration/stable_config.rb +23 -0
- data/lib/datadog/core/configuration.rb +24 -0
- data/lib/datadog/core/crashtracking/component.rb +1 -9
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/environment/git.rb +1 -0
- data/lib/datadog/core/environment/variable_helpers.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +8 -7
- data/lib/datadog/core/process_discovery.rb +32 -0
- data/lib/datadog/core/remote/client.rb +7 -0
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +60 -50
- data/lib/datadog/core/telemetry/emitter.rb +17 -11
- data/lib/datadog/core/telemetry/event.rb +7 -4
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/metric.rb +5 -5
- data/lib/datadog/core/telemetry/request.rb +4 -4
- data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
- data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
- data/lib/datadog/core/telemetry/transport/http.rb +63 -0
- data/lib/datadog/core/telemetry/transport/telemetry.rb +52 -0
- data/lib/datadog/core/telemetry/worker.rb +45 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/core/workers/async.rb +20 -2
- data/lib/datadog/core/workers/interval_loop.rb +12 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
- data/lib/datadog/core.rb +8 -0
- data/lib/datadog/di/boot.rb +34 -0
- data/lib/datadog/di/probe_notification_builder.rb +1 -1
- data/lib/datadog/di/remote.rb +2 -0
- data/lib/datadog/di/transport/http/diagnostics.rb +0 -1
- data/lib/datadog/di/transport/http/input.rb +0 -1
- data/lib/datadog/di/transport/http.rb +0 -6
- data/lib/datadog/di.rb +5 -32
- data/lib/datadog/error_tracking/collector.rb +87 -0
- data/lib/datadog/error_tracking/component.rb +167 -0
- data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
- data/lib/datadog/error_tracking/configuration.rb +11 -0
- data/lib/datadog/error_tracking/ext.rb +18 -0
- data/lib/datadog/error_tracking/extensions.rb +16 -0
- data/lib/datadog/error_tracking/filters.rb +77 -0
- data/lib/datadog/error_tracking.rb +18 -0
- data/lib/datadog/kit/identity.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +3 -0
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +3 -4
- data/lib/datadog/profiling/ext.rb +0 -1
- data/lib/datadog/profiling/flush.rb +4 -7
- data/lib/datadog/profiling/http_transport.rb +10 -59
- data/lib/datadog/profiling/stack_recorder.rb +4 -4
- data/lib/datadog/profiling.rb +1 -0
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/datadog.rb +2 -2
- data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
- data/lib/datadog/tracing/span_event.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +38 -14
- data/lib/datadog/tracing/trace_operation.rb +15 -7
- data/lib/datadog/tracing/tracer.rb +7 -3
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- data/lib/datadog.rb +2 -3
- metadata +40 -10
- data/lib/datadog/core/telemetry/http/env.rb +0 -20
- data/lib/datadog/core/telemetry/http/ext.rb +0 -28
- data/lib/datadog/core/telemetry/http/response.rb +0 -70
- data/lib/datadog/core/telemetry/http/transport.rb +0 -90
@@ -0,0 +1,176 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/*
|
4
|
+
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
require_relative 'agent_settings_resolver'
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
module Core
|
11
|
+
module Configuration
|
12
|
+
# Agent settings resolver for agentless operations (currently, telemetry
|
13
|
+
# in agentless mode).
|
14
|
+
#
|
15
|
+
# The terminology gets a little confusing here, but transports communicate
|
16
|
+
# with servers which are - for most components in the tracer - the
|
17
|
+
# (local) agent. Hence, "agent settings" to refer to where the server
|
18
|
+
# is located. Telemetry supports sending to the local agent but also
|
19
|
+
# implements agentless mode where it sends directly to Datadog intake
|
20
|
+
# endpoints. The agentless mode is configured using different settings,
|
21
|
+
# and this class produces AgentSettings instances when in agentless mode.
|
22
|
+
#
|
23
|
+
# Agentless settings resolver uses the following configuration sources:
|
24
|
+
#
|
25
|
+
# 1. url_override constructor parameter, if provided
|
26
|
+
# 2. Built-in default host/port/TLS settings for the backend
|
27
|
+
# intake endpoint
|
28
|
+
#
|
29
|
+
# The agentless resolver does NOT use agent settings (since it is
|
30
|
+
# for agentless operation), specifically it ignores:
|
31
|
+
#
|
32
|
+
# - c.agent.host
|
33
|
+
# - DD_AGENT_HOST
|
34
|
+
# - c.agent.port
|
35
|
+
# - DD_AGENT_PORT
|
36
|
+
#
|
37
|
+
# However, agentless resolver does respect the timeout specified via
|
38
|
+
# c.agent.timeout_seconds or DD_TRACE_AGENT_TIMEOUT_SECONDS.
|
39
|
+
class AgentlessSettingsResolver < AgentSettingsResolver
|
40
|
+
# To avoid coupling this class to telemetry, the URL override is
|
41
|
+
# taken here as a parameter instead of being read out of
|
42
|
+
# c.telemetry.agentless_url_override. For the same reason, the
|
43
|
+
# +url_override_source+ parameter should be set to the string
|
44
|
+
# "c.telemetry.agentless_url_override".
|
45
|
+
def self.call(settings, host_prefix:, url_override: nil, url_override_source: nil, logger: Datadog.logger)
|
46
|
+
new(
|
47
|
+
settings,
|
48
|
+
host_prefix: host_prefix,
|
49
|
+
url_override: url_override,
|
50
|
+
url_override_source: url_override_source,
|
51
|
+
logger: logger
|
52
|
+
).send(:call)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
attr_reader \
|
58
|
+
:host_prefix,
|
59
|
+
:url_override,
|
60
|
+
:url_override_source
|
61
|
+
|
62
|
+
def initialize(settings, host_prefix:, url_override: nil, url_override_source: nil, logger: Datadog.logger)
|
63
|
+
if url_override && url_override_source.nil?
|
64
|
+
raise ArgumentError, 'url_override_source must be provided when url_override is provided'
|
65
|
+
end
|
66
|
+
|
67
|
+
super(settings, logger: logger)
|
68
|
+
|
69
|
+
@host_prefix = host_prefix
|
70
|
+
@url_override = url_override
|
71
|
+
@url_override_source = url_override_source
|
72
|
+
end
|
73
|
+
|
74
|
+
def hostname
|
75
|
+
if should_use_uds?
|
76
|
+
nil
|
77
|
+
else
|
78
|
+
configured_hostname || "#{host_prefix}.#{settings.site}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def configured_hostname
|
83
|
+
return @configured_hostname if defined?(@configured_hostname)
|
84
|
+
|
85
|
+
if should_use_uds?
|
86
|
+
nil
|
87
|
+
else
|
88
|
+
@configured_hostname = (parsed_url.hostname if parsed_url)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def configured_port
|
93
|
+
return @configured_port if defined?(@configured_port)
|
94
|
+
|
95
|
+
@configured_port = (parsed_url.port if parsed_url)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Note that this method should always return true or false
|
99
|
+
def ssl?
|
100
|
+
if configured_hostname
|
101
|
+
configured_ssl || false
|
102
|
+
else
|
103
|
+
if should_use_uds?
|
104
|
+
false
|
105
|
+
else
|
106
|
+
# If no hostname is specified, we are communicating with the
|
107
|
+
# default Datadog intake, which uses TLS.
|
108
|
+
true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Note that this method can return nil
|
114
|
+
def configured_ssl
|
115
|
+
return @configured_ssl if defined?(@configured_ssl)
|
116
|
+
|
117
|
+
@configured_ssl = (parsed_url_ssl? if parsed_url)
|
118
|
+
end
|
119
|
+
|
120
|
+
def port
|
121
|
+
if configured_port
|
122
|
+
configured_port
|
123
|
+
else
|
124
|
+
if should_use_uds?
|
125
|
+
nil
|
126
|
+
else
|
127
|
+
# If no hostname is specified, we are communicating with the
|
128
|
+
# default Datadog intake, which exists on port 443.
|
129
|
+
443
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def mixed_http_and_uds
|
135
|
+
false
|
136
|
+
end
|
137
|
+
|
138
|
+
def configured_uds_path
|
139
|
+
return @configured_uds_path if defined?(@configured_uds_path)
|
140
|
+
|
141
|
+
parsed_url_uds_path
|
142
|
+
end
|
143
|
+
|
144
|
+
def can_use_uds?
|
145
|
+
# While in theory agentless transport could communicate via UDS,
|
146
|
+
# in practice "agentless" means we are communicating with Datadog
|
147
|
+
# infrastructure which is always remote.
|
148
|
+
# Permit UDS for proxy usage?
|
149
|
+
!configured_uds_path.nil?
|
150
|
+
end
|
151
|
+
|
152
|
+
def parsed_url
|
153
|
+
return @parsed_url if defined?(@parsed_url)
|
154
|
+
|
155
|
+
@parsed_url =
|
156
|
+
if @url_override
|
157
|
+
parsed = URI.parse(@url_override)
|
158
|
+
|
159
|
+
# Agentless URL should never refer to a UDS?
|
160
|
+
if http_scheme?(parsed) || unix_scheme?(parsed)
|
161
|
+
parsed
|
162
|
+
else
|
163
|
+
log_warning(
|
164
|
+
"Invalid URI scheme '#{parsed.scheme}' for #{url_override_source}. " \
|
165
|
+
"Ignoring the contents of #{url_override_source}."
|
166
|
+
)
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# rubocop:enable Style/*
|
@@ -14,9 +14,11 @@ require_relative '../../tracing/component'
|
|
14
14
|
require_relative '../../profiling/component'
|
15
15
|
require_relative '../../appsec/component'
|
16
16
|
require_relative '../../di/component'
|
17
|
+
require_relative '../../error_tracking/component'
|
17
18
|
require_relative '../crashtracking/component'
|
18
19
|
|
19
20
|
require_relative '../environment/agent_info'
|
21
|
+
require_relative '../process_discovery'
|
20
22
|
|
21
23
|
module Datadog
|
22
24
|
module Core
|
@@ -26,12 +28,12 @@ module Datadog
|
|
26
28
|
class << self
|
27
29
|
include Datadog::Tracing::Component
|
28
30
|
|
29
|
-
def build_health_metrics(settings, logger)
|
31
|
+
def build_health_metrics(settings, logger, telemetry)
|
30
32
|
settings = settings.health_metrics
|
31
33
|
options = { enabled: settings.enabled }
|
32
34
|
options[:statsd] = settings.statsd unless settings.statsd.nil?
|
33
35
|
|
34
|
-
Core::Diagnostics::Health::Metrics.new(logger: logger, **options)
|
36
|
+
Core::Diagnostics::Health::Metrics.new(telemetry: telemetry, logger: logger, **options)
|
35
37
|
end
|
36
38
|
|
37
39
|
def build_logger(settings)
|
@@ -41,24 +43,24 @@ module Datadog
|
|
41
43
|
logger
|
42
44
|
end
|
43
45
|
|
44
|
-
def build_runtime_metrics(settings, logger)
|
46
|
+
def build_runtime_metrics(settings, logger, telemetry)
|
45
47
|
options = { enabled: settings.runtime_metrics.enabled }
|
46
48
|
options[:statsd] = settings.runtime_metrics.statsd unless settings.runtime_metrics.statsd.nil?
|
47
49
|
options[:services] = [settings.service] unless settings.service.nil?
|
48
50
|
options[:experimental_runtime_id_enabled] = settings.runtime_metrics.experimental_runtime_id_enabled
|
49
51
|
|
50
|
-
Core::Runtime::Metrics.new(logger: logger, **options)
|
52
|
+
Core::Runtime::Metrics.new(logger: logger, telemetry: telemetry, **options)
|
51
53
|
end
|
52
54
|
|
53
|
-
def build_runtime_metrics_worker(settings, logger)
|
55
|
+
def build_runtime_metrics_worker(settings, logger, telemetry)
|
54
56
|
# NOTE: Should we just ignore building the worker if its not enabled?
|
55
57
|
options = settings.runtime_metrics.opts.merge(
|
56
58
|
enabled: settings.runtime_metrics.enabled,
|
57
|
-
metrics: build_runtime_metrics(settings, logger),
|
59
|
+
metrics: build_runtime_metrics(settings, logger, telemetry),
|
58
60
|
logger: logger,
|
59
61
|
)
|
60
62
|
|
61
|
-
Core::Workers::RuntimeMetrics.new(options)
|
63
|
+
Core::Workers::RuntimeMetrics.new(telemetry: telemetry, **options)
|
62
64
|
end
|
63
65
|
|
64
66
|
def build_telemetry(settings, agent_settings, logger)
|
@@ -68,7 +70,7 @@ module Datadog
|
|
68
70
|
def build_crashtracker(settings, agent_settings, logger:)
|
69
71
|
return unless settings.crashtracking.enabled
|
70
72
|
|
71
|
-
if (libdatadog_api_failure = Datadog::Core::
|
73
|
+
if (libdatadog_api_failure = Datadog::Core::LIBDATADOG_API_FAILURE)
|
72
74
|
logger.debug("Cannot enable crashtracking: #{libdatadog_api_failure}")
|
73
75
|
return
|
74
76
|
end
|
@@ -88,6 +90,7 @@ module Datadog
|
|
88
90
|
:telemetry,
|
89
91
|
:tracer,
|
90
92
|
:crashtracker,
|
93
|
+
:error_tracking,
|
91
94
|
:dynamic_instrumentation,
|
92
95
|
:appsec,
|
93
96
|
:agent_info
|
@@ -118,11 +121,14 @@ module Datadog
|
|
118
121
|
)
|
119
122
|
@environment_logger_extra.merge!(profiler_logger_extra) if profiler_logger_extra
|
120
123
|
|
121
|
-
@runtime_metrics = self.class.build_runtime_metrics_worker(settings, @logger)
|
122
|
-
@health_metrics = self.class.build_health_metrics(settings, @logger)
|
124
|
+
@runtime_metrics = self.class.build_runtime_metrics_worker(settings, @logger, telemetry)
|
125
|
+
@health_metrics = self.class.build_health_metrics(settings, @logger, telemetry)
|
123
126
|
@appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
|
124
127
|
@dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
|
128
|
+
@error_tracking = Datadog::ErrorTracking::Component.build(settings, @tracer, @logger)
|
125
129
|
@environment_logger_extra[:dynamic_instrumentation_enabled] = !!@dynamic_instrumentation
|
130
|
+
# TODO: Re-enable this once we have updated libdatadog to 17.1
|
131
|
+
# @process_discovery_fd = Core::ProcessDiscovery.get_and_store_metadata(settings, @logger)
|
126
132
|
|
127
133
|
self.class.configure_tracing(settings)
|
128
134
|
end
|
@@ -203,6 +209,9 @@ module Datadog
|
|
203
209
|
# enqueue closing event before stopping telemetry so it will be send out on shutdown
|
204
210
|
telemetry.emit_closing! unless replacement
|
205
211
|
telemetry.stop!
|
212
|
+
|
213
|
+
# TODO: Re-enable this once we have updated libdatadog to 17.1
|
214
|
+
# Core::ProcessDiscovery._native_close_tracer_memfd(@process_discovery_fd, @logger) if @process_discovery_fd
|
206
215
|
end
|
207
216
|
end
|
208
217
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'stable_config'
|
3
4
|
require_relative '../utils/safe_dup'
|
4
5
|
|
5
6
|
module Datadog
|
@@ -32,17 +33,25 @@ module Datadog
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# Remote configuration provided through the Datadog app.
|
35
|
-
REMOTE_CONFIGURATION = Value.new(
|
36
|
+
REMOTE_CONFIGURATION = Value.new(5, :remote_configuration).freeze
|
36
37
|
|
37
38
|
# Configuration provided in Ruby code, in this same process
|
38
|
-
|
39
|
-
|
39
|
+
PROGRAMMATIC = Value.new(4, :programmatic).freeze
|
40
|
+
|
41
|
+
# Configuration provided by fleet managed stable config
|
42
|
+
FLEET_STABLE = Value.new(3, :fleet_stable).freeze
|
43
|
+
|
44
|
+
# Configuration provided via environment variable
|
45
|
+
ENVIRONMENT = Value.new(2, :environment).freeze
|
46
|
+
|
47
|
+
# Configuration provided by local stable config file
|
48
|
+
LOCAL_STABLE = Value.new(1, :local_stable).freeze
|
40
49
|
|
41
50
|
# Configuration that comes from default values
|
42
51
|
DEFAULT = Value.new(0, :default).freeze
|
43
52
|
|
44
53
|
# All precedences, sorted from highest to lowest
|
45
|
-
LIST = [REMOTE_CONFIGURATION, PROGRAMMATIC, DEFAULT].sort.reverse.freeze
|
54
|
+
LIST = [REMOTE_CONFIGURATION, PROGRAMMATIC, FLEET_STABLE, ENVIRONMENT, LOCAL_STABLE, DEFAULT].sort.reverse.freeze
|
46
55
|
end
|
47
56
|
|
48
57
|
def initialize(definition, context)
|
@@ -118,11 +127,17 @@ module Datadog
|
|
118
127
|
end
|
119
128
|
|
120
129
|
def get
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
130
|
+
unless @is_set
|
131
|
+
# Ensures that both the default value and the environment value are set.
|
132
|
+
# This approach handles scenarios where an environment value is unset
|
133
|
+
# by falling back to the default value consistently.
|
134
|
+
set_default_value
|
135
|
+
set_customer_stable_config_value
|
136
|
+
set_env_value
|
137
|
+
set_fleet_stable_config_value
|
125
138
|
end
|
139
|
+
|
140
|
+
@value
|
126
141
|
end
|
127
142
|
|
128
143
|
def reset
|
@@ -192,7 +207,7 @@ module Datadog
|
|
192
207
|
when :bool
|
193
208
|
string_value = value.strip
|
194
209
|
string_value = string_value.downcase
|
195
|
-
string_value == 'true' || string_value == '1'
|
210
|
+
string_value == 'true' || string_value == '1'
|
196
211
|
when :string, NilClass
|
197
212
|
value
|
198
213
|
else
|
@@ -256,7 +271,8 @@ module Datadog
|
|
256
271
|
when NilClass
|
257
272
|
true # No validation is performed when option is typeless
|
258
273
|
else
|
259
|
-
raise
|
274
|
+
raise InvalidDefinitionError,
|
275
|
+
"The option #{@definition.name} is using an unsupported type option `#{@definition.type}`"
|
260
276
|
end
|
261
277
|
end
|
262
278
|
|
@@ -269,7 +285,7 @@ module Datadog
|
|
269
285
|
@resolved_env = resolved_env
|
270
286
|
# Store original value to ensure we can always safely call `#internal_set`
|
271
287
|
# when restoring a value from `@value_per_precedence`, and we are only running `definition.setter`
|
272
|
-
# on the original value, not on a
|
288
|
+
# on the original value, not on a value that has already been processed by `definition.setter`.
|
273
289
|
@value_per_precedence[precedence] = value
|
274
290
|
context_exec(v, old_value, precedence, &definition.after_set) if definition.after_set
|
275
291
|
end
|
@@ -283,39 +299,59 @@ module Datadog
|
|
283
299
|
@context.instance_eval(&block)
|
284
300
|
end
|
285
301
|
|
286
|
-
def
|
302
|
+
def set_default_value
|
303
|
+
set(default_value, precedence: Precedence::DEFAULT)
|
304
|
+
end
|
305
|
+
|
306
|
+
def set_env_value
|
307
|
+
value, resolved_env = get_value_and_resolved_env_from(ENV)
|
308
|
+
set(value, precedence: Precedence::ENVIRONMENT, resolved_env: resolved_env) unless value.nil?
|
309
|
+
end
|
310
|
+
|
311
|
+
def set_customer_stable_config_value
|
312
|
+
customer_config = StableConfig.configuration[:local]
|
313
|
+
return if customer_config.nil?
|
314
|
+
|
315
|
+
value, resolved_env = get_value_and_resolved_env_from(customer_config, source: 'local stable config')
|
316
|
+
set(value, precedence: Precedence::LOCAL_STABLE, resolved_env: resolved_env) unless value.nil?
|
317
|
+
end
|
318
|
+
|
319
|
+
def set_fleet_stable_config_value
|
320
|
+
fleet_config = StableConfig.configuration[:fleet]
|
321
|
+
return if fleet_config.nil?
|
322
|
+
|
323
|
+
value, resolved_env = get_value_and_resolved_env_from(fleet_config, source: 'fleet stable config')
|
324
|
+
set(value, precedence: Precedence::FLEET_STABLE, resolved_env: resolved_env) unless value.nil?
|
325
|
+
end
|
326
|
+
|
327
|
+
def get_value_and_resolved_env_from(env_vars, source: 'environment variable')
|
287
328
|
value = nil
|
288
|
-
precedence = nil
|
289
329
|
resolved_env = nil
|
290
330
|
|
291
331
|
if definition.env
|
292
332
|
Array(definition.env).each do |env|
|
293
|
-
next if
|
333
|
+
next if env_vars[env].nil?
|
294
334
|
|
295
335
|
resolved_env = env
|
296
|
-
value = coerce_env_variable(
|
297
|
-
precedence = Precedence::PROGRAMMATIC
|
336
|
+
value = coerce_env_variable(env_vars[env])
|
298
337
|
break
|
299
338
|
end
|
300
339
|
end
|
301
340
|
|
302
|
-
if value.nil? && definition.deprecated_env &&
|
341
|
+
if value.nil? && definition.deprecated_env && env_vars[definition.deprecated_env]
|
303
342
|
resolved_env = definition.deprecated_env
|
304
|
-
value = coerce_env_variable(
|
305
|
-
precedence = Precedence::PROGRAMMATIC
|
343
|
+
value = coerce_env_variable(env_vars[definition.deprecated_env])
|
306
344
|
|
307
345
|
Datadog::Core.log_deprecation do
|
308
|
-
"#{definition.deprecated_env}
|
346
|
+
"#{definition.deprecated_env} #{source} is deprecated, use #{definition.env} instead."
|
309
347
|
end
|
310
348
|
end
|
311
349
|
|
312
|
-
|
313
|
-
|
314
|
-
set(option_value, precedence: precedence || Precedence::DEFAULT, resolved_env: resolved_env)
|
350
|
+
[value, resolved_env]
|
315
351
|
rescue ArgumentError
|
316
352
|
raise ArgumentError,
|
317
|
-
"Expected
|
318
|
-
"but '#{
|
353
|
+
"Expected #{source} #{resolved_env} to be a #{@definition.type}, " \
|
354
|
+
"but '#{env_vars[resolved_env]}' was provided"
|
319
355
|
end
|
320
356
|
|
321
357
|
# Anchor object that represents a value that is not set.
|
@@ -888,6 +888,16 @@ module Datadog
|
|
888
888
|
o.env Core::Telemetry::Ext::ENV_LOG_COLLECTION
|
889
889
|
o.default true
|
890
890
|
end
|
891
|
+
|
892
|
+
# For internal use only.
|
893
|
+
# Enables telemetry debugging through the Datadog platform.
|
894
|
+
#
|
895
|
+
# @default `false`.
|
896
|
+
# @return [Boolean]
|
897
|
+
option :debug do |o|
|
898
|
+
o.type :bool
|
899
|
+
o.default false
|
900
|
+
end
|
891
901
|
end
|
892
902
|
|
893
903
|
# Remote configuration
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Core
|
5
|
+
module Configuration
|
6
|
+
# Import config from config files (fleet automation)
|
7
|
+
module StableConfig
|
8
|
+
def self.extract_configuration
|
9
|
+
if (libdatadog_api_failure = Datadog::Core::LIBDATADOG_API_FAILURE)
|
10
|
+
Datadog.config_init_logger.debug("Cannot enable stable config: #{libdatadog_api_failure}")
|
11
|
+
return {}
|
12
|
+
end
|
13
|
+
Configurator.new.get
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configuration
|
17
|
+
# @configuration ||= StableConfig.extract_configuration # TODO: After libdatadog 17.1 release, uncomment this line
|
18
|
+
@configuration ||= {} # TODO: After libdatadog 17.1 release, delete this line
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -172,6 +172,10 @@ module Datadog
|
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
175
|
+
def config_init_logger
|
176
|
+
configuration? ? logger : logger_without_configuration
|
177
|
+
end
|
178
|
+
|
175
179
|
# Gracefully shuts down all components.
|
176
180
|
#
|
177
181
|
# Components will still respond to method calls as usual,
|
@@ -244,6 +248,10 @@ module Datadog
|
|
244
248
|
end
|
245
249
|
end
|
246
250
|
|
251
|
+
def configuration?
|
252
|
+
(defined?(@configuration) && @configuration) != nil
|
253
|
+
end
|
254
|
+
|
247
255
|
def components?
|
248
256
|
# This does not need to grab the COMPONENTS_READ_LOCK because it's not returning the components
|
249
257
|
(defined?(@components) && @components) != nil
|
@@ -274,6 +282,7 @@ module Datadog
|
|
274
282
|
def logger_without_components
|
275
283
|
# Use default logger without initializing components.
|
276
284
|
# This enables logging during initialization, otherwise we'd run into deadlocks.
|
285
|
+
|
277
286
|
@temp_logger ||= begin
|
278
287
|
logger = configuration.logger.instance || Core::Logger.new($stdout)
|
279
288
|
logger.level = configuration.diagnostics.debug ? ::Logger::DEBUG : configuration.logger.level
|
@@ -281,6 +290,21 @@ module Datadog
|
|
281
290
|
end
|
282
291
|
end
|
283
292
|
|
293
|
+
def logger_without_configuration
|
294
|
+
# There's rare cases where we need to use logger during configuration initialization,
|
295
|
+
# such as reading stable config. In this case we cannot access configuration.
|
296
|
+
|
297
|
+
@temp_config_logger ||= begin
|
298
|
+
debug_env_value = ENV[Ext::Diagnostics::ENV_DEBUG_ENABLED]&.strip&.downcase
|
299
|
+
debug_value = debug_env_value == 'true' || debug_env_value == '1'
|
300
|
+
|
301
|
+
logger = Core::Logger.new($stdout)
|
302
|
+
# We cannot access config and the default level is INFO, so we need to set the level manually
|
303
|
+
logger.level = debug_value ? ::Logger::DEBUG : ::Logger::INFO
|
304
|
+
logger
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
284
308
|
# Called from our at_exit hook whenever there was a pending Interrupt exception (e.g. typically due to ctrl+c)
|
285
309
|
# to print a nice message whenever we're taking a bit longer than usual to finish the process.
|
286
310
|
def handle_interrupt_shutdown!
|
@@ -18,14 +18,6 @@ module Datadog
|
|
18
18
|
#
|
19
19
|
# Methods prefixed with _native_ are implemented in `crashtracker.c`
|
20
20
|
class Component
|
21
|
-
LIBDATADOG_API_FAILURE =
|
22
|
-
begin
|
23
|
-
require "libdatadog_api.#{RUBY_VERSION[/\d+.\d+/]}_#{RUBY_PLATFORM}"
|
24
|
-
nil
|
25
|
-
rescue LoadError => e
|
26
|
-
e.message
|
27
|
-
end
|
28
|
-
|
29
21
|
ONLY_ONCE = Core::Utils::OnlyOnce.new
|
30
22
|
|
31
23
|
def self.build(settings, agent_settings, logger:)
|
@@ -71,7 +63,7 @@ module Datadog
|
|
71
63
|
# Must NOT reference `self` here, as only the first instance will
|
72
64
|
# be captured by the ONLY_ONCE and we want to pick the latest active one
|
73
65
|
# (which may have different tags or agent config)
|
74
|
-
Datadog.send(:components)
|
66
|
+
Datadog.send(:components, allow_initialization: false)&.crashtracker&.update_on_fork
|
75
67
|
end
|
76
68
|
end
|
77
69
|
end
|
@@ -21,9 +21,10 @@ module Datadog
|
|
21
21
|
extend Options
|
22
22
|
extend Helpers
|
23
23
|
|
24
|
-
attr_reader :statsd, :logger
|
24
|
+
attr_reader :statsd, :logger, :telemetry
|
25
25
|
|
26
|
-
def initialize(logger: Datadog.logger, statsd: nil, enabled: true, **_)
|
26
|
+
def initialize(telemetry:, logger: Datadog.logger, statsd: nil, enabled: true, **_)
|
27
|
+
@telemetry = telemetry
|
27
28
|
@logger = logger
|
28
29
|
@statsd =
|
29
30
|
if supported?
|
@@ -102,7 +103,7 @@ module Datadog
|
|
102
103
|
logger.error(
|
103
104
|
"Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
104
105
|
)
|
105
|
-
|
106
|
+
telemetry.report(e, description: 'Failed to send count stat')
|
106
107
|
end
|
107
108
|
|
108
109
|
def distribution(stat, value = nil, options = nil, &block)
|
@@ -116,7 +117,7 @@ module Datadog
|
|
116
117
|
logger.error(
|
117
118
|
"Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
118
119
|
)
|
119
|
-
|
120
|
+
telemetry.report(e, description: 'Failed to send distribution stat')
|
120
121
|
end
|
121
122
|
|
122
123
|
def increment(stat, options = nil)
|
@@ -129,7 +130,7 @@ module Datadog
|
|
129
130
|
logger.error(
|
130
131
|
"Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
131
132
|
)
|
132
|
-
|
133
|
+
telemetry.report(e, description: 'Failed to send increment stat')
|
133
134
|
end
|
134
135
|
|
135
136
|
def gauge(stat, value = nil, options = nil, &block)
|
@@ -143,7 +144,7 @@ module Datadog
|
|
143
144
|
logger.error(
|
144
145
|
"Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
145
146
|
)
|
146
|
-
|
147
|
+
telemetry.report(e, description: 'Failed to send gauge stat')
|
147
148
|
end
|
148
149
|
|
149
150
|
def time(stat, options = nil)
|
@@ -163,7 +164,7 @@ module Datadog
|
|
163
164
|
logger.error(
|
164
165
|
"Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
165
166
|
)
|
166
|
-
|
167
|
+
telemetry.report(e, description: 'Failed to send time stat')
|
167
168
|
end
|
168
169
|
end
|
169
170
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Core
|
5
|
+
# Class used to store tracer metadata in a native file descriptor.
|
6
|
+
class ProcessDiscovery
|
7
|
+
def self.get_and_store_metadata(settings, logger)
|
8
|
+
if (libdatadog_api_failure = Datadog::Core::LIBDATADOG_API_FAILURE)
|
9
|
+
logger.debug("Cannot enable process discovery: #{libdatadog_api_failure}")
|
10
|
+
return
|
11
|
+
end
|
12
|
+
metadata = get_metadata(settings)
|
13
|
+
_native_store_tracer_metadata(logger, **metadata)
|
14
|
+
end
|
15
|
+
|
16
|
+
# According to the RFC, runtime_id, service_name, service_env, service_version are optional.
|
17
|
+
# In the C method exposed by ddcommon, memfd_create replaces empty strings by None for these fields.
|
18
|
+
private_class_method def self.get_metadata(settings)
|
19
|
+
{
|
20
|
+
schema_version: 1,
|
21
|
+
runtime_id: Core::Environment::Identity.id,
|
22
|
+
tracer_language: Core::Environment::Identity.lang,
|
23
|
+
tracer_version: Core::Environment::Identity.gem_datadog_version_semver2,
|
24
|
+
hostname: Core::Environment::Socket.hostname,
|
25
|
+
service_name: settings.service || '',
|
26
|
+
service_env: settings.env || '',
|
27
|
+
service_version: settings.version || ''
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|