datadog 2.10.0 → 2.12.2
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 +72 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +3 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +44 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +4 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
- data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +7 -0
- data/ext/datadog_profiling_native_extension/profiling.c +7 -0
- data/ext/libdatadog_api/crashtracker.c +4 -4
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/configuration/settings.rb +64 -11
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +23 -6
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +63 -15
- data/lib/datadog/appsec/contrib/devise/configuration.rb +76 -0
- data/lib/datadog/appsec/contrib/devise/event.rb +4 -7
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +16 -21
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +8 -15
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/devise/tracking.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +43 -0
- data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
- data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +10 -12
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rack/ext.rb +20 -0
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +84 -72
- data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -0
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +20 -25
- data/lib/datadog/appsec/contrib/rails/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +39 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +38 -49
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +0 -3
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
- data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +19 -25
- data/lib/datadog/appsec/processor/rule_merger.rb +2 -1
- data/lib/datadog/appsec/remote.rb +11 -0
- data/lib/datadog/appsec.rb +3 -0
- data/lib/datadog/core/configuration/components.rb +17 -10
- data/lib/datadog/core/configuration/ext.rb +1 -1
- data/lib/datadog/core/configuration/option_definition.rb +2 -0
- data/lib/datadog/core/configuration/settings.rb +22 -6
- data/lib/datadog/core/encoding.rb +16 -0
- data/lib/datadog/core/environment/agent_info.rb +77 -0
- data/lib/datadog/core/metrics/client.rb +9 -8
- data/lib/datadog/core/remote/client.rb +5 -4
- data/lib/datadog/core/remote/component.rb +14 -12
- data/lib/datadog/core/remote/negotiation.rb +1 -1
- data/lib/datadog/core/remote/transport/http/api.rb +13 -18
- data/lib/datadog/core/remote/transport/http/config.rb +0 -18
- data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -18
- data/lib/datadog/core/remote/transport/http.rb +6 -40
- data/lib/datadog/core/remote/transport/negotiation.rb +13 -1
- data/lib/datadog/core/remote/worker.rb +10 -7
- data/lib/datadog/core/telemetry/component.rb +5 -1
- data/lib/datadog/core/telemetry/event.rb +5 -0
- data/lib/datadog/core/telemetry/worker.rb +9 -5
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
- data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +1 -1
- data/lib/datadog/{tracing → core}/transport/http/api/spec.rb +1 -1
- data/lib/datadog/{tracing → core}/transport/http/builder.rb +37 -17
- data/lib/datadog/core/transport/http.rb +38 -0
- data/lib/datadog/core/transport/response.rb +4 -0
- data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
- data/lib/datadog/di/code_tracker.rb +15 -8
- data/lib/datadog/di/component.rb +2 -3
- data/lib/datadog/di/configuration/settings.rb +14 -0
- data/lib/datadog/di/contrib.rb +2 -0
- data/lib/datadog/di/logger.rb +30 -0
- data/lib/datadog/di/probe.rb +3 -6
- data/lib/datadog/di/probe_manager.rb +5 -2
- data/lib/datadog/di/probe_notifier_worker.rb +35 -8
- data/lib/datadog/di/remote.rb +3 -3
- data/lib/datadog/di/transport/diagnostics.rb +61 -0
- data/lib/datadog/di/transport/http/api.rb +52 -0
- data/lib/datadog/di/transport/http/client.rb +46 -0
- data/lib/datadog/di/transport/http/diagnostics.rb +92 -0
- data/lib/datadog/di/transport/http/input.rb +94 -0
- data/lib/datadog/di/transport/http.rb +105 -0
- data/lib/datadog/di/transport/input.rb +61 -0
- data/lib/datadog/di/utils.rb +91 -0
- data/lib/datadog/di.rb +5 -1
- data/lib/datadog/profiling/component.rb +2 -8
- data/lib/datadog/profiling/load_native_extension.rb +1 -33
- data/lib/datadog/tracing/component.rb +1 -0
- data/lib/datadog/tracing/configuration/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/extensions.rb +14 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
- data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
- data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
- data/lib/datadog/tracing/metadata.rb +2 -0
- data/lib/datadog/tracing/span.rb +10 -1
- data/lib/datadog/tracing/span_operation.rb +6 -1
- data/lib/datadog/tracing/sync_writer.rb +9 -4
- data/lib/datadog/tracing/tracer.rb +15 -7
- data/lib/datadog/tracing/transport/http/api.rb +11 -2
- data/lib/datadog/tracing/transport/http/traces.rb +0 -3
- data/lib/datadog/tracing/transport/http.rb +7 -31
- data/lib/datadog/tracing/transport/serializable_trace.rb +11 -5
- data/lib/datadog/tracing/transport/traces.rb +25 -8
- data/lib/datadog/tracing/workers/trace_writer.rb +10 -3
- data/lib/datadog/tracing/workers.rb +5 -4
- data/lib/datadog/tracing/writer.rb +12 -4
- data/lib/datadog/version.rb +2 -2
- metadata +37 -29
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
- data/ext/datadog_profiling_loader/extconf.rb +0 -60
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
- data/lib/datadog/appsec/contrib/patcher.rb +0 -12
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
- data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
- data/lib/datadog/appsec/reactive/engine.rb +0 -47
- data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
- data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
- data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
- data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
- data/lib/datadog/di/transport.rb +0 -79
@@ -1,35 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'gateway/middleware'
|
4
|
+
|
3
5
|
module Datadog
|
4
6
|
module AppSec
|
5
7
|
# Instrumentation for AppSec
|
6
8
|
module Instrumentation
|
7
9
|
# Instrumentation gateway implementation
|
8
10
|
class Gateway
|
9
|
-
# Instrumentation gateway middleware
|
10
|
-
class Middleware
|
11
|
-
attr_reader :key, :block
|
12
|
-
|
13
|
-
def initialize(key, &block)
|
14
|
-
@key = key
|
15
|
-
@block = block
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(stack, env)
|
19
|
-
@block.call(stack, env)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private_constant :Middleware
|
24
|
-
|
25
11
|
def initialize
|
26
12
|
@middlewares = Hash.new { |h, k| h[k] = [] }
|
13
|
+
@pushed_events = {}
|
27
14
|
end
|
28
15
|
|
16
|
+
# NOTE: Be careful with pushed names because every pushed event name
|
17
|
+
# is recorded in order to provide an ability to any subscriber
|
18
|
+
# to check wether an arbitrary event had happened.
|
19
|
+
#
|
20
|
+
# WARNING: If we start pushing generated names we should consider
|
21
|
+
# limiting the storage of pushed names.
|
29
22
|
def push(name, env, &block)
|
30
|
-
|
23
|
+
@pushed_events[name] = true
|
31
24
|
|
32
|
-
|
25
|
+
block ||= -> {}
|
26
|
+
middlewares_for_name = @middlewares[name]
|
33
27
|
|
34
28
|
return [block.call, nil] if middlewares_for_name.empty?
|
35
29
|
|
@@ -48,14 +42,15 @@ module Datadog
|
|
48
42
|
end
|
49
43
|
|
50
44
|
def watch(name, key, &block)
|
51
|
-
@middlewares[name] << Middleware.new(key, &block) unless middlewares[name].any? { |m| m.key == key }
|
45
|
+
@middlewares[name] << Middleware.new(key, &block) unless @middlewares[name].any? { |m| m.key == key }
|
52
46
|
end
|
53
47
|
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
def pushed?(name)
|
49
|
+
@pushed_events.key?(name)
|
50
|
+
end
|
57
51
|
end
|
58
52
|
|
53
|
+
# NOTE: This left as-is and will be depricated soon.
|
59
54
|
def self.gateway
|
60
55
|
@gateway ||= Gateway.new # TODO: not thread safe
|
61
56
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../instrumentation/gateway'
|
4
|
-
require_relative '../../reactive/engine'
|
5
|
-
require_relative '../reactive/set_user'
|
6
4
|
|
7
5
|
module Datadog
|
8
6
|
module AppSec
|
@@ -19,31 +17,27 @@ module Datadog
|
|
19
17
|
|
20
18
|
def watch_user_id(gateway = Instrumentation.gateway)
|
21
19
|
gateway.watch('identity.set_user', :appsec) do |stack, user|
|
22
|
-
event = nil
|
23
20
|
context = Datadog::AppSec.active_context
|
24
|
-
engine = AppSec::Reactive::Engine.new
|
25
|
-
|
26
|
-
Monitor::Reactive::SetUser.subscribe(engine, context) do |result|
|
27
|
-
if result.match?
|
28
|
-
# TODO: should this hash be an Event instance instead?
|
29
|
-
event = {
|
30
|
-
waf_result: result,
|
31
|
-
trace: context.trace,
|
32
|
-
span: context.span,
|
33
|
-
user: user,
|
34
|
-
actions: result.actions
|
35
|
-
}
|
36
|
-
|
37
|
-
# We want to keep the trace in case of security event
|
38
|
-
context.trace.keep! if context.trace
|
39
|
-
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
40
|
-
context.events << event
|
41
|
-
|
42
|
-
Datadog::AppSec::ActionsHandler.handle(result.actions)
|
43
|
-
end
|
44
|
-
end
|
45
21
|
|
46
|
-
|
22
|
+
persistent_data = {
|
23
|
+
'usr.id' => user.id
|
24
|
+
}
|
25
|
+
|
26
|
+
result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
|
27
|
+
|
28
|
+
if result.match?
|
29
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
30
|
+
|
31
|
+
context.events << {
|
32
|
+
waf_result: result,
|
33
|
+
trace: context.trace,
|
34
|
+
span: context.span,
|
35
|
+
user: user,
|
36
|
+
actions: result.actions
|
37
|
+
}
|
38
|
+
|
39
|
+
Datadog::AppSec::ActionsHandler.handle(result.actions)
|
40
|
+
end
|
47
41
|
|
48
42
|
stack.call(user)
|
49
43
|
end
|
@@ -22,7 +22,7 @@ module Datadog
|
|
22
22
|
# TODO: `processors` and `scanners` are not provided by the caller, consider removing them
|
23
23
|
def merge(
|
24
24
|
telemetry:,
|
25
|
-
rules:, data: [], overrides: [], exclusions: [], custom_rules: [],
|
25
|
+
rules:, actions: [], data: [], overrides: [], exclusions: [], custom_rules: [],
|
26
26
|
processors: nil, scanners: nil
|
27
27
|
)
|
28
28
|
processors ||= begin
|
@@ -54,6 +54,7 @@ module Datadog
|
|
54
54
|
combined_exclusions = combine_exclusions(exclusions) if exclusions.any?
|
55
55
|
combined_custom_rules = combine_custom_rules(custom_rules) if custom_rules.any?
|
56
56
|
|
57
|
+
combined_rules['actions'] = actions if actions.any?
|
57
58
|
combined_rules['rules_data'] = combined_data if combined_data
|
58
59
|
combined_rules['rules_override'] = combined_overrides if combined_overrides
|
59
60
|
combined_rules['exclusions'] = combined_exclusions if combined_exclusions
|
@@ -53,10 +53,12 @@ module Datadog
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# rubocop:disable Metrics/MethodLength
|
56
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
56
57
|
def receivers(telemetry)
|
57
58
|
return [] unless remote_features_enabled?
|
58
59
|
|
59
60
|
matcher = Core::Remote::Dispatcher::Matcher::Product.new(ASM_PRODUCTS)
|
61
|
+
# rubocop:disable Metrics/BlockLength
|
60
62
|
receiver = Core::Remote::Dispatcher::Receiver.new(matcher) do |repository, changes|
|
61
63
|
changes.each do |change|
|
62
64
|
Datadog.logger.debug { "remote config change: '#{change.path}'" }
|
@@ -67,6 +69,7 @@ module Datadog
|
|
67
69
|
data = []
|
68
70
|
overrides = []
|
69
71
|
exclusions = []
|
72
|
+
actions = []
|
70
73
|
|
71
74
|
repository.contents.each do |content|
|
72
75
|
parsed_content = parse_content(content)
|
@@ -80,6 +83,7 @@ module Datadog
|
|
80
83
|
overrides << parsed_content['rules_override'] if parsed_content['rules_override']
|
81
84
|
exclusions << parsed_content['exclusions'] if parsed_content['exclusions']
|
82
85
|
custom_rules << parsed_content['custom_rules'] if parsed_content['custom_rules']
|
86
|
+
actions.concat(parsed_content['actions']) if parsed_content['actions']
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
@@ -97,6 +101,7 @@ module Datadog
|
|
97
101
|
ruleset = AppSec::Processor::RuleMerger.merge(
|
98
102
|
rules: rules,
|
99
103
|
data: data,
|
104
|
+
actions: actions,
|
100
105
|
overrides: overrides,
|
101
106
|
exclusions: exclusions,
|
102
107
|
custom_rules: custom_rules,
|
@@ -104,11 +109,17 @@ module Datadog
|
|
104
109
|
)
|
105
110
|
|
106
111
|
Datadog::AppSec.reconfigure(ruleset: ruleset, telemetry: telemetry)
|
112
|
+
|
113
|
+
repository.contents.each do |content|
|
114
|
+
content.applied if ASM_PRODUCTS.include?(content.path.product)
|
115
|
+
end
|
107
116
|
end
|
117
|
+
# rubocop:enable Metrics/BlockLength
|
108
118
|
|
109
119
|
[receiver]
|
110
120
|
end
|
111
121
|
# rubocop:enable Metrics/MethodLength
|
122
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
112
123
|
|
113
124
|
private
|
114
125
|
|
data/lib/datadog/appsec.rb
CHANGED
@@ -68,5 +68,8 @@ require_relative 'appsec/contrib/rails/integration'
|
|
68
68
|
require_relative 'appsec/contrib/active_record/integration'
|
69
69
|
require_relative 'appsec/contrib/devise/integration'
|
70
70
|
require_relative 'appsec/contrib/graphql/integration'
|
71
|
+
require_relative 'appsec/contrib/faraday/integration'
|
72
|
+
require_relative 'appsec/contrib/excon/integration'
|
73
|
+
require_relative 'appsec/contrib/rest_client/integration'
|
71
74
|
|
72
75
|
require_relative 'appsec/autoload'
|
@@ -16,6 +16,8 @@ require_relative '../../appsec/component'
|
|
16
16
|
require_relative '../../di/component'
|
17
17
|
require_relative '../crashtracking/component'
|
18
18
|
|
19
|
+
require_relative '../environment/agent_info'
|
20
|
+
|
19
21
|
module Datadog
|
20
22
|
module Core
|
21
23
|
module Configuration
|
@@ -24,12 +26,12 @@ module Datadog
|
|
24
26
|
class << self
|
25
27
|
include Datadog::Tracing::Component
|
26
28
|
|
27
|
-
def build_health_metrics(settings)
|
29
|
+
def build_health_metrics(settings, logger)
|
28
30
|
settings = settings.health_metrics
|
29
31
|
options = { enabled: settings.enabled }
|
30
32
|
options[:statsd] = settings.statsd unless settings.statsd.nil?
|
31
33
|
|
32
|
-
Core::Diagnostics::Health::Metrics.new(**options)
|
34
|
+
Core::Diagnostics::Health::Metrics.new(logger: logger, **options)
|
33
35
|
end
|
34
36
|
|
35
37
|
def build_logger(settings)
|
@@ -39,19 +41,20 @@ module Datadog
|
|
39
41
|
logger
|
40
42
|
end
|
41
43
|
|
42
|
-
def build_runtime_metrics(settings)
|
44
|
+
def build_runtime_metrics(settings, logger)
|
43
45
|
options = { enabled: settings.runtime_metrics.enabled }
|
44
46
|
options[:statsd] = settings.runtime_metrics.statsd unless settings.runtime_metrics.statsd.nil?
|
45
47
|
options[:services] = [settings.service] unless settings.service.nil?
|
46
48
|
|
47
|
-
Core::Runtime::Metrics.new(**options)
|
49
|
+
Core::Runtime::Metrics.new(logger: logger, **options)
|
48
50
|
end
|
49
51
|
|
50
|
-
def build_runtime_metrics_worker(settings)
|
52
|
+
def build_runtime_metrics_worker(settings, logger)
|
51
53
|
# NOTE: Should we just ignore building the worker if its not enabled?
|
52
54
|
options = settings.runtime_metrics.opts.merge(
|
53
55
|
enabled: settings.runtime_metrics.enabled,
|
54
|
-
metrics: build_runtime_metrics(settings)
|
56
|
+
metrics: build_runtime_metrics(settings, logger),
|
57
|
+
logger: logger,
|
55
58
|
)
|
56
59
|
|
57
60
|
Core::Workers::RuntimeMetrics.new(options)
|
@@ -85,7 +88,8 @@ module Datadog
|
|
85
88
|
:tracer,
|
86
89
|
:crashtracker,
|
87
90
|
:dynamic_instrumentation,
|
88
|
-
:appsec
|
91
|
+
:appsec,
|
92
|
+
:agent_info
|
89
93
|
|
90
94
|
def initialize(settings)
|
91
95
|
@logger = self.class.build_logger(settings)
|
@@ -96,9 +100,12 @@ module Datadog
|
|
96
100
|
# the Core resolver from within your product/component's namespace.
|
97
101
|
agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
|
98
102
|
|
103
|
+
# Exposes agent capability information for detection by any components
|
104
|
+
@agent_info = Core::Environment::AgentInfo.new(agent_settings)
|
105
|
+
|
99
106
|
@telemetry = self.class.build_telemetry(settings, agent_settings, @logger)
|
100
107
|
|
101
|
-
@remote = Remote::Component.build(settings, agent_settings, telemetry: telemetry)
|
108
|
+
@remote = Remote::Component.build(settings, agent_settings, logger: @logger, telemetry: telemetry)
|
102
109
|
@tracer = self.class.build_tracer(settings, agent_settings, logger: @logger)
|
103
110
|
@crashtracker = self.class.build_crashtracker(settings, agent_settings, logger: @logger)
|
104
111
|
|
@@ -110,8 +117,8 @@ module Datadog
|
|
110
117
|
)
|
111
118
|
@environment_logger_extra.merge!(profiler_logger_extra) if profiler_logger_extra
|
112
119
|
|
113
|
-
@runtime_metrics = self.class.build_runtime_metrics_worker(settings)
|
114
|
-
@health_metrics = self.class.build_health_metrics(settings)
|
120
|
+
@runtime_metrics = self.class.build_runtime_metrics_worker(settings, @logger)
|
121
|
+
@health_metrics = self.class.build_health_metrics(settings, @logger)
|
115
122
|
@appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
|
116
123
|
@dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
|
117
124
|
@environment_logger_extra[:dynamic_instrumentation_enabled] = !!@dynamic_instrumentation
|
@@ -79,6 +79,8 @@ module Datadog
|
|
79
79
|
@deprecated_env = value
|
80
80
|
end
|
81
81
|
|
82
|
+
# Invoked when the option is first read, and {#env} is defined.
|
83
|
+
# The block provided is only invoked if the environment variable is present (not-nil).
|
82
84
|
def env_parser(&block)
|
83
85
|
@env_parser = block
|
84
86
|
end
|
@@ -461,15 +461,31 @@ module Datadog
|
|
461
461
|
end
|
462
462
|
end
|
463
463
|
|
464
|
-
#
|
465
|
-
#
|
466
|
-
# This is a preview feature and disabled by default. It requires Ruby 3.2+.
|
467
|
-
#
|
468
|
-
# @default `DD_PROFILING_PREVIEW_GVL_ENABLED` environment variable as a boolean, otherwise `false`
|
464
|
+
# @deprecated Use {:gvl_enabled} instead.
|
469
465
|
option :preview_gvl_enabled do |o|
|
470
466
|
o.type :bool
|
471
|
-
o.env 'DD_PROFILING_PREVIEW_GVL_ENABLED'
|
472
467
|
o.default false
|
468
|
+
o.after_set do |_, _, precedence|
|
469
|
+
unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
|
470
|
+
Datadog.logger.warn(
|
471
|
+
'The profiling.advanced.preview_gvl_enabled setting has been deprecated for removal and ' \
|
472
|
+
'no longer does anything. Please remove it from your Datadog.configure block. ' \
|
473
|
+
'GVL profiling is now controlled by the profiling.advanced.gvl_enabled setting instead.'
|
474
|
+
)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
# Controls GVL profiling. This will show when threads are waiting for GVL in the timeline view.
|
480
|
+
#
|
481
|
+
# This feature requires Ruby 3.2+.
|
482
|
+
#
|
483
|
+
# @default `DD_PROFILING_GVL_ENABLED` environment variable as a boolean, otherwise `true`
|
484
|
+
option :gvl_enabled do |o|
|
485
|
+
o.type :bool
|
486
|
+
o.deprecated_env 'DD_PROFILING_PREVIEW_GVL_ENABLED'
|
487
|
+
o.env 'DD_PROFILING_GVL_ENABLED'
|
488
|
+
o.default true
|
473
489
|
end
|
474
490
|
|
475
491
|
# Controls the smallest time period the profiler will report a thread waiting for the GVL.
|
@@ -10,6 +10,7 @@ module Datadog
|
|
10
10
|
# Encoder interface that provides the logic to encode traces and service
|
11
11
|
# @abstract
|
12
12
|
module Encoder
|
13
|
+
# :nocov:
|
13
14
|
def content_type
|
14
15
|
raise NotImplementedError
|
15
16
|
end
|
@@ -23,6 +24,13 @@ module Datadog
|
|
23
24
|
def encode(_)
|
24
25
|
raise NotImplementedError
|
25
26
|
end
|
27
|
+
|
28
|
+
# Deserializes a value serialized with {#encode}.
|
29
|
+
# This method is used for debugging purposes.
|
30
|
+
def decode(_)
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
# :nocov:
|
26
34
|
end
|
27
35
|
|
28
36
|
# Encoder for the JSON format
|
@@ -41,6 +49,10 @@ module Datadog
|
|
41
49
|
JSON.dump(obj)
|
42
50
|
end
|
43
51
|
|
52
|
+
def decode(obj)
|
53
|
+
JSON.parse(obj)
|
54
|
+
end
|
55
|
+
|
44
56
|
def join(encoded_data)
|
45
57
|
"[#{encoded_data.join(',')}]"
|
46
58
|
end
|
@@ -62,6 +74,10 @@ module Datadog
|
|
62
74
|
MessagePack.pack(obj)
|
63
75
|
end
|
64
76
|
|
77
|
+
def decode(obj)
|
78
|
+
MessagePack.unpack(obj)
|
79
|
+
end
|
80
|
+
|
65
81
|
def join(encoded_data)
|
66
82
|
packer = MessagePack::Packer.new
|
67
83
|
packer.write_array_header(encoded_data.size)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Core
|
5
|
+
module Environment
|
6
|
+
# Retrieves the agent's `/info` endpoint data.
|
7
|
+
# This data can be used to determine the capabilities of the local Datadog agent.
|
8
|
+
#
|
9
|
+
# @example Example response payload
|
10
|
+
# {
|
11
|
+
# "version" : "7.57.2",
|
12
|
+
# "git_commit" : "38ba0c7",
|
13
|
+
# "endpoints" : [ "/v0.4/traces", "/v0.4/services", "/v0.7/traces", "/v0.7/config" ],
|
14
|
+
# "client_drop_p0s" : true,
|
15
|
+
# "span_meta_structs" : true,
|
16
|
+
# "long_running_spans" : true,
|
17
|
+
# "evp_proxy_allowed_headers" : [ "Content-Type", "Accept-Encoding", "Content-Encoding", "User-Agent" ],
|
18
|
+
# "config" : {
|
19
|
+
# "default_env" : "none",
|
20
|
+
# "target_tps" : 10,
|
21
|
+
# "max_eps" : 200,
|
22
|
+
# "receiver_port" : 8126,
|
23
|
+
# "receiver_socket" : "/var/run/datadog/apm.socket",
|
24
|
+
# "connection_limit" : 0,
|
25
|
+
# "receiver_timeout" : 0,
|
26
|
+
# "max_request_bytes" : 26214400,
|
27
|
+
# "statsd_port" : 8125,
|
28
|
+
# "analyzed_spans_by_service" : { },
|
29
|
+
# "obfuscation" : {
|
30
|
+
# "elastic_search" : true,
|
31
|
+
# "mongo" : true,
|
32
|
+
# "sql_exec_plan" : false,
|
33
|
+
# "sql_exec_plan_normalize" : false,
|
34
|
+
# "http" : {
|
35
|
+
# "remove_query_string" : false,
|
36
|
+
# "remove_path_digits" : false
|
37
|
+
# },
|
38
|
+
# "remove_stack_traces" : false,
|
39
|
+
# "redis" : {
|
40
|
+
# "Enabled" : true,
|
41
|
+
# "RemoveAllArgs" : false
|
42
|
+
# },
|
43
|
+
# "memcached" : {
|
44
|
+
# "Enabled" : true,
|
45
|
+
# "KeepCommand" : false
|
46
|
+
# }
|
47
|
+
# }
|
48
|
+
# },
|
49
|
+
# "peer_tags" : null
|
50
|
+
# }
|
51
|
+
#
|
52
|
+
# @see https://github.com/DataDog/datadog-agent/blob/f07df0a3c1fca0c83b5a15f553bd994091b0c8ac/pkg/trace/api/info.go#L20
|
53
|
+
class AgentInfo
|
54
|
+
attr_reader :agent_settings
|
55
|
+
|
56
|
+
def initialize(agent_settings)
|
57
|
+
@agent_settings = agent_settings
|
58
|
+
@client = Remote::Transport::HTTP.root(agent_settings: agent_settings)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Fetches the information from the agent.
|
62
|
+
# @return [Datadog::Core::Remote::Transport::HTTP::Negotiation::Response] the response from the agent
|
63
|
+
# @return [nil] if an error occurred while fetching the information
|
64
|
+
def fetch
|
65
|
+
res = @client.send_info
|
66
|
+
return unless res.ok?
|
67
|
+
|
68
|
+
res
|
69
|
+
end
|
70
|
+
|
71
|
+
def ==(other)
|
72
|
+
other.is_a?(self.class) && other.agent_settings == agent_settings
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -21,9 +21,10 @@ module Datadog
|
|
21
21
|
extend Options
|
22
22
|
extend Helpers
|
23
23
|
|
24
|
-
attr_reader :statsd
|
24
|
+
attr_reader :statsd, :logger
|
25
25
|
|
26
|
-
def initialize(statsd: nil, enabled: true, **_)
|
26
|
+
def initialize(logger:, statsd: nil, enabled: true, **_)
|
27
|
+
@logger = logger
|
27
28
|
@statsd =
|
28
29
|
if supported?
|
29
30
|
statsd || default_statsd_client
|
@@ -98,7 +99,7 @@ module Datadog
|
|
98
99
|
|
99
100
|
statsd.count(stat, value, metric_options(options))
|
100
101
|
rescue StandardError => e
|
101
|
-
|
102
|
+
logger.error(
|
102
103
|
"Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
103
104
|
)
|
104
105
|
Telemetry::Logger.report(e, description: 'Failed to send count stat')
|
@@ -112,7 +113,7 @@ module Datadog
|
|
112
113
|
|
113
114
|
statsd.distribution(stat, value, metric_options(options))
|
114
115
|
rescue StandardError => e
|
115
|
-
|
116
|
+
logger.error(
|
116
117
|
"Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
117
118
|
)
|
118
119
|
Telemetry::Logger.report(e, description: 'Failed to send distribution stat')
|
@@ -125,7 +126,7 @@ module Datadog
|
|
125
126
|
|
126
127
|
statsd.increment(stat, metric_options(options))
|
127
128
|
rescue StandardError => e
|
128
|
-
|
129
|
+
logger.error(
|
129
130
|
"Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
130
131
|
)
|
131
132
|
Telemetry::Logger.report(e, description: 'Failed to send increment stat')
|
@@ -139,7 +140,7 @@ module Datadog
|
|
139
140
|
|
140
141
|
statsd.gauge(stat, value, metric_options(options))
|
141
142
|
rescue StandardError => e
|
142
|
-
|
143
|
+
logger.error(
|
143
144
|
"Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
144
145
|
)
|
145
146
|
Telemetry::Logger.report(e, description: 'Failed to send gauge stat')
|
@@ -159,7 +160,7 @@ module Datadog
|
|
159
160
|
end
|
160
161
|
rescue StandardError => e
|
161
162
|
# TODO: Likely to be redundant, since `distribution` handles its own errors.
|
162
|
-
|
163
|
+
logger.error(
|
163
164
|
"Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
164
165
|
)
|
165
166
|
Telemetry::Logger.report(e, description: 'Failed to send time stat')
|
@@ -194,7 +195,7 @@ module Datadog
|
|
194
195
|
|
195
196
|
def ignored_statsd_warning
|
196
197
|
IGNORED_STATSD_ONLY_ONCE.run do
|
197
|
-
|
198
|
+
logger.warn(
|
198
199
|
'Ignoring user-supplied statsd instance as currently-installed version of dogstastd-ruby is incompatible. ' \
|
199
200
|
"To fix this, ensure that you have `gem 'dogstatsd-ruby', '~> 5.3'` on your Gemfile or gems.rb file."
|
200
201
|
)
|
@@ -13,10 +13,11 @@ module Datadog
|
|
13
13
|
class TransportError < StandardError; end
|
14
14
|
class SyncError < StandardError; end
|
15
15
|
|
16
|
-
attr_reader :transport, :repository, :id, :dispatcher
|
16
|
+
attr_reader :transport, :repository, :id, :dispatcher, :logger
|
17
17
|
|
18
|
-
def initialize(transport, capabilities, repository: Configuration::Repository.new)
|
18
|
+
def initialize(transport, capabilities, logger:, repository: Configuration::Repository.new)
|
19
19
|
@transport = transport
|
20
|
+
@logger = logger
|
20
21
|
|
21
22
|
@repository = repository
|
22
23
|
@id = SecureRandom.uuid
|
@@ -40,7 +41,7 @@ module Datadog
|
|
40
41
|
def process_response(response)
|
41
42
|
# when response is completely empty, do nothing as in: leave as is
|
42
43
|
if response.empty?
|
43
|
-
|
44
|
+
logger.debug { 'remote: empty response => NOOP' }
|
44
45
|
|
45
46
|
return
|
46
47
|
end
|
@@ -112,7 +113,7 @@ module Datadog
|
|
112
113
|
end
|
113
114
|
|
114
115
|
if changes.empty?
|
115
|
-
|
116
|
+
logger.debug { 'remote: no changes' }
|
116
117
|
else
|
117
118
|
dispatcher.dispatch(changes, repository)
|
118
119
|
end
|
@@ -13,22 +13,24 @@ module Datadog
|
|
13
13
|
# Configures the HTTP transport to communicate with the agent
|
14
14
|
# to fetch and sync the remote configuration
|
15
15
|
class Component
|
16
|
-
attr_reader :client, :healthy
|
16
|
+
attr_reader :logger, :client, :healthy
|
17
|
+
|
18
|
+
def initialize(settings, capabilities, agent_settings, logger:)
|
19
|
+
@logger = logger
|
17
20
|
|
18
|
-
def initialize(settings, capabilities, agent_settings)
|
19
21
|
transport_options = {}
|
20
22
|
transport_options[:agent_settings] = agent_settings if agent_settings
|
21
23
|
|
22
24
|
negotiation = Negotiation.new(settings, agent_settings)
|
23
|
-
transport_v7 = Datadog::Core::Remote::Transport::HTTP.v7(**transport_options
|
25
|
+
transport_v7 = Datadog::Core::Remote::Transport::HTTP.v7(**transport_options) # steep:ignore
|
24
26
|
|
25
27
|
@barrier = Barrier.new(settings.remote.boot_timeout_seconds)
|
26
28
|
|
27
|
-
@client = Client.new(transport_v7, capabilities)
|
29
|
+
@client = Client.new(transport_v7, capabilities, logger: logger)
|
28
30
|
@healthy = false
|
29
|
-
|
31
|
+
logger.debug { "new remote configuration client: #{@client.id}" }
|
30
32
|
|
31
|
-
@worker = Worker.new(interval: settings.remote.poll_interval_seconds) do
|
33
|
+
@worker = Worker.new(interval: settings.remote.poll_interval_seconds, logger: logger) do
|
32
34
|
unless @healthy || negotiation.endpoint?('/v0.7/config')
|
33
35
|
@barrier.lift
|
34
36
|
|
@@ -40,7 +42,7 @@ module Datadog
|
|
40
42
|
@healthy ||= true
|
41
43
|
rescue Client::SyncError => e
|
42
44
|
# Transient errors due to network or agent. Logged the error but not via telemetry
|
43
|
-
|
45
|
+
logger.error do
|
44
46
|
"remote worker client sync error: #{e.message} location: #{Array(e.backtrace).first}. skipping sync"
|
45
47
|
end
|
46
48
|
rescue StandardError => e
|
@@ -50,15 +52,15 @@ module Datadog
|
|
50
52
|
negotiation = Negotiation.new(settings, agent_settings)
|
51
53
|
|
52
54
|
# Transient errors due to network or agent. Logged the error but not via telemetry
|
53
|
-
|
55
|
+
logger.error do
|
54
56
|
"remote worker error: #{e.class.name} #{e.message} location: #{Array(e.backtrace).first}. "\
|
55
57
|
'reseting client state'
|
56
58
|
end
|
57
59
|
|
58
60
|
# client state is unknown, state might be corrupted
|
59
|
-
@client = Client.new(transport_v7, capabilities)
|
61
|
+
@client = Client.new(transport_v7, capabilities, logger: logger)
|
60
62
|
@healthy = false
|
61
|
-
|
63
|
+
logger.debug { "new remote configuration client: #{@client.id}" }
|
62
64
|
|
63
65
|
# TODO: bail out if too many errors?
|
64
66
|
end
|
@@ -152,10 +154,10 @@ module Datadog
|
|
152
154
|
#
|
153
155
|
# Those checks are instead performed inside the worker loop.
|
154
156
|
# This allows users to upgrade their agent while keeping their application running.
|
155
|
-
def build(settings, agent_settings, telemetry:)
|
157
|
+
def build(settings, agent_settings, logger:, telemetry:)
|
156
158
|
return unless settings.remote.enabled
|
157
159
|
|
158
|
-
new(settings, Client::Capabilities.new(settings, telemetry), agent_settings)
|
160
|
+
new(settings, Client::Capabilities.new(settings, telemetry), agent_settings, logger: logger)
|
159
161
|
end
|
160
162
|
end
|
161
163
|
end
|
@@ -11,7 +11,7 @@ module Datadog
|
|
11
11
|
transport_options = {}
|
12
12
|
transport_options[:agent_settings] = agent_settings if agent_settings
|
13
13
|
|
14
|
-
@transport_root = Datadog::Core::Remote::Transport::HTTP.root(**transport_options
|
14
|
+
@transport_root = Datadog::Core::Remote::Transport::HTTP.root(**transport_options) # steep:ignore
|
15
15
|
@logged = suppress_logging
|
16
16
|
end
|
17
17
|
|