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.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -1
  3. data/ext/datadog_profiling_native_extension/collectors_stack.c +3 -3
  4. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +44 -1
  5. data/ext/datadog_profiling_native_extension/extconf.rb +4 -0
  6. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  7. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  9. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -0
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +7 -0
  11. data/ext/datadog_profiling_native_extension/profiling.c +7 -0
  12. data/ext/libdatadog_api/crashtracker.c +4 -4
  13. data/ext/libdatadog_extconf_helpers.rb +1 -1
  14. data/lib/datadog/appsec/configuration/settings.rb +64 -11
  15. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +23 -6
  16. data/lib/datadog/appsec/contrib/active_record/patcher.rb +63 -15
  17. data/lib/datadog/appsec/contrib/devise/configuration.rb +76 -0
  18. data/lib/datadog/appsec/contrib/devise/event.rb +4 -7
  19. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +16 -21
  20. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +8 -15
  21. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +1 -1
  22. data/lib/datadog/appsec/contrib/devise/patcher.rb +0 -3
  23. data/lib/datadog/appsec/contrib/devise/tracking.rb +1 -1
  24. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  25. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  26. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +43 -0
  27. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  28. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  29. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  30. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  31. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
  32. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +10 -12
  33. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  34. data/lib/datadog/appsec/contrib/rack/ext.rb +20 -0
  35. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +84 -72
  36. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  37. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -0
  38. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +20 -25
  39. data/lib/datadog/appsec/contrib/rails/patcher.rb +0 -3
  40. data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
  41. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
  42. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +39 -0
  43. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +38 -49
  44. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +0 -3
  45. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  46. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
  47. data/lib/datadog/appsec/monitor/gateway/watcher.rb +19 -25
  48. data/lib/datadog/appsec/processor/rule_merger.rb +2 -1
  49. data/lib/datadog/appsec/remote.rb +11 -0
  50. data/lib/datadog/appsec.rb +3 -0
  51. data/lib/datadog/core/configuration/components.rb +17 -10
  52. data/lib/datadog/core/configuration/ext.rb +1 -1
  53. data/lib/datadog/core/configuration/option_definition.rb +2 -0
  54. data/lib/datadog/core/configuration/settings.rb +22 -6
  55. data/lib/datadog/core/encoding.rb +16 -0
  56. data/lib/datadog/core/environment/agent_info.rb +77 -0
  57. data/lib/datadog/core/metrics/client.rb +9 -8
  58. data/lib/datadog/core/remote/client.rb +5 -4
  59. data/lib/datadog/core/remote/component.rb +14 -12
  60. data/lib/datadog/core/remote/negotiation.rb +1 -1
  61. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  62. data/lib/datadog/core/remote/transport/http/config.rb +0 -18
  63. data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -18
  64. data/lib/datadog/core/remote/transport/http.rb +6 -40
  65. data/lib/datadog/core/remote/transport/negotiation.rb +13 -1
  66. data/lib/datadog/core/remote/worker.rb +10 -7
  67. data/lib/datadog/core/telemetry/component.rb +5 -1
  68. data/lib/datadog/core/telemetry/event.rb +5 -0
  69. data/lib/datadog/core/telemetry/worker.rb +9 -5
  70. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  71. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +1 -1
  72. data/lib/datadog/{tracing → core}/transport/http/api/spec.rb +1 -1
  73. data/lib/datadog/{tracing → core}/transport/http/builder.rb +37 -17
  74. data/lib/datadog/core/transport/http.rb +38 -0
  75. data/lib/datadog/core/transport/response.rb +4 -0
  76. data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
  77. data/lib/datadog/di/code_tracker.rb +15 -8
  78. data/lib/datadog/di/component.rb +2 -3
  79. data/lib/datadog/di/configuration/settings.rb +14 -0
  80. data/lib/datadog/di/contrib.rb +2 -0
  81. data/lib/datadog/di/logger.rb +30 -0
  82. data/lib/datadog/di/probe.rb +3 -6
  83. data/lib/datadog/di/probe_manager.rb +5 -2
  84. data/lib/datadog/di/probe_notifier_worker.rb +35 -8
  85. data/lib/datadog/di/remote.rb +3 -3
  86. data/lib/datadog/di/transport/diagnostics.rb +61 -0
  87. data/lib/datadog/di/transport/http/api.rb +52 -0
  88. data/lib/datadog/di/transport/http/client.rb +46 -0
  89. data/lib/datadog/di/transport/http/diagnostics.rb +92 -0
  90. data/lib/datadog/di/transport/http/input.rb +94 -0
  91. data/lib/datadog/di/transport/http.rb +105 -0
  92. data/lib/datadog/di/transport/input.rb +61 -0
  93. data/lib/datadog/di/utils.rb +91 -0
  94. data/lib/datadog/di.rb +5 -1
  95. data/lib/datadog/profiling/component.rb +2 -8
  96. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  97. data/lib/datadog/tracing/component.rb +1 -0
  98. data/lib/datadog/tracing/configuration/ext.rb +1 -0
  99. data/lib/datadog/tracing/contrib/extensions.rb +14 -0
  100. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  101. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  102. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  103. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  104. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  105. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  106. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  107. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  108. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  109. data/lib/datadog/tracing/metadata.rb +2 -0
  110. data/lib/datadog/tracing/span.rb +10 -1
  111. data/lib/datadog/tracing/span_operation.rb +6 -1
  112. data/lib/datadog/tracing/sync_writer.rb +9 -4
  113. data/lib/datadog/tracing/tracer.rb +15 -7
  114. data/lib/datadog/tracing/transport/http/api.rb +11 -2
  115. data/lib/datadog/tracing/transport/http/traces.rb +0 -3
  116. data/lib/datadog/tracing/transport/http.rb +7 -31
  117. data/lib/datadog/tracing/transport/serializable_trace.rb +11 -5
  118. data/lib/datadog/tracing/transport/traces.rb +25 -8
  119. data/lib/datadog/tracing/workers/trace_writer.rb +10 -3
  120. data/lib/datadog/tracing/workers.rb +5 -4
  121. data/lib/datadog/tracing/writer.rb +12 -4
  122. data/lib/datadog/version.rb +2 -2
  123. metadata +37 -29
  124. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  125. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  126. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  127. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  128. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  129. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  130. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  131. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  132. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  133. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  134. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  135. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  136. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  137. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  138. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  139. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
  140. data/lib/datadog/di/transport.rb +0 -79
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Metadata
8
+ # This class is a data structure that is used to store
9
+ # complex metadata, such as an array of objects.
10
+ #
11
+ # It is serialized to MessagePack format when sent to the agent.
12
+ class Metastruct
13
+ extend Forwardable
14
+
15
+ def_delegators :@metastruct, :[], :[]=, :to_h
16
+
17
+ def initialize
18
+ @metastruct = {}
19
+ end
20
+
21
+ def to_msgpack(packer = nil)
22
+ # JRuby doesn't pass the packer
23
+ packer ||= MessagePack::Packer.new
24
+
25
+ packer.write(@metastruct.transform_values(&:to_msgpack))
26
+ end
27
+
28
+ def pretty_print(q)
29
+ q.seplist @metastruct.each do |key, value|
30
+ q.text "#{key} => #{value}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'metastruct'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Metadata
8
+ # Adds data storage for the `meta_struct` field.
9
+ #
10
+ # This field is used to send more complex data like an array of objects
11
+ # in MessagePack format to the agent, and has no size limitations.
12
+ #
13
+ # The agent fully supports meta_struct from version v7.35.0 (April 2022).
14
+ #
15
+ # On versions older than v7.35.0, sending traces containing meta_struct
16
+ # has no unexpected side-effects; traces are sent to the backend as expected,
17
+ # while the meta_struct field is stripped.
18
+ module MetastructTagging
19
+ # Set the given key / value tag pair on the metastruct.
20
+ #
21
+ # A valid example is:
22
+ #
23
+ # span.set_metastruct_tag('_dd.stack', [])
24
+ def set_metastruct_tag(key, value)
25
+ metastruct[key] = value
26
+ end
27
+
28
+ # Return the metastruct tag value for the given key,
29
+ # returns nil if the key doesn't exist.
30
+ def get_metastruct_tag(key)
31
+ metastruct[key]
32
+ end
33
+
34
+ private
35
+
36
+ def metastruct
37
+ @metastruct ||= Metastruct.new
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'metadata/analytics'
4
4
  require_relative 'metadata/tagging'
5
+ require_relative 'metadata/metastruct_tagging'
5
6
  require_relative 'metadata/errors'
6
7
 
7
8
  module Datadog
@@ -10,6 +11,7 @@ module Datadog
10
11
  module Metadata
11
12
  def self.included(base)
12
13
  base.include(Metadata::Tagging)
14
+ base.include(Metadata::MetastructTagging)
13
15
  base.include(Metadata::Errors)
14
16
 
15
17
  # Additional extensions
@@ -33,6 +33,9 @@ module Datadog
33
33
  :status,
34
34
  :trace_id
35
35
 
36
+ attr_reader \
37
+ :metastruct
38
+
36
39
  attr_writer \
37
40
  :duration
38
41
 
@@ -54,6 +57,7 @@ module Datadog
54
57
  id: nil,
55
58
  meta: nil,
56
59
  metrics: nil,
60
+ metastruct: nil,
57
61
  parent_id: 0,
58
62
  resource: name,
59
63
  service: nil,
@@ -76,6 +80,7 @@ module Datadog
76
80
 
77
81
  @meta = meta || {}
78
82
  @metrics = metrics || {}
83
+ @metastruct = metastruct || {}
79
84
  @status = status || 0
80
85
 
81
86
  # start_time and end_time track wall clock. In Ruby, wall clock
@@ -144,6 +149,7 @@ module Datadog
144
149
  error: @status,
145
150
  meta: @meta,
146
151
  metrics: @metrics,
152
+ meta_struct: @metastruct.to_h,
147
153
  name: @name,
148
154
  parent_id: @parent_id,
149
155
  resource: @resource,
@@ -185,12 +191,15 @@ module Datadog
185
191
  q.text "#{key} => #{value}"
186
192
  end
187
193
  end
188
- q.group(2, 'Metrics: [', ']') do
194
+ q.group(2, 'Metrics: [', "]\n") do
189
195
  q.breakable
190
196
  q.seplist @metrics.each do |key, value|
191
197
  q.text "#{key} => #{value}"
192
198
  end
193
199
  end
200
+ q.group(2, 'Metastruct: [', ']') do
201
+ metastruct.pretty_print(q)
202
+ end
194
203
  end
195
204
  end
196
205
 
@@ -289,6 +289,7 @@ module Datadog
289
289
  id: @id,
290
290
  meta: meta,
291
291
  metrics: metrics,
292
+ metastruct: metastruct,
292
293
  name: @name,
293
294
  parent_id: @parent_id,
294
295
  resource: @resource,
@@ -328,12 +329,15 @@ module Datadog
328
329
  q.text "#{key} => #{value}"
329
330
  end
330
331
  end
331
- q.group(2, 'Metrics: [', ']') do
332
+ q.group(2, 'Metrics: [', "]\n") do
332
333
  q.breakable
333
334
  q.seplist metrics.each do |key, value|
334
335
  q.text "#{key} => #{value}"
335
336
  end
336
337
  end
338
+ q.group(2, 'Metastruct: [', ']') do
339
+ metastruct.pretty_print(q)
340
+ end
337
341
  end
338
342
  end
339
343
 
@@ -456,6 +460,7 @@ module Datadog
456
460
  id: @id,
457
461
  meta: Core::Utils::SafeDup.frozen_or_dup(meta),
458
462
  metrics: Core::Utils::SafeDup.frozen_or_dup(metrics),
463
+ metastruct: Core::Utils::SafeDup.frozen_or_dup(metastruct),
459
464
  parent_id: @parent_id,
460
465
  resource: @resource,
461
466
  service: @service,
@@ -17,17 +17,22 @@ module Datadog
17
17
  # @public_api
18
18
  class SyncWriter
19
19
  attr_reader \
20
+ :logger,
20
21
  :events,
21
- :transport
22
+ :transport,
23
+ :agent_settings
22
24
 
23
25
  # @param [Datadog::Tracing::Transport::Traces::Transport] transport a custom transport instance.
24
26
  # If provided, overrides `transport_options` and `agent_settings`.
25
27
  # @param [Hash<Symbol,Object>] transport_options options for the default transport instance.
26
28
  # @param [Datadog::Tracing::Configuration::AgentSettingsResolver::AgentSettings] agent_settings agent options for
27
29
  # the default transport instance.
28
- def initialize(transport: nil, transport_options: {}, agent_settings: nil)
30
+ def initialize(transport: nil, transport_options: {}, agent_settings: nil, logger: Datadog.logger)
31
+ @logger = logger
32
+ @agent_settings = agent_settings
33
+
29
34
  @transport = transport || begin
30
- transport_options[:agent_settings] = agent_settings if agent_settings
35
+ transport_options = transport_options.merge(agent_settings: agent_settings) if agent_settings
31
36
  Transport::HTTP.default(**transport_options)
32
37
  end
33
38
 
@@ -40,7 +45,7 @@ module Datadog
40
45
  def write(trace)
41
46
  flush_trace(trace)
42
47
  rescue => e
43
- Datadog.logger.debug(e)
48
+ logger.debug(e)
44
49
  end
45
50
 
46
51
  # Does nothing.
@@ -28,7 +28,8 @@ module Datadog
28
28
  :provider,
29
29
  :sampler,
30
30
  :span_sampler,
31
- :tags
31
+ :tags,
32
+ :logger
32
33
 
33
34
  attr_accessor \
34
35
  :default_service,
@@ -48,21 +49,28 @@ module Datadog
48
49
  # @param tags [Hash] default tags added to all spans
49
50
  # @param writer [Datadog::Tracing::Writer] consumes traces returned by the provided +trace_flush+
50
51
  def initialize(
52
+ # rubocop:disable Style/KeywordParametersOrder
53
+ # https://github.com/rubocop/rubocop/issues/13933
51
54
  trace_flush: Flush::Finished.new,
52
55
  context_provider: DefaultContextProvider.new,
53
56
  default_service: Core::Environment::Ext::FALLBACK_SERVICE_NAME,
54
57
  enabled: true,
58
+ logger: Datadog.logger,
55
59
  sampler: Sampling::PrioritySampler.new(
56
60
  base_sampler: Sampling::AllSampler.new,
57
61
  post_sampler: Sampling::RuleSampler.new
58
62
  ),
59
63
  span_sampler: Sampling::Span::Sampler.new,
60
64
  tags: {},
61
- writer: Writer.new
65
+ # writer is not defaulted because creating it requires agent_settings,
66
+ # which we do not have here and otherwise do not need.
67
+ writer:
68
+ # rubocop:enable Style/KeywordParametersOrder
62
69
  )
63
70
  @trace_flush = trace_flush
64
71
  @default_service = default_service
65
72
  @enabled = enabled
73
+ @logger = logger
66
74
  @provider = context_provider
67
75
  @sampler = sampler
68
76
  @span_sampler = span_sampler
@@ -146,7 +154,7 @@ module Datadog
146
154
  active_trace
147
155
  end
148
156
  rescue StandardError => e
149
- Datadog.logger.debug { "Failed to trace: #{e}" }
157
+ logger.debug { "Failed to trace: #{e}" }
150
158
 
151
159
  # Tracing failed: fallback and run code without tracing.
152
160
  return skip_trace(name, &block)
@@ -268,7 +276,7 @@ module Datadog
268
276
  @sampler.sample!(trace_op)
269
277
  rescue StandardError => e
270
278
  SAMPLE_TRACE_LOG_ONLY_ONCE.run do
271
- Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
279
+ logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
272
280
  end
273
281
  end
274
282
  end
@@ -488,7 +496,7 @@ module Datadog
488
496
  @span_sampler.sample!(trace_op, span)
489
497
  rescue StandardError => e
490
498
  SAMPLE_SPAN_LOG_ONLY_ONCE.run do
491
- Datadog.logger.warn { "Failed to sample span: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
499
+ logger.warn { "Failed to sample span: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
492
500
  end
493
501
  end
494
502
  end
@@ -504,7 +512,7 @@ module Datadog
504
512
  write(trace) if trace && !trace.empty?
505
513
  rescue StandardError => e
506
514
  FLUSH_TRACE_LOG_ONLY_ONCE.run do
507
- Datadog.logger.warn { "Failed to flush trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
515
+ logger.warn { "Failed to flush trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
508
516
  end
509
517
  end
510
518
  end
@@ -518,7 +526,7 @@ module Datadog
518
526
  return unless trace && @writer
519
527
 
520
528
  if Datadog.configuration.diagnostics.debug
521
- Datadog.logger.debug { "Writing #{trace.length} spans (enabled: #{@enabled})\n#{trace.spans.pretty_inspect}" }
529
+ logger.debug { "Writing #{trace.length} spans (enabled: #{@enabled})\n#{trace.spans.pretty_inspect}" }
522
530
  end
523
531
 
524
532
  @writer.write(trace)
@@ -3,7 +3,8 @@
3
3
  require_relative '../../../core/encoding'
4
4
 
5
5
  require_relative '../../../core/transport/http/api/map'
6
- require_relative 'api/spec'
6
+ require_relative '../../../core/transport/http/api/instance'
7
+ require_relative '../../../core/transport/http/api/spec'
7
8
 
8
9
  require_relative 'traces'
9
10
 
@@ -20,7 +21,7 @@ module Datadog
20
21
  module_function
21
22
 
22
23
  def defaults
23
- Datadog::Core::Transport::HTTP::API::Map[
24
+ Core::Transport::HTTP::API::Map[
24
25
  V4 => Spec.new do |s|
25
26
  s.traces = Traces::API::Endpoint.new(
26
27
  '/v0.4/traces',
@@ -36,6 +37,14 @@ module Datadog
36
37
  end,
37
38
  ].with_fallbacks(V4 => V3)
38
39
  end
40
+
41
+ class Instance < Core::Transport::HTTP::API::Instance
42
+ include Traces::API::Instance
43
+ end
44
+
45
+ class Spec < Core::Transport::HTTP::API::Spec
46
+ include Traces::API::Spec
47
+ end
39
48
  end
40
49
  end
41
50
  end
@@ -6,7 +6,6 @@ require_relative '../traces'
6
6
  require_relative 'client'
7
7
  require_relative '../../../core/transport/http/response'
8
8
  require_relative '../../../core/transport/http/api/endpoint'
9
- require_relative 'api/instance'
10
9
 
11
10
  module Datadog
12
11
  module Tracing
@@ -143,8 +142,6 @@ module Datadog
143
142
 
144
143
  # Add traces behavior to transport components
145
144
  HTTP::Client.include(Traces::Client)
146
- HTTP::API::Spec.include(Traces::API::Spec)
147
- HTTP::API::Instance.include(Traces::API::Instance)
148
145
  end
149
146
  end
150
147
  end
@@ -1,15 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'uri'
4
-
5
3
  require_relative '../../core/environment/container'
6
4
  require_relative '../../core/environment/ext'
7
5
  require_relative '../../core/transport/ext'
8
- require_relative '../../core/transport/http/adapters/net'
9
- require_relative '../../core/transport/http/adapters/test'
10
- require_relative '../../core/transport/http/adapters/unix_socket'
6
+ require_relative '../../core/transport/http'
11
7
  require_relative 'http/api'
12
- require_relative 'http/builder'
13
8
  require_relative '../../../datadog/version'
14
9
 
15
10
  module Datadog
@@ -17,30 +12,22 @@ module Datadog
17
12
  module Transport
18
13
  # Namespace for HTTP transport components
19
14
  module HTTP
20
- # NOTE: Due to... legacy reasons... This class likes having a default `AgentSettings` instance to fall back to.
21
- # Because we generate this instance with an empty instance of `Settings`, the resulting `AgentSettings` below
22
- # represents only settings specified via environment variables + the usual defaults.
23
- #
24
- # DO NOT USE THIS IN NEW CODE, as it ignores any settings specified by users via `Datadog.configure`.
25
- DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS = Datadog::Core::Configuration::AgentSettingsResolver.call(
26
- Datadog::Core::Configuration::Settings.new,
27
- logger: nil,
28
- )
29
-
30
15
  module_function
31
16
 
32
17
  # Builds a new Transport::HTTP::Client
33
- def new(&block)
34
- Builder.new(&block).to_transport
18
+ def new(klass, &block)
19
+ Core::Transport::HTTP.build(
20
+ api_instance_class: API::Instance, &block
21
+ ).to_transport(klass)
35
22
  end
36
23
 
37
24
  # Builds a new Transport::HTTP::Client with default settings
38
25
  # Pass a block to override any settings.
39
26
  def default(
40
- agent_settings: DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS,
27
+ agent_settings:,
41
28
  **options
42
29
  )
43
- new do |transport|
30
+ new(Transport::Traces::Transport) do |transport|
44
31
  transport.adapter(agent_settings)
45
32
  transport.headers default_headers
46
33
 
@@ -84,17 +71,6 @@ module Datadog
84
71
  def default_adapter
85
72
  Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
86
73
  end
87
-
88
- # Add adapters to registry
89
- Builder::REGISTRY.set(
90
- Datadog::Core::Transport::HTTP::Adapters::Net,
91
- Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
92
- )
93
- Builder::REGISTRY.set(Datadog::Core::Transport::HTTP::Adapters::Test, Datadog::Core::Transport::Ext::Test::ADAPTER)
94
- Builder::REGISTRY.set(
95
- Datadog::Core::Transport::HTTP::Adapters::UnixSocket,
96
- Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
97
- )
98
74
  end
99
75
  end
100
76
  end
@@ -14,7 +14,7 @@ module Datadog
14
14
 
15
15
  # @param trace [Datadog::Trace] the trace to serialize
16
16
  # @param native_events_supported [Boolean] whether the agent supports span events as a top-level field
17
- def initialize(trace, native_events_supported = false)
17
+ def initialize(trace, native_events_supported:)
18
18
  @trace = trace
19
19
  @native_events_supported = native_events_supported
20
20
  end
@@ -29,13 +29,17 @@ module Datadog
29
29
  # @param packer [MessagePack::Packer] serialization buffer, can be +nil+ with JRuby
30
30
  def to_msgpack(packer = nil)
31
31
  # As of 1.3.3, JRuby implementation doesn't pass an existing packer
32
- trace.spans.map { |s| SerializableSpan.new(s, @native_events_supported) }.to_msgpack(packer)
32
+ trace.spans.map do |s|
33
+ SerializableSpan.new(s, native_events_supported: @native_events_supported)
34
+ end.to_msgpack(packer)
33
35
  end
34
36
 
35
37
  # JSON serializer interface.
36
38
  # Used by older version of the transport.
37
39
  def to_json(*args)
38
- trace.spans.map { |s| SerializableSpan.new(s, @native_events_supported).to_hash }.to_json(*args)
40
+ trace.spans.map do |s|
41
+ SerializableSpan.new(s, native_events_supported: @native_events_supported).to_hash
42
+ end.to_json(*args)
39
43
  end
40
44
  end
41
45
 
@@ -46,7 +50,7 @@ module Datadog
46
50
 
47
51
  # @param span [Datadog::Span] the span to serialize
48
52
  # @param native_events_supported [Boolean] whether the agent supports span events as a top-level field
49
- def initialize(span, native_events_supported)
53
+ def initialize(span, native_events_supported:)
50
54
  @span = span
51
55
  @trace_id = Tracing::Utils::TraceId.to_low_order(span.trace_id)
52
56
  @native_events_supported = native_events_supported
@@ -65,7 +69,7 @@ module Datadog
65
69
  def to_msgpack(packer = nil)
66
70
  packer ||= MessagePack::Packer.new
67
71
 
68
- number_of_elements_to_write = 11
72
+ number_of_elements_to_write = 12
69
73
 
70
74
  number_of_elements_to_write += 1 if span.events.any? && @native_events_supported
71
75
 
@@ -113,6 +117,8 @@ module Datadog
113
117
  packer.write(span.meta)
114
118
  packer.write('metrics')
115
119
  packer.write(span.metrics)
120
+ packer.write('meta_struct')
121
+ packer.write(span.metastruct)
116
122
  packer.write('span_links')
117
123
  packer.write(span.links.map(&:to_hash))
118
124
  packer.write('error')
@@ -50,8 +50,9 @@ module Datadog
50
50
  #
51
51
  # @param encoder [Datadog::Core::Encoding::Encoder]
52
52
  # @param max_size [String] maximum acceptable payload size
53
- def initialize(encoder, max_size: DEFAULT_MAX_PAYLOAD_SIZE)
53
+ def initialize(encoder, native_events_supported:, max_size: DEFAULT_MAX_PAYLOAD_SIZE)
54
54
  @encoder = encoder
55
+ @native_events_supported = native_events_supported
55
56
  @max_size = max_size
56
57
  end
57
58
 
@@ -77,7 +78,7 @@ module Datadog
77
78
  private
78
79
 
79
80
  def encode_one(trace)
80
- encoded = Encoder.encode_trace(encoder, trace)
81
+ encoded = Encoder.encode_trace(encoder, trace, native_events_supported: @native_events_supported)
81
82
 
82
83
  if encoded.size > max_size
83
84
  # This single trace is too large, we can't flush it
@@ -95,17 +96,18 @@ module Datadog
95
96
  module Encoder
96
97
  module_function
97
98
 
98
- def encode_trace(encoder, trace)
99
+ def encode_trace(encoder, trace, native_events_supported:)
99
100
  # Format the trace for transport
100
101
  TraceFormatter.format!(trace)
101
102
 
102
103
  # Make the trace serializable
103
- serializable_trace = SerializableTrace.new(trace)
104
-
105
- Datadog.logger.debug { "Flushing trace: #{JSON.dump(serializable_trace)}" }
104
+ serializable_trace = SerializableTrace.new(trace, native_events_supported: native_events_supported)
106
105
 
107
106
  # Encode the trace
108
- encoder.encode(serializable_trace)
107
+ encoder.encode(serializable_trace).tap do |encoded|
108
+ # Print the actual serialized trace, since the encoder can change make non-trivial changes
109
+ Datadog.logger.debug { "Flushing trace: #{encoder.decode(encoded)}" }
110
+ end
109
111
  end
110
112
  end
111
113
 
@@ -126,7 +128,10 @@ module Datadog
126
128
 
127
129
  def send_traces(traces)
128
130
  encoder = current_api.encoder
129
- chunker = Datadog::Tracing::Transport::Traces::Chunker.new(encoder)
131
+ chunker = Datadog::Tracing::Transport::Traces::Chunker.new(
132
+ encoder,
133
+ native_events_supported: native_events_supported?
134
+ )
130
135
 
131
136
  responses = chunker.encode_in_chunks(traces.lazy).map do |encoded_traces, trace_count|
132
137
  request = Request.new(EncodedParcel.new(encoded_traces, trace_count))
@@ -188,6 +193,18 @@ module Datadog
188
193
  @client = HTTP::Client.new(current_api)
189
194
  end
190
195
 
196
+ # Queries the agent for native span events serialization support.
197
+ # This changes how the serialization of span events performed.
198
+ def native_events_supported?
199
+ return @native_events_supported if defined?(@native_events_supported)
200
+
201
+ if (res = Datadog.send(:components).agent_info.fetch)
202
+ @native_events_supported = res.span_events == true
203
+ else
204
+ false
205
+ end
206
+ end
207
+
191
208
  # Raised when configured with an unknown API version
192
209
  class UnknownApiVersionError < StandardError
193
210
  attr_reader :version
@@ -17,13 +17,20 @@ module Datadog
17
17
  # Writes traces to transport synchronously
18
18
  class TraceWriter < Core::Worker
19
19
  attr_reader \
20
- :transport
20
+ :logger,
21
+ :transport,
22
+ :agent_settings
21
23
 
22
24
  # rubocop:disable Lint/MissingSuper
23
25
  def initialize(options = {})
26
+ @logger = options[:logger] || Datadog.logger
27
+
24
28
  transport_options = options.fetch(:transport_options, {})
25
29
 
26
- transport_options[:agent_settings] = options[:agent_settings] if options.key?(:agent_settings)
30
+ if options.key?(:agent_settings)
31
+ @agent_settings = options[:agent_settings]
32
+ transport_options = transport_options.merge(agent_settings: @agent_settings)
33
+ end
27
34
 
28
35
  @transport = options.fetch(:transport) do
29
36
  Datadog::Tracing::Transport::HTTP.default(**transport_options)
@@ -43,7 +50,7 @@ module Datadog
43
50
  traces = process_traces(traces)
44
51
  flush_traces(traces)
45
52
  rescue StandardError => e
46
- Datadog.logger.warn(
53
+ logger.warn(
47
54
  "Error while writing traces: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
48
55
  )
49
56
  end
@@ -18,8 +18,7 @@ module Datadog
18
18
  BACK_OFF_MAX = 5
19
19
  DEFAULT_SHUTDOWN_TIMEOUT = 1
20
20
 
21
- attr_reader \
22
- :trace_buffer
21
+ attr_reader :trace_buffer, :logger
23
22
 
24
23
  def initialize(options = {})
25
24
  @transport = options[:transport]
@@ -42,6 +41,8 @@ module Datadog
42
41
  @mutex = Mutex.new
43
42
  @worker = nil
44
43
  @run = false
44
+
45
+ @logger = options.fetch(:logger)
45
46
  end
46
47
 
47
48
  # Callback function that process traces and executes the +send_traces()+ method.
@@ -56,7 +57,7 @@ module Datadog
56
57
  # ensures that the thread will not die because of an exception.
57
58
  # TODO[manu]: findout the reason and reschedule the send if it's not
58
59
  # a fatal exception
59
- Datadog.logger.warn(
60
+ logger.warn(
60
61
  "Error during traces flush: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
61
62
  )
62
63
  end
@@ -68,7 +69,7 @@ module Datadog
68
69
  return if @run
69
70
 
70
71
  @run = true
71
- Datadog.logger.debug { "Starting thread for: #{self}" }
72
+ logger.debug { "Starting thread for: #{self}" }
72
73
  @worker = Thread.new { perform }
73
74
  @worker.name = self.class.name
74
75
  @worker.thread_variable_set(:fork_safe, true)
@@ -13,17 +13,24 @@ module Datadog
13
13
  # @public_api
14
14
  class Writer
15
15
  attr_reader \
16
+ :logger,
16
17
  :transport,
17
18
  :worker,
18
- :events
19
+ :events,
20
+ :agent_settings
19
21
 
20
22
  def initialize(options = {})
23
+ @logger = options[:logger] || Datadog.logger
24
+
21
25
  # writer and transport parameters
22
26
  @buff_size = options.fetch(:buffer_size, Workers::AsyncTransport::DEFAULT_BUFFER_MAX_SIZE)
23
27
  @flush_interval = options.fetch(:flush_interval, Workers::AsyncTransport::DEFAULT_FLUSH_INTERVAL)
24
28
  transport_options = options.fetch(:transport_options, {})
25
29
 
26
- transport_options[:agent_settings] = options[:agent_settings] if options.key?(:agent_settings)
30
+ if options.key?(:agent_settings)
31
+ @agent_settings = options[:agent_settings]
32
+ transport_options = transport_options.merge(agent_settings: @agent_settings)
33
+ end
27
34
 
28
35
  # transport and buffers
29
36
  @transport = options.fetch(:transport) do
@@ -119,7 +126,7 @@ module Datadog
119
126
  if worker_local
120
127
  worker_local.enqueue_trace(trace)
121
128
  elsif !@stopped
122
- Datadog.logger.debug('Writer either failed to start or was stopped before #write could complete')
129
+ logger.debug('Writer either failed to start or was stopped before #write could complete')
123
130
  end
124
131
  end
125
132
 
@@ -160,7 +167,8 @@ module Datadog
160
167
  buffer_size: @buff_size,
161
168
  on_trace: @trace_handler,
162
169
  interval: @flush_interval,
163
- shutdown_timeout: @shutdown_timeout
170
+ shutdown_timeout: @shutdown_timeout,
171
+ logger: logger,
164
172
  )
165
173
 
166
174
  @worker.start
@@ -3,8 +3,8 @@
3
3
  module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 10
7
- PATCH = 0
6
+ MINOR = 12
7
+ PATCH = 2
8
8
  PRE = nil
9
9
  BUILD = nil
10
10
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow