datadog 2.11.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 +11 -1
- 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.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +1 -1
- data/lib/datadog/core/remote/component.rb +11 -9
- data/lib/datadog/core/remote/worker.rb +10 -7
- data/lib/datadog/core/telemetry/component.rb +5 -1
- data/lib/datadog/core/telemetry/worker.rb +9 -5
- data/lib/datadog/di/component.rb +1 -3
- data/lib/datadog/di/probe_notifier_worker.rb +20 -4
- 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.rb +2 -1
- data/lib/datadog/tracing/component.rb +1 -0
- data/lib/datadog/tracing/sync_writer.rb +5 -2
- data/lib/datadog/tracing/tracer.rb +10 -7
- 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 +14 -5
- data/lib/datadog/di/transport.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5687b95de2487329c4b7e6d6eab86704f8eb2cdcedd5588bcf11af0fdc266f7e
|
4
|
+
data.tar.gz: 837992da8e2c14754b6eb12eb6b26de83a20b68d2bdc369ba925ddd404c2d91b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de9312020663a01030298e462fa5b86e12b151203c6c2a555fc091954c39ecebb36c49a6dee31f9b337c35d3cad7df24c93a883f0d7da426f78d62581200d272
|
7
|
+
data.tar.gz: 26b49b0f342521eccdafe2390ab13c2762abfb1791cf27faf68c75be5727a949f888ccfc8ebff39ae69de267563ea38c1abea1faaafcfef166dd25226b340c9d
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [2.12.0] - 2025-02-27
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* AppSec: Add detection of Server-Side Request Forgery attacks for `rest-client` ([#4424][])
|
10
|
+
* Dynamic Instrumentation: Add support for unix domain sockets ([#4426][])
|
11
|
+
|
5
12
|
## [2.11.0] - 2025-02-24
|
6
13
|
|
7
14
|
### Added
|
@@ -3126,7 +3133,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
3126
3133
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
3127
3134
|
|
3128
3135
|
|
3129
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
3136
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.0...master
|
3137
|
+
[2.12.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.11.0...v2.12.0
|
3130
3138
|
[2.11.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.10.0...v2.11.0
|
3131
3139
|
[2.10.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.9.0...v2.10.0
|
3132
3140
|
[2.9.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.8.0...v2.9.0
|
@@ -4624,7 +4632,9 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4624
4632
|
[#4406]: https://github.com/DataDog/dd-trace-rb/issues/4406
|
4625
4633
|
[#4411]: https://github.com/DataDog/dd-trace-rb/issues/4411
|
4626
4634
|
[#4422]: https://github.com/DataDog/dd-trace-rb/issues/4422
|
4635
|
+
[#4424]: https://github.com/DataDog/dd-trace-rb/issues/4424
|
4627
4636
|
[#4425]: https://github.com/DataDog/dd-trace-rb/issues/4425
|
4637
|
+
[#4426]: https://github.com/DataDog/dd-trace-rb/issues/4426
|
4628
4638
|
[@AdrianLC]: https://github.com/AdrianLC
|
4629
4639
|
[@Azure7111]: https://github.com/Azure7111
|
4630
4640
|
[@BabyGroot]: https://github.com/BabyGroot
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../integration'
|
4
|
+
require_relative 'patcher'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module AppSec
|
8
|
+
module Contrib
|
9
|
+
module RestClient
|
10
|
+
# This class defines properties of rest-client AppSec integration
|
11
|
+
class Integration
|
12
|
+
include Datadog::AppSec::Contrib::Integration
|
13
|
+
|
14
|
+
MINIMUM_VERSION = Gem::Version.new('1.8')
|
15
|
+
|
16
|
+
register_as :rest_client
|
17
|
+
|
18
|
+
def self.gem_name
|
19
|
+
'rest-client'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.version
|
23
|
+
Gem.loaded_specs['rest-client'] && Gem.loaded_specs['rest-client'].version
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.loaded?
|
27
|
+
!defined?(::RestClient::Request).nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.compatible?
|
31
|
+
super && version >= MINIMUM_VERSION
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.auto_instrument?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def patcher
|
39
|
+
Patcher
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module Contrib
|
6
|
+
module RestClient
|
7
|
+
# Patcher for RestClient gem
|
8
|
+
module Patcher
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def patched?
|
12
|
+
Patcher.instance_variable_get(:@patched)
|
13
|
+
end
|
14
|
+
|
15
|
+
def target_version
|
16
|
+
Integration.version
|
17
|
+
end
|
18
|
+
|
19
|
+
def patch
|
20
|
+
require_relative 'request_ssrf_detection_patch'
|
21
|
+
|
22
|
+
::RestClient::Request.prepend(RequestSSRFDetectionPatch)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# rubocop:disable Naming/FileName
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module AppSec
|
6
|
+
module Contrib
|
7
|
+
module RestClient
|
8
|
+
# Module that adds SSRF detection to RestClient::Request#execute
|
9
|
+
module RequestSSRFDetectionPatch
|
10
|
+
def execute(&block)
|
11
|
+
return super unless AppSec.rasp_enabled? && AppSec.active_context
|
12
|
+
|
13
|
+
context = AppSec.active_context
|
14
|
+
|
15
|
+
ephemeral_data = { 'server.io.net.url' => url }
|
16
|
+
result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
|
17
|
+
|
18
|
+
if result.match?
|
19
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
20
|
+
|
21
|
+
context.events << {
|
22
|
+
waf_result: result,
|
23
|
+
trace: context.trace,
|
24
|
+
span: context.span,
|
25
|
+
request_url: url,
|
26
|
+
actions: result.actions
|
27
|
+
}
|
28
|
+
|
29
|
+
ActionsHandler.handle(result.actions)
|
30
|
+
end
|
31
|
+
|
32
|
+
super(&block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
# rubocop:enable Naming/FileName
|
data/lib/datadog/appsec.rb
CHANGED
@@ -70,5 +70,6 @@ require_relative 'appsec/contrib/devise/integration'
|
|
70
70
|
require_relative 'appsec/contrib/graphql/integration'
|
71
71
|
require_relative 'appsec/contrib/faraday/integration'
|
72
72
|
require_relative 'appsec/contrib/excon/integration'
|
73
|
+
require_relative 'appsec/contrib/rest_client/integration'
|
73
74
|
|
74
75
|
require_relative 'appsec/autoload'
|
@@ -104,7 +104,7 @@ module Datadog
|
|
104
104
|
|
105
105
|
@telemetry = self.class.build_telemetry(settings, agent_settings, @logger)
|
106
106
|
|
107
|
-
@remote = Remote::Component.build(settings, agent_settings, telemetry: telemetry)
|
107
|
+
@remote = Remote::Component.build(settings, agent_settings, logger: @logger, telemetry: telemetry)
|
108
108
|
@tracer = self.class.build_tracer(settings, agent_settings, logger: @logger)
|
109
109
|
@crashtracker = self.class.build_crashtracker(settings, agent_settings, logger: @logger)
|
110
110
|
|
@@ -13,9 +13,11 @@ 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
|
|
@@ -26,9 +28,9 @@ module Datadog
|
|
26
28
|
|
27
29
|
@client = Client.new(transport_v7, capabilities)
|
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,7 +52,7 @@ 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
|
@@ -58,7 +60,7 @@ module Datadog
|
|
58
60
|
# client state is unknown, state might be corrupted
|
59
61
|
@client = Client.new(transport_v7, capabilities)
|
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
|
@@ -5,7 +5,7 @@ module Datadog
|
|
5
5
|
module Remote
|
6
6
|
# Worker executes a block every interval on a separate Thread
|
7
7
|
class Worker
|
8
|
-
def initialize(interval:, &block)
|
8
|
+
def initialize(interval:, logger:, &block)
|
9
9
|
@mutex = Mutex.new
|
10
10
|
@thr = nil
|
11
11
|
|
@@ -14,18 +14,21 @@ module Datadog
|
|
14
14
|
@stopped = false
|
15
15
|
|
16
16
|
@interval = interval
|
17
|
+
@logger = logger
|
17
18
|
raise ArgumentError, 'can not initialize a worker without a block' unless block
|
18
19
|
|
19
20
|
@block = block
|
20
21
|
end
|
21
22
|
|
23
|
+
attr_reader :logger
|
24
|
+
|
22
25
|
def start
|
23
|
-
|
26
|
+
logger.debug { 'remote worker starting' }
|
24
27
|
|
25
28
|
acquire_lock
|
26
29
|
|
27
30
|
if @stopped
|
28
|
-
|
31
|
+
logger.debug('remote worker: refusing to restart after previous stop')
|
29
32
|
return
|
30
33
|
end
|
31
34
|
|
@@ -41,13 +44,13 @@ module Datadog
|
|
41
44
|
@started = true
|
42
45
|
@starting = false
|
43
46
|
|
44
|
-
|
47
|
+
logger.debug { 'remote worker started' }
|
45
48
|
ensure
|
46
49
|
release_lock
|
47
50
|
end
|
48
51
|
|
49
52
|
def stop
|
50
|
-
|
53
|
+
logger.debug { 'remote worker stopping' }
|
51
54
|
|
52
55
|
acquire_lock
|
53
56
|
|
@@ -62,7 +65,7 @@ module Datadog
|
|
62
65
|
@thr = nil
|
63
66
|
@stopped = true
|
64
67
|
|
65
|
-
|
68
|
+
logger.debug { 'remote worker stopped' }
|
66
69
|
ensure
|
67
70
|
release_lock
|
68
71
|
end
|
@@ -92,7 +95,7 @@ module Datadog
|
|
92
95
|
end
|
93
96
|
|
94
97
|
def call
|
95
|
-
|
98
|
+
logger.debug { 'remote worker perform' }
|
96
99
|
|
97
100
|
@block.call
|
98
101
|
end
|
@@ -16,7 +16,7 @@ module Datadog
|
|
16
16
|
# Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
|
17
17
|
# Note: Telemetry does not spawn its worker thread in fork processes, thus no telemetry is sent in forked processes.
|
18
18
|
class Component
|
19
|
-
attr_reader :enabled
|
19
|
+
attr_reader :enabled, :logger
|
20
20
|
|
21
21
|
include Core::Utils::Forking
|
22
22
|
include Telemetry::Logging
|
@@ -52,6 +52,7 @@ module Datadog
|
|
52
52
|
heartbeat_interval_seconds: settings.telemetry.heartbeat_interval_seconds,
|
53
53
|
metrics_aggregation_interval_seconds: settings.telemetry.metrics_aggregation_interval_seconds,
|
54
54
|
dependency_collection: settings.telemetry.dependency_collection,
|
55
|
+
logger: logger,
|
55
56
|
shutdown_timeout_seconds: settings.telemetry.shutdown_timeout_seconds,
|
56
57
|
log_collection_enabled: settings.telemetry.log_collection_enabled
|
57
58
|
)
|
@@ -66,6 +67,7 @@ module Datadog
|
|
66
67
|
heartbeat_interval_seconds:,
|
67
68
|
metrics_aggregation_interval_seconds:,
|
68
69
|
dependency_collection:,
|
70
|
+
logger:,
|
69
71
|
http_transport:,
|
70
72
|
shutdown_timeout_seconds:,
|
71
73
|
enabled: true,
|
@@ -74,6 +76,7 @@ module Datadog
|
|
74
76
|
)
|
75
77
|
@enabled = enabled
|
76
78
|
@log_collection_enabled = log_collection_enabled
|
79
|
+
@logger = logger
|
77
80
|
|
78
81
|
@metrics_manager = MetricsManager.new(
|
79
82
|
enabled: enabled && metrics_enabled,
|
@@ -87,6 +90,7 @@ module Datadog
|
|
87
90
|
emitter: Emitter.new(http_transport: http_transport),
|
88
91
|
metrics_manager: @metrics_manager,
|
89
92
|
dependency_collection: dependency_collection,
|
93
|
+
logger: logger,
|
90
94
|
shutdown_timeout: shutdown_timeout_seconds
|
91
95
|
)
|
92
96
|
|
@@ -25,6 +25,7 @@ module Datadog
|
|
25
25
|
emitter:,
|
26
26
|
metrics_manager:,
|
27
27
|
dependency_collection:,
|
28
|
+
logger:,
|
28
29
|
enabled: true,
|
29
30
|
shutdown_timeout: Workers::Polling::DEFAULT_SHUTDOWN_TIMEOUT,
|
30
31
|
buffer_size: DEFAULT_BUFFER_MAX_SIZE
|
@@ -32,6 +33,7 @@ module Datadog
|
|
32
33
|
@emitter = emitter
|
33
34
|
@metrics_manager = metrics_manager
|
34
35
|
@dependency_collection = dependency_collection
|
36
|
+
@logger = logger
|
35
37
|
|
36
38
|
@ticks_per_heartbeat = (heartbeat_interval_seconds / metrics_aggregation_interval_seconds).to_i
|
37
39
|
@current_ticks = 0
|
@@ -48,6 +50,8 @@ module Datadog
|
|
48
50
|
self.buffer = buffer_klass.new(@buffer_size)
|
49
51
|
end
|
50
52
|
|
53
|
+
attr_reader :logger
|
54
|
+
|
51
55
|
def start
|
52
56
|
return if !enabled? || forked?
|
53
57
|
|
@@ -99,7 +103,7 @@ module Datadog
|
|
99
103
|
|
100
104
|
events = deduplicate_logs(events)
|
101
105
|
|
102
|
-
|
106
|
+
logger.debug { "Sending #{events&.count} telemetry events" }
|
103
107
|
send_event(Event::MessageBatch.new(events))
|
104
108
|
end
|
105
109
|
|
@@ -113,7 +117,7 @@ module Datadog
|
|
113
117
|
return unless enabled?
|
114
118
|
|
115
119
|
if failed_to_start?
|
116
|
-
|
120
|
+
logger.debug('Telemetry app-started event exhausted retries, disabling telemetry worker')
|
117
121
|
disable!
|
118
122
|
return
|
119
123
|
end
|
@@ -122,13 +126,13 @@ module Datadog
|
|
122
126
|
res = send_event(Event::AppStarted.new)
|
123
127
|
|
124
128
|
if res.ok?
|
125
|
-
|
129
|
+
logger.debug('Telemetry app-started event is successfully sent')
|
126
130
|
|
127
131
|
send_event(Event::AppDependenciesLoaded.new) if @dependency_collection
|
128
132
|
|
129
133
|
true
|
130
134
|
else
|
131
|
-
|
135
|
+
logger.debug('Error sending telemetry app-started event, retry after heartbeat interval...')
|
132
136
|
false
|
133
137
|
end
|
134
138
|
end
|
@@ -166,7 +170,7 @@ module Datadog
|
|
166
170
|
def disable_on_not_found!(response)
|
167
171
|
return unless response.not_found?
|
168
172
|
|
169
|
-
|
173
|
+
logger.debug('Agent does not support telemetry; disabling future telemetry events.')
|
170
174
|
disable!
|
171
175
|
end
|
172
176
|
|
data/lib/datadog/di/component.rb
CHANGED
@@ -81,8 +81,7 @@ module Datadog
|
|
81
81
|
@redactor = Redactor.new(settings)
|
82
82
|
@serializer = Serializer.new(settings, redactor, telemetry: telemetry)
|
83
83
|
@instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry)
|
84
|
-
@
|
85
|
-
@probe_notifier_worker = ProbeNotifierWorker.new(settings, transport, logger, telemetry: telemetry)
|
84
|
+
@probe_notifier_worker = ProbeNotifierWorker.new(settings, logger, agent_settings: agent_settings, telemetry: telemetry)
|
86
85
|
@probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer)
|
87
86
|
@probe_manager = ProbeManager.new(settings, instrumenter, probe_notification_builder, probe_notifier_worker, logger, telemetry: telemetry)
|
88
87
|
probe_notifier_worker.start
|
@@ -94,7 +93,6 @@ module Datadog
|
|
94
93
|
attr_reader :telemetry
|
95
94
|
attr_reader :code_tracker
|
96
95
|
attr_reader :instrumenter
|
97
|
-
attr_reader :transport
|
98
96
|
attr_reader :probe_notifier_worker
|
99
97
|
attr_reader :probe_notification_builder
|
100
98
|
attr_reader :probe_manager
|
@@ -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
|
@@ -43,6 +43,7 @@ module Datadog
|
|
43
43
|
attr_reader :settings
|
44
44
|
attr_reader :logger
|
45
45
|
attr_reader :telemetry
|
46
|
+
attr_reader :agent_settings
|
46
47
|
|
47
48
|
def start
|
48
49
|
return if @thread && @pid == Process.pid
|
@@ -154,7 +155,6 @@ module Datadog
|
|
154
155
|
|
155
156
|
private
|
156
157
|
|
157
|
-
attr_reader :transport
|
158
158
|
attr_reader :wake
|
159
159
|
attr_reader :thread
|
160
160
|
|
@@ -170,6 +170,22 @@ module Datadog
|
|
170
170
|
|
171
171
|
attr_reader :last_sent
|
172
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
|
+
|
173
189
|
[
|
174
190
|
[:status, 'probe status'],
|
175
191
|
[:snapshot, 'snapshot'],
|
@@ -245,7 +261,7 @@ module Datadog
|
|
245
261
|
if batch.any? # steep:ignore
|
246
262
|
begin
|
247
263
|
logger.trace { "di: sending #{batch.length} #{event_type} event(s) to agent" } # steep:ignore
|
248
|
-
|
264
|
+
send("do_send_#{event_type}", batch)
|
249
265
|
time = Core::Utils::Time.get_time
|
250
266
|
@lock.synchronize do
|
251
267
|
@last_sent = time
|
@@ -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
|