datadog 2.12.2 → 2.13.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -1
  3. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +14 -13
  4. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  5. data/lib/datadog/appsec/actions_handler.rb +22 -1
  6. data/lib/datadog/appsec/anonymizer.rb +16 -0
  7. data/lib/datadog/appsec/configuration/settings.rb +62 -10
  8. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  9. data/lib/datadog/appsec/contrib/devise/configuration.rb +7 -31
  10. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +79 -0
  11. data/lib/datadog/appsec/contrib/devise/ext.rb +21 -0
  12. data/lib/datadog/appsec/contrib/devise/integration.rb +0 -1
  13. data/lib/datadog/appsec/contrib/devise/patcher.rb +36 -23
  14. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  15. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  16. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +2 -2
  17. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +93 -0
  18. data/lib/datadog/appsec/contrib/rack/ext.rb +14 -0
  19. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +10 -3
  20. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +0 -2
  21. data/lib/datadog/appsec/event.rb +1 -1
  22. data/lib/datadog/appsec/ext.rb +4 -2
  23. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +4 -2
  24. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -3
  25. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  26. data/lib/datadog/appsec/utils.rb +0 -2
  27. data/lib/datadog/core/configuration/components.rb +2 -1
  28. data/lib/datadog/core/configuration/ext.rb +4 -0
  29. data/lib/datadog/core/configuration/options.rb +2 -2
  30. data/lib/datadog/core/configuration/settings.rb +53 -30
  31. data/lib/datadog/core/environment/agent_info.rb +4 -3
  32. data/lib/datadog/core/remote/component.rb +3 -6
  33. data/lib/datadog/core/remote/configuration/repository.rb +2 -1
  34. data/lib/datadog/core/remote/negotiation.rb +9 -9
  35. data/lib/datadog/core/remote/transport/config.rb +4 -3
  36. data/lib/datadog/core/remote/transport/http/client.rb +4 -3
  37. data/lib/datadog/core/remote/transport/http/config.rb +6 -32
  38. data/lib/datadog/core/remote/transport/http/negotiation.rb +6 -32
  39. data/lib/datadog/core/remote/transport/http.rb +22 -57
  40. data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
  41. data/lib/datadog/core/runtime/metrics.rb +8 -1
  42. data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
  43. data/lib/datadog/core/transport/http/api/instance.rb +17 -0
  44. data/lib/datadog/core/transport/http/api/spec.rb +17 -0
  45. data/lib/datadog/core/transport/http/builder.rb +5 -3
  46. data/lib/datadog/core/transport/http.rb +39 -2
  47. data/lib/datadog/di/component.rb +0 -2
  48. data/lib/datadog/di/probe_notifier_worker.rb +16 -16
  49. data/lib/datadog/di/transport/diagnostics.rb +4 -3
  50. data/lib/datadog/di/transport/http/api.rb +2 -12
  51. data/lib/datadog/di/transport/http/client.rb +4 -3
  52. data/lib/datadog/di/transport/http/diagnostics.rb +7 -33
  53. data/lib/datadog/di/transport/http/input.rb +7 -33
  54. data/lib/datadog/di/transport/http.rb +14 -56
  55. data/lib/datadog/di/transport/input.rb +4 -3
  56. data/lib/datadog/di/utils.rb +5 -0
  57. data/lib/datadog/kit/appsec/events.rb +9 -0
  58. data/lib/datadog/kit/identity.rb +5 -1
  59. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  60. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  61. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  62. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  63. data/lib/datadog/opentelemetry.rb +2 -1
  64. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  65. data/lib/datadog/profiling.rb +5 -2
  66. data/lib/datadog/tracing/component.rb +15 -12
  67. data/lib/datadog/tracing/configuration/ext.rb +7 -1
  68. data/lib/datadog/tracing/configuration/settings.rb +18 -2
  69. data/lib/datadog/tracing/context_provider.rb +1 -1
  70. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  71. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  72. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  73. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  74. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  75. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  76. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  77. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  78. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -5
  79. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -11
  80. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +6 -10
  81. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  82. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  83. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  84. data/lib/datadog/tracing/correlation.rb +9 -2
  85. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  86. data/lib/datadog/tracing/distributed/datadog.rb +2 -0
  87. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  88. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  89. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  90. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  91. data/lib/datadog/tracing/span_operation.rb +2 -1
  92. data/lib/datadog/tracing/sync_writer.rb +1 -2
  93. data/lib/datadog/tracing/trace_digest.rb +9 -2
  94. data/lib/datadog/tracing/trace_operation.rb +29 -17
  95. data/lib/datadog/tracing/trace_segment.rb +6 -4
  96. data/lib/datadog/tracing/tracer.rb +38 -2
  97. data/lib/datadog/tracing/transport/http/api.rb +2 -10
  98. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  99. data/lib/datadog/tracing/transport/http/traces.rb +13 -41
  100. data/lib/datadog/tracing/transport/http.rb +11 -44
  101. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  102. data/lib/datadog/tracing/transport/traces.rb +21 -9
  103. data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
  104. data/lib/datadog/tracing/writer.rb +2 -6
  105. data/lib/datadog/tracing.rb +16 -3
  106. data/lib/datadog/version.rb +2 -2
  107. metadata +17 -13
  108. data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
  109. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
  110. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
  111. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  112. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  113. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
@@ -80,6 +80,9 @@ module Datadog
80
80
  # This allows later propagation to include those unknown fields, as they can represent future versions of the spec
81
81
  # sending data through this service. This value ends in a trailing `;` to facilitate serialization.
82
82
  # @return [String]
83
+ # @!attribute [r] baggage
84
+ # The W3C "baggage" extracted from a distributed context. This field is a hash of key/value pairs.
85
+ # @return [Hash<String,String>]
83
86
  # TODO: The documentation for the last attribute above won't be rendered.
84
87
  # TODO: This might be a YARD bug as adding an attribute, making it now second-last attribute, renders correctly.
85
88
  attr_reader \
@@ -102,7 +105,8 @@ module Datadog
102
105
  :trace_flags,
103
106
  :trace_state,
104
107
  :trace_state_unknown_fields,
105
- :span_remote
108
+ :span_remote,
109
+ :baggage
106
110
 
107
111
  def initialize(
108
112
  span_id: nil,
@@ -124,7 +128,8 @@ module Datadog
124
128
  trace_flags: nil,
125
129
  trace_state: nil,
126
130
  trace_state_unknown_fields: nil,
127
- span_remote: true
131
+ span_remote: true,
132
+ baggage: nil
128
133
  )
129
134
  @span_id = span_id
130
135
  @span_name = span_name && span_name.dup.freeze
@@ -146,6 +151,7 @@ module Datadog
146
151
  @trace_state = trace_state && trace_state.dup.freeze
147
152
  @trace_state_unknown_fields = trace_state_unknown_fields && trace_state_unknown_fields.dup.freeze
148
153
  @span_remote = span_remote
154
+ @baggage = baggage && baggage.dup.freeze
149
155
  freeze
150
156
  end
151
157
 
@@ -177,6 +183,7 @@ module Datadog
177
183
  trace_state: trace_state,
178
184
  trace_state_unknown_fields: trace_state_unknown_fields,
179
185
  span_remote: span_remote,
186
+ baggage: baggage
180
187
  }.merge!(field_value_pairs)
181
188
  )
182
189
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative '../core/environment/identity'
4
4
  require_relative '../core/utils'
5
- require_relative 'tracer'
6
5
  require_relative 'event'
7
6
  require_relative 'metadata/tagging'
8
7
  require_relative 'sampling/ext'
@@ -37,7 +36,8 @@ module Datadog
37
36
  :rule_sample_rate,
38
37
  :sample_rate,
39
38
  :sampling_priority,
40
- :remote_parent
39
+ :remote_parent,
40
+ :baggage
41
41
 
42
42
  attr_reader \
43
43
  :active_span_count,
@@ -71,19 +71,21 @@ module Datadog
71
71
  sampling_priority: nil,
72
72
  service: nil,
73
73
  profiling_enabled: nil,
74
+ apm_tracing_enabled: nil,
74
75
  tags: nil,
75
76
  metrics: nil,
76
77
  trace_state: nil,
77
78
  trace_state_unknown_fields: nil,
78
79
  remote_parent: false,
79
- tracer: nil
80
+ tracer: nil,
81
+ baggage: nil
80
82
 
81
83
  )
82
84
  # Attributes
83
85
  @id = id || Tracing::Utils::TraceId.next_id
84
86
  @max_length = max_length || DEFAULT_MAX_LENGTH
85
87
  @parent_span_id = parent_span_id
86
- @sampled = sampled.nil? ? true : sampled
88
+ @sampled = sampled.nil? || sampled
87
89
  @remote_parent = remote_parent
88
90
 
89
91
  # Tags
@@ -98,9 +100,11 @@ module Datadog
98
100
  @sampling_priority = sampling_priority
99
101
  @service = service
100
102
  @profiling_enabled = profiling_enabled
103
+ @apm_tracing_enabled = apm_tracing_enabled
101
104
  @trace_state = trace_state
102
105
  @trace_state_unknown_fields = trace_state_unknown_fields
103
106
  @tracer = tracer
107
+ @baggage = baggage
104
108
 
105
109
  # Generic tags
106
110
  set_tags(tags) if tags
@@ -173,6 +177,12 @@ module Datadog
173
177
  super || (root_span && root_span.get_metric(key))
174
178
  end
175
179
 
180
+ def set_distributed_source(product_bit)
181
+ source = get_tag(Metadata::Ext::Distributed::TAG_TRACE_SOURCE)&.to_i(16) || 0
182
+ source |= product_bit
183
+ set_tag(Metadata::Ext::Distributed::TAG_TRACE_SOURCE, format('%02X', source))
184
+ end
185
+
176
186
  def tags
177
187
  all_tags = {}
178
188
  all_tags.merge!(root_span&.tags || {}) if root_span
@@ -315,10 +325,10 @@ module Datadog
315
325
 
316
326
  TraceDigest.new(
317
327
  span_id: span_id,
318
- span_name: (@active_span && @active_span.name),
319
- span_resource: (@active_span && @active_span.resource),
320
- span_service: (@active_span && @active_span.service),
321
- span_type: (@active_span && @active_span.type),
328
+ span_name: @active_span && @active_span.name,
329
+ span_resource: @active_span && @active_span.resource,
330
+ span_service: @active_span && @active_span.service,
331
+ span_type: @active_span && @active_span.type,
322
332
  trace_distributed_tags: distributed_tags,
323
333
  trace_hostname: @hostname,
324
334
  trace_id: @id,
@@ -331,7 +341,8 @@ module Datadog
331
341
  trace_service: service,
332
342
  trace_state: @trace_state,
333
343
  trace_state_unknown_fields: @trace_state_unknown_fields,
334
- span_remote: (@remote_parent && @active_span.nil?),
344
+ span_remote: @remote_parent && @active_span.nil?,
345
+ baggage: @baggage.nil? || @baggage.empty? ? nil : @baggage
335
346
  ).freeze
336
347
  end
337
348
 
@@ -351,22 +362,22 @@ module Datadog
351
362
  def fork_clone
352
363
  self.class.new(
353
364
  agent_sample_rate: @agent_sample_rate,
354
- events: (@events && @events.dup),
355
- hostname: (@hostname && @hostname.dup),
365
+ events: @events && @events.dup,
366
+ hostname: @hostname && @hostname.dup,
356
367
  id: @id,
357
368
  max_length: @max_length,
358
- name: (name && name.dup),
359
- origin: (@origin && @origin.dup),
369
+ name: name && name.dup,
370
+ origin: @origin && @origin.dup,
360
371
  parent_span_id: (@active_span && @active_span.id) || @parent_span_id,
361
372
  rate_limiter_rate: @rate_limiter_rate,
362
- resource: (resource && resource.dup),
373
+ resource: resource && resource.dup,
363
374
  rule_sample_rate: @rule_sample_rate,
364
375
  sample_rate: @sample_rate,
365
376
  sampled: @sampled,
366
377
  sampling_priority: @sampling_priority,
367
- service: (service && service.dup),
368
- trace_state: (@trace_state && @trace_state.dup),
369
- trace_state_unknown_fields: (@trace_state_unknown_fields && @trace_state_unknown_fields.dup),
378
+ service: service && service.dup,
379
+ trace_state: @trace_state && @trace_state.dup,
380
+ trace_state_unknown_fields: @trace_state_unknown_fields && @trace_state_unknown_fields.dup,
370
381
  tags: meta.dup,
371
382
  metrics: metrics.dup,
372
383
  remote_parent: @remote_parent
@@ -510,6 +521,7 @@ module Datadog
510
521
  metrics: metrics,
511
522
  root_span_id: !partial ? root_span && root_span.id : nil,
512
523
  profiling_enabled: @profiling_enabled,
524
+ apm_tracing_enabled: @apm_tracing_enabled
513
525
  )
514
526
  end
515
527
 
@@ -34,7 +34,8 @@ module Datadog
34
34
  :sampling_decision_maker,
35
35
  :sampling_priority,
36
36
  :service,
37
- :profiling_enabled
37
+ :profiling_enabled,
38
+ :apm_tracing_enabled
38
39
 
39
40
  # rubocop:disable Metrics/CyclomaticComplexity
40
41
  # rubocop:disable Metrics/PerceivedComplexity
@@ -58,7 +59,8 @@ module Datadog
58
59
  service: nil,
59
60
  tags: nil,
60
61
  metrics: nil,
61
- profiling_enabled: nil
62
+ profiling_enabled: nil,
63
+ apm_tracing_enabled: nil
62
64
  )
63
65
  @id = id
64
66
  @root_span_id = root_span_id
@@ -85,6 +87,7 @@ module Datadog
85
87
  @sampling_priority = sampling_priority || sampling_priority_tag
86
88
  @service = Core::Utils::SafeDup.frozen_or_dup(service || service_tag)
87
89
  @profiling_enabled = profiling_enabled
90
+ @apm_tracing_enabled = apm_tracing_enabled
88
91
  end
89
92
  # rubocop:enable Metrics/PerceivedComplexity
90
93
  # rubocop:enable Metrics/CyclomaticComplexity
@@ -128,8 +131,7 @@ module Datadog
128
131
  end
129
132
 
130
133
  def sampled?
131
- sampling_priority == Sampling::Ext::Priority::AUTO_KEEP \
132
- || sampling_priority == Sampling::Ext::Priority::USER_KEEP
134
+ [Sampling::Ext::Priority::AUTO_KEEP, Sampling::Ext::Priority::USER_KEEP].include?(sampling_priority)
133
135
  end
134
136
 
135
137
  # Returns the high order part of the trace id as a hexadecimal string; the most significant 64 bits.
@@ -338,24 +338,30 @@ module Datadog
338
338
  hostname = hostname && !hostname.empty? ? hostname : nil
339
339
 
340
340
  if digest
341
+ sampling_priority = if propagate_sampling_priority?(upstream_tags: digest.trace_distributed_tags)
342
+ digest.trace_sampling_priority
343
+ end
341
344
  TraceOperation.new(
342
345
  hostname: hostname,
343
346
  profiling_enabled: profiling_enabled,
347
+ apm_tracing_enabled: apm_tracing_enabled,
344
348
  id: digest.trace_id,
345
349
  origin: digest.trace_origin,
346
350
  parent_span_id: digest.span_id,
347
- sampling_priority: digest.trace_sampling_priority,
351
+ sampling_priority: sampling_priority,
348
352
  # Distributed tags are just regular trace tags with special meaning to Datadog
349
353
  tags: digest.trace_distributed_tags,
350
354
  trace_state: digest.trace_state,
351
355
  trace_state_unknown_fields: digest.trace_state_unknown_fields,
352
356
  remote_parent: digest.span_remote,
353
- tracer: self
357
+ tracer: self,
358
+ baggage: digest.baggage
354
359
  )
355
360
  else
356
361
  TraceOperation.new(
357
362
  hostname: hostname,
358
363
  profiling_enabled: profiling_enabled,
364
+ apm_tracing_enabled: apm_tracing_enabled,
359
365
  remote_parent: false,
360
366
  tracer: self
361
367
  )
@@ -545,10 +551,40 @@ module Datadog
545
551
  end
546
552
  end
547
553
 
554
+ # Decide whether upstream sampling priority should be propagated, by taking into account
555
+ # the upstream tags and the configuration.
556
+ # We should always propagate if APM is enabled.
557
+ #
558
+ # e.g.: upstream tags containing dd.p.ts: 02, and appsec is enabled, return true.
559
+ def propagate_sampling_priority?(upstream_tags:)
560
+ return true if apm_tracing_enabled
561
+
562
+ if upstream_tags&.key?(Tracing::Metadata::Ext::Distributed::TAG_TRACE_SOURCE)
563
+ appsec_bit = upstream_tags[Tracing::Metadata::Ext::Distributed::TAG_TRACE_SOURCE].to_i(16) &
564
+ Datadog::AppSec::Ext::PRODUCT_BIT
565
+ return appsec_enabled if appsec_bit != 0
566
+ end
567
+
568
+ false
569
+ end
570
+
548
571
  def profiling_enabled
549
572
  @profiling_enabled ||=
550
573
  !!(defined?(Datadog::Profiling) && Datadog::Profiling.respond_to?(:enabled?) && Datadog::Profiling.enabled?)
551
574
  end
575
+
576
+ def appsec_enabled
577
+ @appsec_enabled ||= Datadog.configuration.appsec.enabled
578
+ end
579
+
580
+ # Due to APM Tracing (the product) and Tracing (the transport) being intertwined, we cannot completely disabled APM
581
+ # without also disabling the tracer. When setting `@apm_tracing_enabled` to `false`, it does not disable the tracer,
582
+ # but rather only sends heartbeat traces (1 per minutes), so that the service is considered alive in the backend.
583
+ # Other products (like ASM) can then set the sampling priority of their traces to `MANUAL_KEEP`,
584
+ # effectively allowing standalone products to work without APM.
585
+ def apm_tracing_enabled
586
+ @apm_tracing_enabled ||= Datadog.configuration.apm.tracing.enabled
587
+ end
552
588
  end
553
589
  end
554
590
  end
@@ -22,14 +22,14 @@ module Datadog
22
22
 
23
23
  def defaults
24
24
  Core::Transport::HTTP::API::Map[
25
- V4 => Spec.new do |s|
25
+ V4 => Traces::API::Spec.new do |s|
26
26
  s.traces = Traces::API::Endpoint.new(
27
27
  '/v0.4/traces',
28
28
  Core::Encoding::MsgpackEncoder,
29
29
  service_rates: true
30
30
  )
31
31
  end,
32
- V3 => Spec.new do |s|
32
+ V3 => Traces::API::Spec.new do |s|
33
33
  s.traces = Traces::API::Endpoint.new(
34
34
  '/v0.3/traces',
35
35
  Core::Encoding::MsgpackEncoder
@@ -37,14 +37,6 @@ module Datadog
37
37
  end,
38
38
  ].with_fallbacks(V4 => V3)
39
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
48
40
  end
49
41
  end
50
42
  end
@@ -12,10 +12,11 @@ module Datadog
12
12
  class Client
13
13
  include Datadog::Tracing::Transport::HTTP::Statistics
14
14
 
15
- attr_reader :api
15
+ attr_reader :api, :logger
16
16
 
17
- def initialize(api)
17
+ def initialize(api, logger)
18
18
  @api = api
19
+ @logger = logger
19
20
  end
20
21
 
21
22
  def send_request(request, &block)
@@ -36,10 +37,10 @@ module Datadog
36
37
 
37
38
  # Log error
38
39
  if stats.consecutive_errors > 0
39
- Datadog.logger.debug(message)
40
+ logger.debug(message)
40
41
  else
41
42
  # Not to report telemetry logs
42
- Datadog.logger.error(message)
43
+ logger.error(message)
43
44
  end
44
45
 
45
46
  # Update statistics
@@ -6,6 +6,8 @@ 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 '../../../core/transport/http/api/spec'
10
+ require_relative '../../../core/transport/http/api/instance'
9
11
 
10
12
  module Datadog
11
13
  module Tracing
@@ -35,16 +37,12 @@ module Datadog
35
37
  end
36
38
 
37
39
  module API
38
- # Extensions for HTTP API Spec
39
- module Spec
40
- attr_reader :traces
41
-
42
- def traces=(endpoint)
43
- @traces = endpoint
44
- end
40
+ # HTTP API Spec
41
+ class Spec < Core::Transport::HTTP::API::Spec
42
+ attr_accessor :traces
45
43
 
46
44
  def send_traces(env, &block)
47
- raise NoTraceEndpointDefinedError, self if traces.nil?
45
+ raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('traces', self) if traces.nil?
48
46
 
49
47
  traces.call(env, &block)
50
48
  end
@@ -52,47 +50,21 @@ module Datadog
52
50
  def encoder
53
51
  traces.encoder
54
52
  end
55
-
56
- # Raised when traces sent but no traces endpoint is defined
57
- class NoTraceEndpointDefinedError < StandardError
58
- attr_reader :spec
59
-
60
- def initialize(spec)
61
- super
62
-
63
- @spec = spec
64
- end
65
-
66
- def message
67
- 'No trace endpoint is defined for API specification!'
68
- end
69
- end
70
53
  end
71
54
 
72
- # Extensions for HTTP API Instance
73
- module Instance
55
+ # HTTP API Instance
56
+ class Instance < Core::Transport::HTTP::API::Instance
74
57
  def send_traces(env)
75
- raise TracesNotSupportedError, spec unless spec.is_a?(Traces::API::Spec)
58
+ unless spec.is_a?(Traces::API::Spec)
59
+ raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new(
60
+ 'traces', self
61
+ )
62
+ end
76
63
 
77
64
  spec.send_traces(env) do |request_env|
78
65
  call(request_env)
79
66
  end
80
67
  end
81
-
82
- # Raised when traces sent to API that does not support traces
83
- class TracesNotSupportedError < StandardError
84
- attr_reader :spec
85
-
86
- def initialize(spec)
87
- super
88
-
89
- @spec = spec
90
- end
91
-
92
- def message
93
- 'Traces not supported for this API!'
94
- end
95
- end
96
68
  end
97
69
 
98
70
  # Endpoint for submitting trace data
@@ -14,62 +14,29 @@ module Datadog
14
14
  module HTTP
15
15
  module_function
16
16
 
17
- # Builds a new Transport::HTTP::Client
18
- def new(klass, &block)
19
- Core::Transport::HTTP.build(
20
- api_instance_class: API::Instance, &block
21
- ).to_transport(klass)
22
- end
23
-
24
17
  # Builds a new Transport::HTTP::Client with default settings
25
18
  # Pass a block to override any settings.
26
19
  def default(
27
20
  agent_settings:,
28
- **options
21
+ logger:,
22
+ api_version: nil,
23
+ headers: nil
29
24
  )
30
- new(Transport::Traces::Transport) do |transport|
31
- transport.adapter(agent_settings)
32
- transport.headers default_headers
33
-
25
+ Core::Transport::HTTP.build(
26
+ api_instance_class: Traces::API::Instance,
27
+ agent_settings: agent_settings,
28
+ logger: logger,
29
+ api_version: api_version,
30
+ headers: headers
31
+ ) do |transport|
34
32
  apis = API.defaults
35
33
 
36
34
  transport.api API::V4, apis[API::V4], fallback: API::V3, default: true
37
35
  transport.api API::V3, apis[API::V3]
38
36
 
39
- # Apply any settings given by options
40
- unless options.empty?
41
- transport.default_api = options[:api_version] if options.key?(:api_version)
42
- transport.headers options[:headers] if options.key?(:headers)
43
- end
44
-
45
37
  # Call block to apply any customization, if provided
46
38
  yield(transport) if block_given?
47
- end
48
- end
49
-
50
- def default_headers
51
- {
52
- Datadog::Core::Transport::Ext::HTTP::HEADER_CLIENT_COMPUTED_TOP_LEVEL => '1',
53
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG => Datadog::Core::Environment::Ext::LANG,
54
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG_VERSION => Datadog::Core::Environment::Ext::LANG_VERSION,
55
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG_INTERPRETER =>
56
- Datadog::Core::Environment::Ext::LANG_INTERPRETER,
57
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG_INTERPRETER_VENDOR => Core::Environment::Ext::LANG_ENGINE,
58
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_TRACER_VERSION =>
59
- Datadog::Core::Environment::Ext::GEM_DATADOG_VERSION
60
- }.tap do |headers|
61
- # Add container ID, if present.
62
- container_id = Datadog::Core::Environment::Container.container_id
63
- headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CONTAINER_ID] = container_id unless container_id.nil?
64
- # Pretend that stats computation are already done by the client
65
- if Datadog.configuration.appsec.standalone.enabled
66
- headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CLIENT_COMPUTED_STATS] = 'yes'
67
- end
68
- end
69
- end
70
-
71
- def default_adapter
72
- Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
39
+ end.to_transport(Transport::Traces::Transport)
73
40
  end
74
41
  end
75
42
  end
@@ -59,6 +59,7 @@ module Datadog
59
59
  tag_high_order_trace_id!
60
60
  tag_sampling_priority!
61
61
  tag_profiling_enabled!
62
+ tag_apm_tracing_disabled!
62
63
 
63
64
  if first_span
64
65
  tag_git_repository_url!
@@ -196,6 +197,12 @@ module Datadog
196
197
  )
197
198
  end
198
199
 
200
+ def tag_apm_tracing_disabled!
201
+ return if trace.apm_tracing_enabled
202
+
203
+ root_span.set_tag(Tracing::Metadata::Ext::TAG_APM_ENABLED, 0)
204
+ end
205
+
199
206
  def tag_git_repository_url!
200
207
  return if git_repository_url.nil?
201
208
 
@@ -43,15 +43,17 @@ module Datadog
43
43
  # We set the value to a conservative 5 MiB, in case network speed is slow.
44
44
  DEFAULT_MAX_PAYLOAD_SIZE = 5 * 1024 * 1024
45
45
 
46
- attr_reader :encoder, :max_size
46
+ attr_reader :encoder, :max_size, :logger
47
47
 
48
48
  #
49
49
  # Single traces larger than +max_size+ will be discarded.
50
50
  #
51
51
  # @param encoder [Datadog::Core::Encoding::Encoder]
52
+ # @param logger [Datadog::Core::Logger]
52
53
  # @param max_size [String] maximum acceptable payload size
53
- def initialize(encoder, native_events_supported:, max_size: DEFAULT_MAX_PAYLOAD_SIZE)
54
+ def initialize(encoder, logger, native_events_supported:, max_size: DEFAULT_MAX_PAYLOAD_SIZE)
54
55
  @encoder = encoder
56
+ @logger = logger
55
57
  @native_events_supported = native_events_supported
56
58
  @max_size = max_size
57
59
  end
@@ -78,11 +80,11 @@ module Datadog
78
80
  private
79
81
 
80
82
  def encode_one(trace)
81
- encoded = Encoder.encode_trace(encoder, trace, native_events_supported: @native_events_supported)
83
+ encoded = Encoder.encode_trace(encoder, trace, logger, native_events_supported: @native_events_supported)
82
84
 
83
85
  if encoded.size > max_size
84
86
  # This single trace is too large, we can't flush it
85
- Datadog.logger.debug { "Dropping trace. Payload too large: '#{trace.inspect}'" }
87
+ logger.debug { "Dropping trace. Payload too large: '#{trace.inspect}'" }
86
88
  Datadog.health_metrics.transport_trace_too_large(1)
87
89
 
88
90
  return nil
@@ -96,7 +98,7 @@ module Datadog
96
98
  module Encoder
97
99
  module_function
98
100
 
99
- def encode_trace(encoder, trace, native_events_supported:)
101
+ def encode_trace(encoder, trace, logger, native_events_supported:)
100
102
  # Format the trace for transport
101
103
  TraceFormatter.format!(trace)
102
104
 
@@ -106,7 +108,7 @@ module Datadog
106
108
  # Encode the trace
107
109
  encoder.encode(serializable_trace).tap do |encoded|
108
110
  # Print the actual serialized trace, since the encoder can change make non-trivial changes
109
- Datadog.logger.debug { "Flushing trace: #{encoder.decode(encoded)}" }
111
+ logger.debug { "Flushing trace: #{encoder.decode(encoded)}" }
110
112
  end
111
113
  end
112
114
  end
@@ -117,11 +119,12 @@ module Datadog
117
119
  # batches of traces into smaller chunks and handles
118
120
  # API version downgrade handshake.
119
121
  class Transport
120
- attr_reader :client, :apis, :default_api, :current_api_id
122
+ attr_reader :client, :apis, :default_api, :current_api_id, :logger
121
123
 
122
- def initialize(apis, default_api)
124
+ def initialize(apis, default_api, logger)
123
125
  @apis = apis
124
126
  @default_api = default_api
127
+ @logger = logger
125
128
 
126
129
  change_api!(default_api)
127
130
  end
@@ -130,6 +133,7 @@ module Datadog
130
133
  encoder = current_api.encoder
131
134
  chunker = Datadog::Tracing::Transport::Traces::Chunker.new(
132
135
  encoder,
136
+ logger,
133
137
  native_events_supported: native_events_supported?
134
138
  )
135
139
 
@@ -190,7 +194,7 @@ module Datadog
190
194
  raise UnknownApiVersionError, api_id unless apis.key?(api_id)
191
195
 
192
196
  @current_api_id = api_id
193
- @client = HTTP::Client.new(current_api)
197
+ @client = HTTP::Client.new(current_api, logger)
194
198
  end
195
199
 
196
200
  # Queries the agent for native span events serialization support.
@@ -198,6 +202,14 @@ module Datadog
198
202
  def native_events_supported?
199
203
  return @native_events_supported if defined?(@native_events_supported)
200
204
 
205
+ # Check for an explicit override
206
+ option = Datadog.configuration.tracing.native_span_events
207
+ unless option.nil?
208
+ @native_events_supported = option
209
+ return option
210
+ end
211
+
212
+ # Otherwise, check for agent support, to ensure a configuration-less setup.
201
213
  if (res = Datadog.send(:components).agent_info.fetch)
202
214
  @native_events_supported = res.span_events == true
203
215
  else
@@ -26,14 +26,10 @@ module Datadog
26
26
  @logger = options[:logger] || Datadog.logger
27
27
 
28
28
  transport_options = options.fetch(:transport_options, {})
29
-
30
- if options.key?(:agent_settings)
31
- @agent_settings = options[:agent_settings]
32
- transport_options = transport_options.merge(agent_settings: @agent_settings)
33
- end
29
+ @agent_settings = options[:agent_settings]
34
30
 
35
31
  @transport = options.fetch(:transport) do
36
- Datadog::Tracing::Transport::HTTP.default(**transport_options)
32
+ Datadog::Tracing::Transport::HTTP.default(agent_settings: agent_settings, logger: logger, **transport_options)
37
33
  end
38
34
  end
39
35
  # rubocop:enable Lint/MissingSuper
@@ -26,15 +26,11 @@ module Datadog
26
26
  @buff_size = options.fetch(:buffer_size, Workers::AsyncTransport::DEFAULT_BUFFER_MAX_SIZE)
27
27
  @flush_interval = options.fetch(:flush_interval, Workers::AsyncTransport::DEFAULT_FLUSH_INTERVAL)
28
28
  transport_options = options.fetch(:transport_options, {})
29
-
30
- if options.key?(:agent_settings)
31
- @agent_settings = options[:agent_settings]
32
- transport_options = transport_options.merge(agent_settings: @agent_settings)
33
- end
29
+ @agent_settings = options[:agent_settings]
34
30
 
35
31
  # transport and buffers
36
32
  @transport = options.fetch(:transport) do
37
- Transport::HTTP.default(**transport_options)
33
+ Transport::HTTP.default(agent_settings: agent_settings, logger: logger, **transport_options)
38
34
  end
39
35
 
40
36
  @shutdown_timeout = options.fetch(:shutdown_timeout, Workers::AsyncTransport::DEFAULT_SHUTDOWN_TIMEOUT)