datadog 2.15.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 +46 -2
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.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/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 +7 -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/recommended.json +1344 -0
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1344 -0
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +11 -4
- 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 +1 -1
- 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 +85 -95
- 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 +14 -13
- 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/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/request.rb +3 -3
- 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/remote.rb +2 -0
- 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/exporter.rb +1 -1
- data/lib/datadog/tracing/analytics.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/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_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 +34 -8
- 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
@@ -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
|
@@ -140,6 +140,13 @@ module Datadog
|
|
140
140
|
"ruby.gem.libdatadog.platform:#{gem_spec('libdatadog').platform}",
|
141
141
|
]
|
142
142
|
|
143
|
+
if (git_repository_url = Core::Environment::Git.git_repository_url)
|
144
|
+
client_tracer_tags << "git.repository_url:#{git_repository_url}"
|
145
|
+
end
|
146
|
+
if (git_commit_sha = Core::Environment::Git.git_commit_sha)
|
147
|
+
client_tracer_tags << "git.commit.sha:#{git_commit_sha}"
|
148
|
+
end
|
149
|
+
|
143
150
|
client_tracer = {
|
144
151
|
runtime_id: Core::Environment::Identity.id,
|
145
152
|
language: Core::Environment::Identity.lang,
|
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
require_relative 'emitter'
|
4
4
|
require_relative 'event'
|
5
|
-
require_relative 'http/transport'
|
6
5
|
require_relative 'metrics_manager'
|
7
6
|
require_relative 'worker'
|
8
7
|
require_relative 'logging'
|
8
|
+
require_relative 'transport/http'
|
9
9
|
|
10
10
|
require_relative '../configuration/ext'
|
11
|
+
require_relative '../configuration/agentless_settings_resolver'
|
11
12
|
require_relative '../utils/forking'
|
12
13
|
|
13
14
|
module Datadog
|
@@ -16,7 +17,7 @@ module Datadog
|
|
16
17
|
# Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
|
17
18
|
# Note: Telemetry does not spawn its worker thread in fork processes, thus no telemetry is sent in forked processes.
|
18
19
|
class Component
|
19
|
-
attr_reader :enabled, :logger
|
20
|
+
attr_reader :enabled, :logger, :transport, :worker
|
20
21
|
|
21
22
|
include Core::Utils::Forking
|
22
23
|
include Telemetry::Logging
|
@@ -25,89 +26,87 @@ module Datadog
|
|
25
26
|
enabled = settings.telemetry.enabled
|
26
27
|
agentless_enabled = settings.telemetry.agentless_enabled
|
27
28
|
|
28
|
-
if !agentless_enabled && agent_settings.adapter != Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
29
|
-
enabled = false
|
30
|
-
logger.debug { "Telemetry disabled. Agent network adapter not supported: #{agent_settings.adapter}" }
|
31
|
-
end
|
32
|
-
|
33
29
|
if agentless_enabled && settings.api_key.nil?
|
34
30
|
enabled = false
|
35
|
-
logger.debug { 'Telemetry disabled. Agentless telemetry requires
|
31
|
+
logger.debug { 'Telemetry disabled. Agentless telemetry requires a DD_API_KEY variable to be set.' }
|
36
32
|
end
|
37
33
|
|
38
|
-
transport = if agentless_enabled
|
39
|
-
Datadog::Core::Telemetry::Http::Transport.build_agentless_transport(
|
40
|
-
api_key: settings.api_key,
|
41
|
-
dd_site: settings.site,
|
42
|
-
url_override: settings.telemetry.agentless_url_override
|
43
|
-
)
|
44
|
-
else
|
45
|
-
Datadog::Core::Telemetry::Http::Transport.build_agent_transport(agent_settings)
|
46
|
-
end
|
47
|
-
|
48
34
|
Telemetry::Component.new(
|
49
|
-
|
35
|
+
settings: settings,
|
36
|
+
agent_settings: agent_settings,
|
50
37
|
enabled: enabled,
|
51
|
-
metrics_enabled: enabled && settings.telemetry.metrics_enabled,
|
52
|
-
heartbeat_interval_seconds: settings.telemetry.heartbeat_interval_seconds,
|
53
|
-
metrics_aggregation_interval_seconds: settings.telemetry.metrics_aggregation_interval_seconds,
|
54
|
-
dependency_collection: settings.telemetry.dependency_collection,
|
55
38
|
logger: logger,
|
56
|
-
shutdown_timeout_seconds: settings.telemetry.shutdown_timeout_seconds,
|
57
|
-
log_collection_enabled: settings.telemetry.log_collection_enabled
|
58
39
|
)
|
59
40
|
end
|
60
41
|
|
61
42
|
# @param enabled [Boolean] Determines whether telemetry events should be sent to the API
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
# @param [Boolean] dependency_collection Whether to send the `app-dependencies-loaded` event
|
66
|
-
def initialize(
|
67
|
-
heartbeat_interval_seconds:,
|
68
|
-
metrics_aggregation_interval_seconds:,
|
69
|
-
dependency_collection:,
|
43
|
+
def initialize( # rubocop: disable Metrics/MethodLength
|
44
|
+
settings:,
|
45
|
+
agent_settings:,
|
70
46
|
logger:,
|
71
|
-
|
72
|
-
shutdown_timeout_seconds:,
|
73
|
-
enabled: true,
|
74
|
-
metrics_enabled: true,
|
75
|
-
log_collection_enabled: true
|
47
|
+
enabled:
|
76
48
|
)
|
77
49
|
@enabled = enabled
|
78
|
-
@log_collection_enabled = log_collection_enabled
|
50
|
+
@log_collection_enabled = settings.telemetry.log_collection_enabled
|
79
51
|
@logger = logger
|
80
52
|
|
81
53
|
@metrics_manager = MetricsManager.new(
|
82
|
-
enabled: enabled && metrics_enabled,
|
83
|
-
aggregation_interval: metrics_aggregation_interval_seconds
|
54
|
+
enabled: @enabled && settings.telemetry.metrics_enabled,
|
55
|
+
aggregation_interval: settings.telemetry.metrics_aggregation_interval_seconds,
|
84
56
|
)
|
85
57
|
|
58
|
+
@stopped = false
|
59
|
+
|
60
|
+
return unless @enabled
|
61
|
+
|
62
|
+
@transport = if settings.telemetry.agentless_enabled
|
63
|
+
agent_settings = Core::Configuration::AgentlessSettingsResolver.call(
|
64
|
+
settings,
|
65
|
+
host_prefix: 'instrumentation-telemetry-intake',
|
66
|
+
url_override: settings.telemetry.agentless_url_override,
|
67
|
+
url_override_source: 'c.telemetry.agentless_url_override',
|
68
|
+
logger: logger,
|
69
|
+
)
|
70
|
+
Telemetry::Transport::HTTP.agentless_telemetry(
|
71
|
+
agent_settings: agent_settings,
|
72
|
+
logger: logger,
|
73
|
+
# api_key should have already validated to be
|
74
|
+
# not nil by +build+ method above.
|
75
|
+
api_key: settings.api_key,
|
76
|
+
)
|
77
|
+
else
|
78
|
+
Telemetry::Transport::HTTP.agent_telemetry(
|
79
|
+
agent_settings: agent_settings, logger: logger,
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
86
83
|
@worker = Telemetry::Worker.new(
|
87
84
|
enabled: @enabled,
|
88
|
-
heartbeat_interval_seconds: heartbeat_interval_seconds,
|
89
|
-
metrics_aggregation_interval_seconds: metrics_aggregation_interval_seconds,
|
90
|
-
emitter: Emitter.new(
|
85
|
+
heartbeat_interval_seconds: settings.telemetry.heartbeat_interval_seconds,
|
86
|
+
metrics_aggregation_interval_seconds: settings.telemetry.metrics_aggregation_interval_seconds,
|
87
|
+
emitter: Emitter.new(
|
88
|
+
@transport,
|
89
|
+
logger: @logger,
|
90
|
+
debug: settings.telemetry.debug,
|
91
|
+
),
|
91
92
|
metrics_manager: @metrics_manager,
|
92
|
-
dependency_collection: dependency_collection,
|
93
|
+
dependency_collection: settings.telemetry.dependency_collection,
|
93
94
|
logger: logger,
|
94
|
-
shutdown_timeout: shutdown_timeout_seconds
|
95
|
+
shutdown_timeout: settings.telemetry.shutdown_timeout_seconds,
|
95
96
|
)
|
96
97
|
|
97
|
-
@stopped = false
|
98
|
-
|
99
98
|
@worker.start
|
100
99
|
end
|
101
100
|
|
102
101
|
def disable!
|
103
102
|
@enabled = false
|
104
|
-
@worker
|
103
|
+
@worker&.enabled = false
|
105
104
|
end
|
106
105
|
|
107
106
|
def stop!
|
108
107
|
return if @stopped
|
109
108
|
|
110
|
-
@worker
|
109
|
+
@worker&.stop(true)
|
111
110
|
@stopped = true
|
112
111
|
end
|
113
112
|
|
@@ -129,6 +128,17 @@ module Datadog
|
|
129
128
|
@worker.enqueue(event)
|
130
129
|
end
|
131
130
|
|
131
|
+
# Wait for the worker to send out all events that have already
|
132
|
+
# been queued, up to 15 seconds. Returns whether all events have
|
133
|
+
# been flushed.
|
134
|
+
#
|
135
|
+
# @api private
|
136
|
+
def flush
|
137
|
+
return if !@enabled || forked?
|
138
|
+
|
139
|
+
@worker.flush
|
140
|
+
end
|
141
|
+
|
132
142
|
# Report configuration changes caused by Remote Configuration.
|
133
143
|
def client_configuration_change!(changes)
|
134
144
|
return if !@enabled || forked?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'request'
|
4
|
-
require_relative '
|
4
|
+
require_relative '../transport/response'
|
5
5
|
require_relative '../utils/sequence'
|
6
6
|
require_relative '../utils/forking'
|
7
7
|
|
@@ -10,26 +10,32 @@ module Datadog
|
|
10
10
|
module Telemetry
|
11
11
|
# Class that emits telemetry events
|
12
12
|
class Emitter
|
13
|
-
attr_reader :
|
13
|
+
attr_reader :transport, :logger
|
14
14
|
|
15
15
|
extend Core::Utils::Forking
|
16
16
|
|
17
|
-
# @param
|
18
|
-
#
|
19
|
-
def initialize(
|
20
|
-
@
|
17
|
+
# @param transport [Datadog::Core::Telemetry::Transport::Telemetry::Transport]
|
18
|
+
# Transport object that can be used to send telemetry requests
|
19
|
+
def initialize(transport, logger: Datadog.logger, debug: false)
|
20
|
+
@transport = transport
|
21
|
+
@logger = logger
|
22
|
+
@debug = !!debug
|
23
|
+
end
|
24
|
+
|
25
|
+
def debug?
|
26
|
+
@debug
|
21
27
|
end
|
22
28
|
|
23
29
|
# Retrieves and emits a TelemetryRequest object based on the request type specified
|
24
30
|
def request(event)
|
25
31
|
seq_id = self.class.sequence.next
|
26
|
-
payload = Request.build_payload(event, seq_id)
|
27
|
-
res = @
|
28
|
-
|
32
|
+
payload = Request.build_payload(event, seq_id, debug: debug?)
|
33
|
+
res = @transport.send_telemetry(request_type: event.type, payload: payload)
|
34
|
+
logger.debug { "Telemetry sent for event `#{event.type}` (response code: #{res.code})" }
|
29
35
|
res
|
30
36
|
rescue => e
|
31
|
-
|
32
|
-
|
37
|
+
logger.debug { "Unable to send telemetry request for event `#{event.type rescue 'unknown'}`: #{e}" }
|
38
|
+
Core::Transport::InternalErrorResponse.new(e)
|
33
39
|
end
|
34
40
|
|
35
41
|
# Initializes a Sequence object to track seq_id if not already initialized; else returns stored
|