datadog 2.10.0 → 2.12.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 +56 -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 +56 -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/patcher.rb +0 -3
- 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/gateway/watcher.rb +65 -73
- data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
- 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/monitor/gateway/watcher.rb +19 -25
- data/lib/datadog/appsec/remote.rb +4 -0
- data/lib/datadog/appsec.rb +3 -0
- data/lib/datadog/core/configuration/components.rb +8 -2
- 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/remote/component.rb +11 -9
- 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 +7 -12
- 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/response.rb +4 -0
- 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 +119 -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/sync_writer.rb +5 -2
- data/lib/datadog/tracing/tracer.rb +10 -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 +12 -7
- data/lib/datadog/tracing/transport/serializable_trace.rb +8 -4
- data/lib/datadog/tracing/transport/traces.rb +25 -8
- data/lib/datadog/tracing/workers/trace_writer.rb +4 -1
- data/lib/datadog/tracing/workers.rb +5 -4
- data/lib/datadog/tracing/writer.rb +6 -2
- data/lib/datadog/version.rb +1 -1
- metadata +33 -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,13 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative '
|
5
|
-
require_relative '
|
6
|
-
require_relative 'api/instance'
|
7
|
-
require_relative 'client'
|
3
|
+
require_relative '../../configuration/agent_settings_resolver'
|
4
|
+
require_relative 'adapters/registry'
|
5
|
+
require_relative 'api/map'
|
8
6
|
|
9
7
|
module Datadog
|
10
|
-
module
|
8
|
+
module Core
|
11
9
|
module Transport
|
12
10
|
module HTTP
|
13
11
|
# Builds new instances of Transport::HTTP::Client
|
@@ -15,13 +13,14 @@ module Datadog
|
|
15
13
|
REGISTRY = Datadog::Core::Transport::HTTP::Adapters::Registry.new
|
16
14
|
|
17
15
|
attr_reader \
|
16
|
+
:api_instance_class,
|
18
17
|
:apis,
|
19
18
|
:api_options,
|
20
19
|
:default_adapter,
|
21
20
|
:default_api,
|
22
21
|
:default_headers
|
23
22
|
|
24
|
-
def initialize
|
23
|
+
def initialize(api_instance_class:)
|
25
24
|
# Global settings
|
26
25
|
@default_adapter = nil
|
27
26
|
@default_headers = {}
|
@@ -33,6 +32,8 @@ module Datadog
|
|
33
32
|
# API settings
|
34
33
|
@api_options = {}
|
35
34
|
|
35
|
+
@api_instance_class = api_instance_class
|
36
|
+
|
36
37
|
yield(self) if block_given?
|
37
38
|
end
|
38
39
|
|
@@ -82,11 +83,10 @@ module Datadog
|
|
82
83
|
@default_api = key
|
83
84
|
end
|
84
85
|
|
85
|
-
def to_transport
|
86
|
+
def to_transport(klass)
|
86
87
|
raise NoDefaultApiError if @default_api.nil?
|
87
88
|
|
88
|
-
|
89
|
-
Transport::Traces::Transport.new(to_api_instances, @default_api)
|
89
|
+
klass.new(to_api_instances, @default_api)
|
90
90
|
end
|
91
91
|
|
92
92
|
def to_api_instances
|
@@ -117,28 +117,48 @@ module Datadog
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
def api_instance_class
|
121
|
-
API::Instance
|
122
|
-
end
|
123
|
-
|
124
120
|
# Raised when the API key does not match known APIs.
|
125
121
|
class UnknownApiError < StandardError
|
122
|
+
attr_reader :key
|
123
|
+
|
126
124
|
def initialize(key)
|
127
|
-
super(
|
125
|
+
super()
|
126
|
+
|
127
|
+
@key = key
|
128
|
+
end
|
129
|
+
|
130
|
+
def message
|
131
|
+
"Unknown transport API '#{key}'!"
|
128
132
|
end
|
129
133
|
end
|
130
134
|
|
131
135
|
# Raised when the identifier cannot be matched to an adapter.
|
132
136
|
class UnknownAdapterError < StandardError
|
137
|
+
attr_reader :type
|
138
|
+
|
133
139
|
def initialize(type)
|
134
|
-
super(
|
140
|
+
super()
|
141
|
+
|
142
|
+
@type = type
|
143
|
+
end
|
144
|
+
|
145
|
+
def message
|
146
|
+
"Unknown transport adapter '#{type}'!"
|
135
147
|
end
|
136
148
|
end
|
137
149
|
|
138
150
|
# Raised when an adapter cannot be resolved for an API instance.
|
139
151
|
class NoAdapterForApiError < StandardError
|
152
|
+
attr_reader :key
|
153
|
+
|
140
154
|
def initialize(key)
|
141
|
-
super(
|
155
|
+
super()
|
156
|
+
|
157
|
+
@key = key
|
158
|
+
end
|
159
|
+
|
160
|
+
def message
|
161
|
+
"No adapter resolved for transport API '#{key}'!"
|
142
162
|
end
|
143
163
|
end
|
144
164
|
|
@@ -140,16 +140,23 @@ module Datadog
|
|
140
140
|
exact = registry[suffix]
|
141
141
|
return [suffix, exact] if exact
|
142
142
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
143
|
+
suffix = suffix.dup
|
144
|
+
loop do
|
145
|
+
inexact = []
|
146
|
+
registry.each do |path, iseq|
|
147
|
+
if Utils.path_matches_suffix?(path, suffix)
|
148
|
+
inexact << [path, iseq]
|
149
|
+
end
|
147
150
|
end
|
151
|
+
if inexact.length > 1
|
152
|
+
raise Error::MultiplePathsMatch, "Multiple paths matched requested suffix"
|
153
|
+
end
|
154
|
+
if inexact.any?
|
155
|
+
return inexact.first
|
156
|
+
end
|
157
|
+
return nil unless suffix.include?('/')
|
158
|
+
suffix.sub!(%r{.*/+}, '')
|
148
159
|
end
|
149
|
-
if inexact.length > 1
|
150
|
-
raise Error::MultiplePathsMatch, "Multiple paths matched requested suffix"
|
151
|
-
end
|
152
|
-
inexact.first
|
153
160
|
end
|
154
161
|
end
|
155
162
|
|
data/lib/datadog/di/component.rb
CHANGED
@@ -74,14 +74,14 @@ module Datadog
|
|
74
74
|
def initialize(settings, agent_settings, logger, code_tracker: nil, telemetry: nil)
|
75
75
|
@settings = settings
|
76
76
|
@agent_settings = agent_settings
|
77
|
+
logger = DI::Logger.new(settings, logger)
|
77
78
|
@logger = logger
|
78
79
|
@telemetry = telemetry
|
79
80
|
@code_tracker = code_tracker
|
80
81
|
@redactor = Redactor.new(settings)
|
81
82
|
@serializer = Serializer.new(settings, redactor, telemetry: telemetry)
|
82
83
|
@instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry)
|
83
|
-
@
|
84
|
-
@probe_notifier_worker = ProbeNotifierWorker.new(settings, transport, logger, telemetry: telemetry)
|
84
|
+
@probe_notifier_worker = ProbeNotifierWorker.new(settings, logger, agent_settings: agent_settings, telemetry: telemetry)
|
85
85
|
@probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer)
|
86
86
|
@probe_manager = ProbeManager.new(settings, instrumenter, probe_notification_builder, probe_notifier_worker, logger, telemetry: telemetry)
|
87
87
|
probe_notifier_worker.start
|
@@ -93,7 +93,6 @@ module Datadog
|
|
93
93
|
attr_reader :telemetry
|
94
94
|
attr_reader :code_tracker
|
95
95
|
attr_reader :instrumenter
|
96
|
-
attr_reader :transport
|
97
96
|
attr_reader :probe_notifier_worker
|
98
97
|
attr_reader :probe_notification_builder
|
99
98
|
attr_reader :probe_manager
|
@@ -188,6 +188,20 @@ module Datadog
|
|
188
188
|
o.type :bool
|
189
189
|
o.default false
|
190
190
|
end
|
191
|
+
|
192
|
+
# Enable logging of dynamic instrumentation activity.
|
193
|
+
# This is quite verbose.
|
194
|
+
option :trace_logging do |o|
|
195
|
+
o.type :bool
|
196
|
+
o.default false
|
197
|
+
|
198
|
+
# Use the same environment variable as the rest of
|
199
|
+
# dd-trace-rb logging for now. Could change to a
|
200
|
+
# dedicated environment variable in the future but
|
201
|
+
# will likely need a way to turn on remote config
|
202
|
+
# debugging (since DI uses RC for configuration).
|
203
|
+
o.env 'DD_TRACE_DEBUG'
|
204
|
+
end
|
191
205
|
end
|
192
206
|
end
|
193
207
|
end
|
data/lib/datadog/di/contrib.rb
CHANGED
@@ -7,6 +7,7 @@ module Datadog
|
|
7
7
|
module Contrib
|
8
8
|
module_function def load_now_or_later
|
9
9
|
if Datadog::Core::Contrib::Rails::Utils.railtie_supported?
|
10
|
+
Datadog.logger.debug('di: loading contrib/railtie')
|
10
11
|
require_relative 'contrib/railtie'
|
11
12
|
else
|
12
13
|
load_now
|
@@ -18,6 +19,7 @@ module Datadog
|
|
18
19
|
# dependencies are loaded (or potentially loaded).
|
19
20
|
module_function def load_now
|
20
21
|
if defined?(ActiveRecord::Base)
|
22
|
+
Datadog.logger.debug('di: loading contrib/active_record')
|
21
23
|
require_relative 'contrib/active_record'
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module DI
|
7
|
+
# Logger facade to add the +trace+ method.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
class Logger
|
11
|
+
extend Forwardable # steep:ignore
|
12
|
+
|
13
|
+
def initialize(settings, target)
|
14
|
+
@settings = settings
|
15
|
+
@target = target
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :settings
|
19
|
+
attr_reader :target
|
20
|
+
|
21
|
+
def_delegators :target, :debug # steep:ignore
|
22
|
+
|
23
|
+
def trace(&block)
|
24
|
+
if settings.dynamic_instrumentation.internal.trace_logging
|
25
|
+
debug(&block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/datadog/di/probe.rb
CHANGED
@@ -155,11 +155,8 @@ module Datadog
|
|
155
155
|
# Returns whether the provided +path+ matches the user-designated
|
156
156
|
# file (of a line probe).
|
157
157
|
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
# If file is not an absolute path, the path matches if the file is its suffix,
|
162
|
-
# at a path component boundary.
|
158
|
+
# Delegates to Utils.path_can_match_spec? which performs fuzzy
|
159
|
+
# matching. See the comments in utils.rb for details.
|
163
160
|
def file_matches?(path)
|
164
161
|
if path.nil?
|
165
162
|
raise ArgumentError, "Cannot match against a nil path"
|
@@ -167,7 +164,7 @@ module Datadog
|
|
167
164
|
unless file
|
168
165
|
raise ArgumentError, "Probe does not have a file to match against"
|
169
166
|
end
|
170
|
-
Utils.
|
167
|
+
Utils.path_can_match_spec?(path, file)
|
171
168
|
end
|
172
169
|
|
173
170
|
# Instrumentation module for method probes.
|
@@ -111,9 +111,11 @@ module Datadog
|
|
111
111
|
# Always remove from pending list here because it makes the
|
112
112
|
# API smaller and shouldn't cause any actual problems.
|
113
113
|
@pending_probes.delete(probe.id)
|
114
|
+
logger.trace { "di: installed #{probe.type} probe at #{probe.location} (#{probe.id})" }
|
114
115
|
true
|
115
116
|
rescue Error::DITargetNotDefined
|
116
117
|
@pending_probes[probe.id] = probe
|
118
|
+
logger.trace { "di: could not install #{probe.type} probe at #{probe.location} (#{probe.id}) because its target is not defined, adding it to pending list" }
|
117
119
|
false
|
118
120
|
end
|
119
121
|
rescue => exc
|
@@ -160,7 +162,7 @@ module Datadog
|
|
160
162
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
161
163
|
# Silence all exceptions?
|
162
164
|
# TODO should we propagate here and rescue upstream?
|
163
|
-
logger.debug { "di: error removing probe #{probe.id}: #{exc.class}: #{exc}" }
|
165
|
+
logger.debug { "di: error removing #{probe.type} probe at #{probe.location} (#{probe.id}): #{exc.class}: #{exc}" }
|
164
166
|
telemetry&.report(exc, description: "Error removing probe")
|
165
167
|
end
|
166
168
|
end
|
@@ -190,7 +192,7 @@ module Datadog
|
|
190
192
|
rescue => exc
|
191
193
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
192
194
|
|
193
|
-
logger.debug { "di: error installing probe after class is defined: #{exc.class}: #{exc}" }
|
195
|
+
logger.debug { "di: error installing #{probe.type} probe at #{probe.location} (#{probe.id}) after class is defined: #{exc.class}: #{exc}" }
|
194
196
|
telemetry&.report(exc, description: "Error installing probe after class is defined")
|
195
197
|
end
|
196
198
|
end
|
@@ -228,6 +230,7 @@ module Datadog
|
|
228
230
|
# backend (once per the probe's lifetime) and a snapshot corresponding
|
229
231
|
# to the current invocation.
|
230
232
|
def probe_executed_callback(probe:, **opts)
|
233
|
+
logger.trace { "di: executed #{probe.type} probe at #{probe.location} (#{probe.id})" }
|
231
234
|
unless probe.emitting_notified?
|
232
235
|
payload = probe_notification_builder.build_emitting(probe)
|
233
236
|
probe_notifier_worker.add_status(payload)
|
@@ -10,7 +10,7 @@ module Datadog
|
|
10
10
|
# The loop inside the worker rescues all exceptions to prevent termination
|
11
11
|
# due to unhandled exceptions raised by any downstream code.
|
12
12
|
# This includes communication and protocol errors when sending the
|
13
|
-
#
|
13
|
+
# events to the agent.
|
14
14
|
#
|
15
15
|
# The worker groups the data to send into batches. The goal is to perform
|
16
16
|
# no more than one network operation per event type per second.
|
@@ -23,12 +23,12 @@ module Datadog
|
|
23
23
|
#
|
24
24
|
# @api private
|
25
25
|
class ProbeNotifierWorker
|
26
|
-
def initialize(settings,
|
26
|
+
def initialize(settings, logger, agent_settings:, telemetry: nil)
|
27
27
|
@settings = settings
|
28
28
|
@telemetry = telemetry
|
29
29
|
@status_queue = []
|
30
30
|
@snapshot_queue = []
|
31
|
-
@
|
31
|
+
@agent_settings = agent_settings
|
32
32
|
@logger = logger
|
33
33
|
@lock = Mutex.new
|
34
34
|
@wake = Core::Semaphore.new
|
@@ -36,15 +36,18 @@ module Datadog
|
|
36
36
|
@sleep_remaining = nil
|
37
37
|
@wake_scheduled = false
|
38
38
|
@thread = nil
|
39
|
+
@pid = nil
|
39
40
|
@flush = 0
|
40
41
|
end
|
41
42
|
|
42
43
|
attr_reader :settings
|
43
44
|
attr_reader :logger
|
44
45
|
attr_reader :telemetry
|
46
|
+
attr_reader :agent_settings
|
45
47
|
|
46
48
|
def start
|
47
|
-
return if @thread
|
49
|
+
return if @thread && @pid == Process.pid
|
50
|
+
logger.trace { "di: starting probe notifier: pid #{$$}" }
|
48
51
|
@thread = Thread.new do
|
49
52
|
loop do
|
50
53
|
# TODO If stop is requested, we stop immediately without
|
@@ -86,6 +89,7 @@ module Datadog
|
|
86
89
|
wake.wait(more ? min_send_interval : nil)
|
87
90
|
end
|
88
91
|
end
|
92
|
+
@pid = Process.pid
|
89
93
|
end
|
90
94
|
|
91
95
|
# Stops the background thread.
|
@@ -94,6 +98,7 @@ module Datadog
|
|
94
98
|
# to killing the thread using Thread#kill.
|
95
99
|
def stop(timeout = 1)
|
96
100
|
@stop_requested = true
|
101
|
+
logger.trace { "di: stopping probe notifier: pid #{$$}" }
|
97
102
|
wake.signal
|
98
103
|
if thread
|
99
104
|
unless thread.join(timeout)
|
@@ -150,7 +155,6 @@ module Datadog
|
|
150
155
|
|
151
156
|
private
|
152
157
|
|
153
|
-
attr_reader :transport
|
154
158
|
attr_reader :wake
|
155
159
|
attr_reader :thread
|
156
160
|
|
@@ -166,6 +170,22 @@ module Datadog
|
|
166
170
|
|
167
171
|
attr_reader :last_sent
|
168
172
|
|
173
|
+
def status_transport
|
174
|
+
@status_transport ||= DI::Transport::HTTP.diagnostics(agent_settings: agent_settings)
|
175
|
+
end
|
176
|
+
|
177
|
+
def do_send_status(batch)
|
178
|
+
status_transport.send_diagnostics(batch)
|
179
|
+
end
|
180
|
+
|
181
|
+
def snapshot_transport
|
182
|
+
@snapshot_transport ||= DI::Transport::HTTP.input(agent_settings: agent_settings)
|
183
|
+
end
|
184
|
+
|
185
|
+
def do_send_snapshot(batch)
|
186
|
+
snapshot_transport.send_input(batch)
|
187
|
+
end
|
188
|
+
|
169
189
|
[
|
170
190
|
[:status, 'probe status'],
|
171
191
|
[:snapshot, 'snapshot'],
|
@@ -184,8 +204,9 @@ module Datadog
|
|
184
204
|
@lock.synchronize do
|
185
205
|
queue = send("#{event_type}_queue")
|
186
206
|
if queue.length > settings.dynamic_instrumentation.internal.snapshot_queue_capacity
|
187
|
-
logger.debug { "di: #{self.class.name}: dropping #{event_type} because queue is full" }
|
207
|
+
logger.debug { "di: #{self.class.name}: dropping #{event_type} event because queue is full" }
|
188
208
|
else
|
209
|
+
logger.trace { "di: #{self.class.name}: queueing #{event_type} event" }
|
189
210
|
queue << event
|
190
211
|
end
|
191
212
|
end
|
@@ -200,6 +221,10 @@ module Datadog
|
|
200
221
|
wake.signal
|
201
222
|
end
|
202
223
|
end
|
224
|
+
|
225
|
+
# Worker could be not running if the process forked - check and
|
226
|
+
# start it again in this case.
|
227
|
+
start
|
203
228
|
end
|
204
229
|
|
205
230
|
# Determine how much longer the worker thread should sleep
|
@@ -232,9 +257,11 @@ module Datadog
|
|
232
257
|
instance_variable_set("@#{event_type}_queue", [])
|
233
258
|
@io_in_progress = batch.any? # steep:ignore
|
234
259
|
end
|
260
|
+
logger.trace { "di: #{self.class.name}: checking #{event_type} queue - #{batch.length} entries" } # steep:ignore
|
235
261
|
if batch.any? # steep:ignore
|
236
262
|
begin
|
237
|
-
|
263
|
+
logger.trace { "di: sending #{batch.length} #{event_type} event(s) to agent" } # steep:ignore
|
264
|
+
send("do_send_#{event_type}", batch)
|
238
265
|
time = Core::Utils::Time.get_time
|
239
266
|
@lock.synchronize do
|
240
267
|
@last_sent = time
|
@@ -263,7 +290,7 @@ module Datadog
|
|
263
290
|
|
264
291
|
def maybe_send
|
265
292
|
rv = maybe_send_status
|
266
|
-
|
293
|
+
maybe_send_snapshot || rv
|
267
294
|
end
|
268
295
|
end
|
269
296
|
end
|
data/lib/datadog/di/remote.rb
CHANGED
@@ -53,7 +53,7 @@ module Datadog
|
|
53
53
|
payload = probe_notification_builder.build_received(probe)
|
54
54
|
probe_notifier_worker = component.probe_notifier_worker
|
55
55
|
probe_notifier_worker.add_status(payload)
|
56
|
-
component.logger.debug { "di: received probe
|
56
|
+
component.logger.debug { "di: received #{probe.type} probe at #{probe.location} (#{probe.id}) via RC" }
|
57
57
|
|
58
58
|
begin
|
59
59
|
# TODO test exception capture
|
@@ -76,7 +76,7 @@ module Datadog
|
|
76
76
|
rescue => exc
|
77
77
|
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
78
78
|
|
79
|
-
component.logger.debug { "di: unhandled exception adding probe in DI remote receiver: #{exc.class}: #{exc}" }
|
79
|
+
component.logger.debug { "di: unhandled exception adding #{probe.type} probe at #{probe.location} (#{probe.id}) in DI remote receiver: #{exc.class}: #{exc}" }
|
80
80
|
component.telemetry&.report(exc, description: "Unhandled exception adding probe in DI remote receiver")
|
81
81
|
|
82
82
|
# TODO test this path
|
@@ -101,7 +101,7 @@ module Datadog
|
|
101
101
|
rescue => exc
|
102
102
|
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
103
103
|
|
104
|
-
component.logger.debug { "di: unhandled exception handling probe in DI remote receiver: #{exc.class}: #{exc}" }
|
104
|
+
component.logger.debug { "di: unhandled exception handling a probe in DI remote receiver: #{exc.class}: #{exc}" }
|
105
105
|
component.telemetry&.report(exc, description: "Unhandled exception handling probe in DI remote receiver")
|
106
106
|
|
107
107
|
# TODO assert content state (errored for this example)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../core/transport/parcel'
|
4
|
+
require_relative 'http/client'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module DI
|
8
|
+
module Transport
|
9
|
+
module Diagnostics
|
10
|
+
class EncodedParcel
|
11
|
+
include Datadog::Core::Transport::Parcel
|
12
|
+
end
|
13
|
+
|
14
|
+
class Request < Datadog::Core::Transport::Request
|
15
|
+
end
|
16
|
+
|
17
|
+
class Transport
|
18
|
+
attr_reader :client, :apis, :default_api, :current_api_id
|
19
|
+
|
20
|
+
def initialize(apis, default_api)
|
21
|
+
@apis = apis
|
22
|
+
|
23
|
+
@client = HTTP::Client.new(current_api)
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_api
|
27
|
+
@apis[HTTP::API::DIAGNOSTICS]
|
28
|
+
end
|
29
|
+
|
30
|
+
def send_diagnostics(payload)
|
31
|
+
json = JSON.dump(payload)
|
32
|
+
parcel = EncodedParcel.new(json)
|
33
|
+
request = Request.new(parcel)
|
34
|
+
|
35
|
+
response = @client.send_diagnostics_payload(request)
|
36
|
+
unless response.ok?
|
37
|
+
# TODO Datadog::Core::Transport::InternalErrorResponse
|
38
|
+
# does not have +code+ method, what is the actual API of
|
39
|
+
# these response objects?
|
40
|
+
raise Error::AgentCommunicationError, "send_diagnostics failed: #{begin
|
41
|
+
response.code
|
42
|
+
rescue
|
43
|
+
"???"
|
44
|
+
end}: #{response.payload}"
|
45
|
+
end
|
46
|
+
rescue Error::AgentCommunicationError
|
47
|
+
raise
|
48
|
+
# Datadog::Core::Transport does not perform any exception mapping,
|
49
|
+
# therefore we could have any exception here from failure to parse
|
50
|
+
# agent URI for example.
|
51
|
+
# If we ever implement retries for network errors, we should distinguish
|
52
|
+
# actual network errors from non-network errors that are raised by
|
53
|
+
# transport code.
|
54
|
+
rescue => exc
|
55
|
+
raise Error::AgentCommunicationError, "send_diagnostics failed: #{exc.class}: #{exc}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../core/encoding'
|
4
|
+
require_relative '../../../core/transport/http/api/map'
|
5
|
+
require_relative '../../../core/transport/http/api/instance'
|
6
|
+
require_relative '../../../core/transport/http/api/spec'
|
7
|
+
require_relative 'diagnostics'
|
8
|
+
require_relative 'input'
|
9
|
+
|
10
|
+
module Datadog
|
11
|
+
module DI
|
12
|
+
module Transport
|
13
|
+
module HTTP
|
14
|
+
# Namespace for API components
|
15
|
+
module API
|
16
|
+
# Default API versions
|
17
|
+
DIAGNOSTICS = 'diagnostics'
|
18
|
+
INPUT = 'input'
|
19
|
+
|
20
|
+
module_function
|
21
|
+
|
22
|
+
def defaults
|
23
|
+
Datadog::Core::Transport::HTTP::API::Map[
|
24
|
+
DIAGNOSTICS => Spec.new do |s|
|
25
|
+
s.diagnostics = Diagnostics::API::Endpoint.new(
|
26
|
+
'/debugger/v1/diagnostics',
|
27
|
+
Core::Encoding::JSONEncoder,
|
28
|
+
)
|
29
|
+
end,
|
30
|
+
INPUT => Spec.new do |s|
|
31
|
+
s.input = Input::API::Endpoint.new(
|
32
|
+
'/debugger/v1/input',
|
33
|
+
Core::Encoding::JSONEncoder,
|
34
|
+
)
|
35
|
+
end,
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
class Instance < Core::Transport::HTTP::API::Instance
|
40
|
+
include Diagnostics::API::Instance
|
41
|
+
include Input::API::Instance
|
42
|
+
end
|
43
|
+
|
44
|
+
class Spec < Core::Transport::HTTP::API::Spec
|
45
|
+
include Diagnostics::API::Spec
|
46
|
+
include Input::API::Spec
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../core/transport/http/env'
|
4
|
+
require_relative '../../../core/transport/http/response'
|
5
|
+
|
6
|
+
# TODO: Decouple transport/http/client
|
7
|
+
#
|
8
|
+
# The standard one does `include Transport::HTTP::Statistics` and performs
|
9
|
+
# stats updates, which may or may not be desirable in general.
|
10
|
+
|
11
|
+
module Datadog
|
12
|
+
module DI
|
13
|
+
module Transport
|
14
|
+
module HTTP
|
15
|
+
# Routes, encodes, and sends DI data to the trace agent via HTTP.
|
16
|
+
class Client
|
17
|
+
attr_reader :api
|
18
|
+
|
19
|
+
def initialize(api)
|
20
|
+
@api = api
|
21
|
+
end
|
22
|
+
|
23
|
+
def send_request(request, &block)
|
24
|
+
# Build request into env
|
25
|
+
env = build_env(request)
|
26
|
+
|
27
|
+
# Get responses from API
|
28
|
+
yield(api, env)
|
29
|
+
rescue => e
|
30
|
+
message =
|
31
|
+
"Internal error during #{self.class.name} request. Cause: #{e.class.name} #{e.message} " \
|
32
|
+
"Location: #{Array(e.backtrace).first}"
|
33
|
+
|
34
|
+
Datadog.logger.debug(message)
|
35
|
+
|
36
|
+
Datadog::Core::Transport::InternalErrorResponse.new(e)
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_env(request)
|
40
|
+
Datadog::Core::Transport::HTTP::Env.new(request)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|