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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae1f5db840520c849d4a21b02232137e5272619ddd7fb46126f263c71c8a5849
4
- data.tar.gz: bd1b16b752c9e457722965ee29cf8af770ba1dcf3b42cac412c206f6245dd333
3
+ metadata.gz: 5687b95de2487329c4b7e6d6eab86704f8eb2cdcedd5588bcf11af0fdc266f7e
4
+ data.tar.gz: 837992da8e2c14754b6eb12eb6b26de83a20b68d2bdc369ba925ddd404c2d91b
5
5
  SHA512:
6
- metadata.gz: 072e88d7ba0698a8ef6b080b6b1ab6a5be18b4a69fdb142b42494bc0afc6184aadbe7c4f52e54e2373a37f40fe439215a8a9a4594653d4d6453ef614142ca8e7
7
- data.tar.gz: 88cb6087f42bc450a517d53338772b4fb10b00fe40024843fec3df3849bbc14f6efd25defaf1dcadb9224c9513878c75e2ee33fb0d3d24bb063ca1d2dd36dcb6
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.11.0...master
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
@@ -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
- Datadog.logger.debug { "new remote configuration client: #{@client.id}" }
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
- Datadog.logger.error do
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
- Datadog.logger.error do
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
- Datadog.logger.debug { "new remote configuration client: #{@client.id}" }
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
- Datadog.logger.debug { 'remote worker starting' }
26
+ logger.debug { 'remote worker starting' }
24
27
 
25
28
  acquire_lock
26
29
 
27
30
  if @stopped
28
- Datadog.logger.debug('remote worker: refusing to restart after previous stop')
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
- Datadog.logger.debug { 'remote worker started' }
47
+ logger.debug { 'remote worker started' }
45
48
  ensure
46
49
  release_lock
47
50
  end
48
51
 
49
52
  def stop
50
- Datadog.logger.debug { 'remote worker stopping' }
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
- Datadog.logger.debug { 'remote worker stopped' }
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
- Datadog.logger.debug { 'remote worker perform' }
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
- Datadog.logger.debug { "Sending #{events&.count} telemetry events" }
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
- Datadog.logger.debug('Telemetry app-started event exhausted retries, disabling telemetry worker')
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
- Datadog.logger.debug('Telemetry app-started event is successfully sent')
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
- Datadog.logger.debug('Error sending telemetry app-started event, retry after heartbeat interval...')
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
- Datadog.logger.debug('Agent does not support telemetry; disabling future telemetry events.')
173
+ logger.debug('Agent does not support telemetry; disabling future telemetry events.')
170
174
  disable!
171
175
  end
172
176
 
@@ -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
- @transport = Transport.new(agent_settings)
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, transport, logger, telemetry: nil)
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
- @transport = transport
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
- transport.public_send("send_#{event_type}", batch)
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