datadog 2.12.2 → 2.14.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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -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/metrics/client.rb +1 -1
  33. data/lib/datadog/core/remote/client.rb +1 -1
  34. data/lib/datadog/core/remote/component.rb +3 -6
  35. data/lib/datadog/core/remote/configuration/repository.rb +2 -1
  36. data/lib/datadog/core/remote/negotiation.rb +9 -9
  37. data/lib/datadog/core/remote/transport/config.rb +4 -3
  38. data/lib/datadog/core/remote/transport/http/client.rb +4 -3
  39. data/lib/datadog/core/remote/transport/http/config.rb +6 -32
  40. data/lib/datadog/core/remote/transport/http/negotiation.rb +6 -32
  41. data/lib/datadog/core/remote/transport/http.rb +22 -57
  42. data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
  43. data/lib/datadog/core/runtime/metrics.rb +8 -1
  44. data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
  45. data/lib/datadog/core/transport/http/api/instance.rb +17 -0
  46. data/lib/datadog/core/transport/http/api/spec.rb +17 -0
  47. data/lib/datadog/core/transport/http/builder.rb +5 -3
  48. data/lib/datadog/core/transport/http.rb +39 -2
  49. data/lib/datadog/di/component.rb +0 -2
  50. data/lib/datadog/di/probe_notifier_worker.rb +16 -16
  51. data/lib/datadog/di/transport/diagnostics.rb +4 -3
  52. data/lib/datadog/di/transport/http/api.rb +2 -12
  53. data/lib/datadog/di/transport/http/client.rb +4 -3
  54. data/lib/datadog/di/transport/http/diagnostics.rb +7 -33
  55. data/lib/datadog/di/transport/http/input.rb +7 -33
  56. data/lib/datadog/di/transport/http.rb +14 -56
  57. data/lib/datadog/di/transport/input.rb +4 -3
  58. data/lib/datadog/di/utils.rb +5 -0
  59. data/lib/datadog/kit/appsec/events.rb +12 -0
  60. data/lib/datadog/kit/identity.rb +5 -1
  61. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  62. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  63. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  64. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  65. data/lib/datadog/opentelemetry.rb +2 -1
  66. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  67. data/lib/datadog/profiling.rb +5 -2
  68. data/lib/datadog/tracing/component.rb +15 -12
  69. data/lib/datadog/tracing/configuration/ext.rb +7 -1
  70. data/lib/datadog/tracing/configuration/settings.rb +18 -2
  71. data/lib/datadog/tracing/context_provider.rb +1 -1
  72. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  73. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  74. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  75. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  76. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  77. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  78. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  79. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  80. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  81. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -5
  82. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -11
  83. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +6 -10
  84. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  85. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +46 -0
  86. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  87. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  88. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  89. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  90. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  91. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  92. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  93. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  94. data/lib/datadog/tracing/contrib.rb +1 -0
  95. data/lib/datadog/tracing/correlation.rb +9 -2
  96. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  97. data/lib/datadog/tracing/distributed/datadog.rb +2 -0
  98. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  99. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  100. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  101. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  102. data/lib/datadog/tracing/span_operation.rb +2 -1
  103. data/lib/datadog/tracing/sync_writer.rb +1 -2
  104. data/lib/datadog/tracing/trace_digest.rb +9 -2
  105. data/lib/datadog/tracing/trace_operation.rb +29 -17
  106. data/lib/datadog/tracing/trace_segment.rb +6 -4
  107. data/lib/datadog/tracing/tracer.rb +38 -2
  108. data/lib/datadog/tracing/transport/http/api.rb +2 -10
  109. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  110. data/lib/datadog/tracing/transport/http/traces.rb +13 -41
  111. data/lib/datadog/tracing/transport/http.rb +11 -44
  112. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  113. data/lib/datadog/tracing/transport/traces.rb +26 -9
  114. data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
  115. data/lib/datadog/tracing/writer.rb +2 -6
  116. data/lib/datadog/tracing.rb +16 -3
  117. data/lib/datadog/version.rb +2 -2
  118. data/lib/datadog.rb +1 -1
  119. metadata +24 -13
  120. data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
  121. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
  122. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
  123. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  124. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  125. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
@@ -42,7 +42,7 @@ module Datadog
42
42
  #
43
43
  # The tracer will try to find distributed headers in the order they are present in the list provided to this option.
44
44
  # The first format to have valid data present will be used.
45
- #
45
+ # Baggage style is a special case, as it will always be extracted in addition if present.
46
46
  # @default `DD_TRACE_PROPAGATION_STYLE_EXTRACT` environment variable (comma-separated list),
47
47
  # otherwise `['datadog','b3multi','b3']`.
48
48
  # @return [Array<String>]
@@ -53,6 +53,7 @@ module Datadog
53
53
  [
54
54
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG,
55
55
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT,
56
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_BAGGAGE,
56
57
  ]
57
58
  )
58
59
  o.after_set do |styles|
@@ -74,6 +75,7 @@ module Datadog
74
75
  o.default [
75
76
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG,
76
77
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT,
78
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_BAGGAGE,
77
79
  ]
78
80
  o.after_set do |styles|
79
81
  # Make values case-insensitive
@@ -186,7 +188,7 @@ module Datadog
186
188
  # It is not supported by our backend yet. Do not enable it.
187
189
  option :trace_id_128_bit_logging_enabled do |o|
188
190
  o.env Tracing::Configuration::Ext::Correlation::ENV_TRACE_ID_128_BIT_LOGGING_ENABLED
189
- o.default false
191
+ o.default true
190
192
  o.type :bool
191
193
  end
192
194
 
@@ -249,6 +251,20 @@ module Datadog
249
251
  o.type :bool
250
252
  end
251
253
 
254
+ # Forces the tracer to always send span events with the native span events format
255
+ # regardless of the agent support. This is useful in agent-less setups.
256
+ #
257
+ # When set to `nil`, the default, the agent will be queried for
258
+ # native span events support.
259
+ #
260
+ # @default `DD_TRACE_NATIVE_SPAN_EVENTS` environment variable, otherwise `false`
261
+ # @return [Boolean,nil]
262
+ option :native_span_events do |o|
263
+ o.env Tracing::Configuration::Ext::ENV_NATIVE_SPAN_EVENTS
264
+ o.default nil
265
+ o.type :bool, nilable: true
266
+ end
267
+
252
268
  # A custom sampler instance.
253
269
  # The object must respect the {Datadog::Tracing::Sampling::Sampler} interface.
254
270
  # @default `nil`
@@ -49,7 +49,7 @@ module Datadog
49
49
  # To support multiple tracers simultaneously, each {Datadog::Tracing::FiberLocalContext}
50
50
  # instance has its own fiber-local variable.
51
51
  def initialize
52
- @key = "datadog_context_#{FiberLocalContext.next_instance_id}".to_sym
52
+ @key = :"datadog_context_#{FiberLocalContext.next_instance_id}"
53
53
 
54
54
  self.local = Context.new
55
55
  end
@@ -22,7 +22,7 @@ module Datadog
22
22
  end
23
23
 
24
24
  def configure(options = {})
25
- self.class.options.each do |name, _value|
25
+ self.class.options.each_key do |name|
26
26
  self[name] = options[name] if options.key?(name)
27
27
  end
28
28
 
@@ -110,11 +110,10 @@ module Datadog
110
110
 
111
111
  datadog_tag_request
112
112
 
113
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(datadog_trace)
114
- datadog_trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
115
- end
116
-
117
- if datadog_configuration[:distributed_tracing]
113
+ if Tracing::Distributed::PropagationPolicy.enabled?(
114
+ global_config: datadog_configuration,
115
+ trace: datadog_trace
116
+ )
118
117
  @datadog_original_headers ||= {}
119
118
  Contrib::HTTP.inject(datadog_trace, @datadog_original_headers)
120
119
  self.headers = @datadog_original_headers
@@ -30,10 +30,12 @@ module Datadog
30
30
  trace = Tracing.active_trace
31
31
  datum[:datadog_span] = span
32
32
  annotate!(span, datum)
33
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
34
- trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
33
+ if Tracing::Distributed::PropagationPolicy.enabled?(
34
+ global_config: @options,
35
+ trace: trace
36
+ )
37
+ propagate!(trace, span, datum)
35
38
  end
36
- propagate!(trace, span, datum) if distributed_tracing?
37
39
 
38
40
  span
39
41
  end
@@ -48,6 +48,7 @@ module Datadog
48
48
 
49
49
  module Messaging
50
50
  TAG_SYSTEM = 'messaging.system'
51
+ TAG_DESTINATION = 'messaging.destination'
51
52
  PEER_SERVICE_SOURCES = Array[Tracing::Metadata::Ext::NET::TAG_DESTINATION_NAME,
52
53
  Tracing::Metadata::Ext::TAG_PEER_HOSTNAME,
53
54
  Tracing::Metadata::Ext::NET::TAG_TARGET_HOST,].freeze
@@ -29,10 +29,12 @@ module Datadog
29
29
 
30
30
  Tracing.trace(Ext::SPAN_REQUEST, on_error: request_options[:on_error]) do |span, trace|
31
31
  annotate!(span, env, request_options)
32
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
33
- trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
32
+ if Tracing::Distributed::PropagationPolicy.enabled?(
33
+ global_config: request_options,
34
+ trace: trace
35
+ )
36
+ propagate!(trace, span, env)
34
37
  end
35
- propagate!(trace, span, env) if request_options[:distributed_tracing] && Tracing.enabled?
36
38
  app.call(env).on_complete { |resp| handle_response(span, resp, request_options) }
37
39
  end
38
40
  end
@@ -81,7 +81,13 @@ module Datadog
81
81
  # Set analytics sample rate
82
82
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
83
83
 
84
- GRPC.inject(trace, metadata) if distributed_tracing?
84
+ if Tracing::Distributed::PropagationPolicy.enabled?(
85
+ pin_config: Datadog.configuration_for(self),
86
+ global_config: datadog_configuration,
87
+ trace: trace
88
+ )
89
+ GRPC.inject(trace, metadata)
90
+ end
85
91
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
86
92
  rescue StandardError => e
87
93
  Datadog.logger.debug("GRPC client trace failed: #{e}")
@@ -3,6 +3,7 @@
3
3
  require_relative 'fetcher'
4
4
  require_relative '../../../distributed/b3_multi'
5
5
  require_relative '../../../distributed/b3_single'
6
+ require_relative '../../../distributed/propagation_policy'
6
7
  require_relative '../../../distributed/datadog'
7
8
  require_relative '../../../distributed/none'
8
9
  require_relative '../../../distributed/propagation'
@@ -31,6 +32,8 @@ module Datadog
31
32
  Tracing::Distributed::Datadog.new(fetcher: Fetcher),
32
33
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
33
34
  Tracing::Distributed::TraceContext.new(fetcher: Fetcher),
35
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_BAGGAGE =>
36
+ Tracing::Distributed::Baggage.new(fetcher: Fetcher),
34
37
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new
35
38
  },
36
39
  propagation_style_inject: propagation_style_inject,
@@ -27,21 +27,6 @@ module Datadog
27
27
  !!(request[Datadog::Core::Transport::Ext::HTTP::HEADER_META_TRACER_VERSION] ||
28
28
  request[Datadog::Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST])
29
29
  end
30
-
31
- def should_skip_distributed_tracing?(client_config)
32
- if Datadog.configuration.appsec.standalone.enabled
33
- # Skip distributed tracing so that we don't bill distributed traces in case of absence of
34
- # upstream ASM event (_dd.p.appsec:1) and no local security event (which sets _dd.p.appsec:1 locally).
35
- # If there is an ASM event, we still have to check if distributed tracing is enabled or not
36
- return true unless Tracing.active_trace
37
-
38
- return true if Tracing.active_trace.get_tag(Datadog::AppSec::Ext::TAG_DISTRIBUTED_APPSEC_EVENT) != '1'
39
- end
40
-
41
- return !client_config[:distributed_tracing] if client_config && client_config.key?(:distributed_tracing)
42
-
43
- !Datadog.configuration.tracing[:http][:distributed_tracing]
44
- end
45
30
  end
46
31
  end
47
32
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'fetcher'
4
4
  require_relative '../../../distributed/propagation'
5
+ require_relative '../../../distributed/propagation_policy'
5
6
  require_relative '../../../distributed/b3_multi'
6
7
  require_relative '../../../distributed/b3_single'
7
8
  require_relative '../../../distributed/datadog'
@@ -30,7 +31,9 @@ module Datadog
30
31
  Tracing::Distributed::Datadog.new(fetcher: Fetcher),
31
32
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
32
33
  Tracing::Distributed::TraceContext.new(fetcher: Fetcher),
33
- Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new
34
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_BAGGAGE =>
35
+ Tracing::Distributed::Baggage.new(fetcher: Fetcher),
36
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new,
34
37
  },
35
38
  propagation_style_inject: propagation_style_inject,
36
39
  propagation_style_extract: propagation_style_extract,
@@ -35,11 +35,11 @@ module Datadog
35
35
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
36
36
  span.resource = req.method
37
37
 
38
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
39
- trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
40
- end
41
-
42
- if Tracing.enabled? && !Contrib::HTTP.should_skip_distributed_tracing?(client_config)
38
+ if Tracing::Distributed::PropagationPolicy.enabled?(
39
+ pin_config: client_config,
40
+ global_config: Datadog.configuration.tracing[:http],
41
+ trace: trace
42
+ )
43
43
  Contrib::HTTP.inject(trace, req)
44
44
  end
45
45
 
@@ -30,11 +30,11 @@ module Datadog
30
30
  span.service = service_name(host, request_options, client_config)
31
31
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
32
32
 
33
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
34
- trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
35
- end
36
-
37
- if Tracing.enabled? && !should_skip_distributed_tracing?(client_config)
33
+ if Tracing::Distributed::PropagationPolicy.enabled?(
34
+ pin_config: client_config,
35
+ global_config: Datadog.configuration.tracing[:httpclient],
36
+ trace: trace
37
+ )
38
38
  Contrib::HTTP.inject(trace, req.header)
39
39
  end
40
40
 
@@ -123,12 +123,6 @@ module Datadog
123
123
  Contrib::Analytics.enabled?(request_options[:analytics_enabled])
124
124
  end
125
125
 
126
- def should_skip_distributed_tracing?(client_config)
127
- return !client_config[:distributed_tracing] if client_config && client_config.key?(:distributed_tracing)
128
-
129
- !Datadog.configuration.tracing[:httpclient][:distributed_tracing]
130
- end
131
-
132
126
  def set_analytics_sample_rate(span, request_options)
133
127
  return unless analytics_enabled?(request_options)
134
128
 
@@ -30,12 +30,14 @@ module Datadog
30
30
  span.service = service_name(host, request_options, client_config)
31
31
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
32
32
 
33
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
34
- trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
33
+ if Tracing::Distributed::PropagationPolicy.enabled?(
34
+ pin_config: client_config,
35
+ global_config: Datadog.configuration.tracing[:httprb],
36
+ trace: trace
37
+ )
38
+ Contrib::HTTP.inject(trace, req)
35
39
  end
36
40
 
37
- Contrib::HTTP.inject(trace, req) if Tracing.enabled? && !should_skip_distributed_tracing?(client_config)
38
-
39
41
  # Add additional request specific tags to the span.
40
42
  annotate_span_with_request!(span, req, request_options)
41
43
  rescue StandardError => e
@@ -135,12 +137,6 @@ module Datadog
135
137
  Datadog.logger
136
138
  end
137
139
 
138
- def should_skip_distributed_tracing?(client_config)
139
- return !client_config[:distributed_tracing] if client_config && client_config.key?(:distributed_tracing)
140
-
141
- !Datadog.configuration.tracing[:httprb][:distributed_tracing]
142
- end
143
-
144
140
  def set_analytics_sample_rate(span, request_options)
145
141
  return unless analytics_enabled?(request_options)
146
142
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../configuration/settings'
4
+ require_relative '../ext'
5
+
6
+ module Datadog
7
+ module Tracing
8
+ module Contrib
9
+ module Karafka
10
+ module Configuration
11
+ # @public_api
12
+ class Settings < Contrib::Configuration::Settings
13
+ option :enabled do |o|
14
+ o.type :bool
15
+ o.env Ext::ENV_ENABLED
16
+ o.default true
17
+ end
18
+
19
+ option :service_name
20
+
21
+ option :distributed_tracing, default: false, type: :bool
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../distributed/fetcher'
4
+ require_relative '../../../distributed/propagation'
5
+ require_relative '../../../distributed/b3_multi'
6
+ require_relative '../../../distributed/b3_single'
7
+ require_relative '../../../distributed/datadog'
8
+ require_relative '../../../distributed/none'
9
+ require_relative '../../../distributed/trace_context'
10
+ require_relative '../../../configuration/ext'
11
+
12
+ module Datadog
13
+ module Tracing
14
+ module Contrib
15
+ module Karafka
16
+ module Distributed
17
+ # Extracts and injects propagation through Kafka message headers.
18
+ class Propagation < Tracing::Distributed::Propagation
19
+ def initialize(
20
+ propagation_style_inject:,
21
+ propagation_style_extract:,
22
+ propagation_extract_first:
23
+ )
24
+ super(
25
+ propagation_styles: {
26
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER =>
27
+ Tracing::Distributed::B3Multi.new(fetcher: Tracing::Distributed::Fetcher),
28
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER =>
29
+ Tracing::Distributed::B3Single.new(fetcher: Tracing::Distributed::Fetcher),
30
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG =>
31
+ Tracing::Distributed::Datadog.new(fetcher: Tracing::Distributed::Fetcher),
32
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
33
+ Tracing::Distributed::TraceContext.new(fetcher: Tracing::Distributed::Fetcher),
34
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new
35
+ },
36
+ propagation_style_inject: propagation_style_inject,
37
+ propagation_style_extract: propagation_style_extract,
38
+ propagation_extract_first: propagation_extract_first
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Karafka
7
+ module Ext
8
+ ENV_ENABLED = 'DD_TRACE_KARAFKA_ENABLED'
9
+
10
+ SPAN_MESSAGE_CONSUME = 'karafka.consume'
11
+ SPAN_WORKER_PROCESS = 'worker.process'
12
+
13
+ TAG_CONSUMER = 'kafka.consumer'
14
+ TAG_TOPIC = 'kafka.topic'
15
+ TAG_PARTITION = 'kafka.partition'
16
+ TAG_OFFSET = 'kafka.offset'
17
+ TAG_OFFSET_LAG = 'kafka.offset_lag'
18
+ TAG_MESSAGE_COUNT = 'kafka.message_count'
19
+ TAG_MESSAGE_KEY = 'kafka.message_key'
20
+ TAG_SYSTEM = 'kafka'
21
+
22
+ TAG_OPERATION_PROCESS_BATCH = 'consumer.process_batch'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../integration'
4
+ require_relative 'configuration/settings'
5
+ require_relative 'patcher'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ module Karafka
11
+ # Description of Kafka integration
12
+ class Integration
13
+ include Contrib::Integration
14
+
15
+ # Minimum version of the Karafka library that we support
16
+ # https://karafka.io/docs/Versions-Lifecycle-and-EOL/#versioning-strategy
17
+ MINIMUM_VERSION = Gem::Version.new('2.3.0')
18
+
19
+ # @public_api Changing the integration name or integration options can cause breaking changes
20
+ register_as :karafka, auto_patch: false
21
+
22
+ def self.version
23
+ Gem.loaded_specs['karafka']&.version
24
+ end
25
+
26
+ def self.loaded?
27
+ !defined?(::Karafka).nil?
28
+ end
29
+
30
+ def self.compatible?
31
+ super && version >= MINIMUM_VERSION
32
+ end
33
+
34
+ def new_configuration
35
+ Configuration::Settings.new
36
+ end
37
+
38
+ def patcher
39
+ Patcher
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Contrib
8
+ module Karafka
9
+ # Custom monitor for Karafka.
10
+ # Creating a custom monitor, instead of subscribing to an event
11
+ # (e.g. `Karafka.monitor.subscribe 'worker.processed'`),
12
+ # is required because event subscriptions cannot wrap the event execution (`yield`).
13
+ module Monitor
14
+ TRACEABLE_EVENTS = %w[
15
+ worker.processed
16
+ ].freeze
17
+
18
+ def instrument(event_id, payload = EMPTY_HASH, &block)
19
+ return super unless TRACEABLE_EVENTS.include?(event_id)
20
+
21
+ Datadog::Tracing.trace(Ext::SPAN_WORKER_PROCESS) do |span|
22
+ job = payload[:job]
23
+ job_type = fetch_job_type(job.class)
24
+ consumer = job.executor.topic.consumer
25
+
26
+ action = case job_type
27
+ when 'Periodic', 'PeriodicNonBlocking'
28
+ 'tick'
29
+ when 'Shutdown'
30
+ 'shutdown'
31
+ when 'Revoked', 'RevokedNonBlocking'
32
+ 'revoked'
33
+ when 'Idle'
34
+ 'idle'
35
+ when 'Eofed', 'EofedNonBlocking'
36
+ 'eofed'
37
+ else
38
+ 'consume'
39
+ end
40
+
41
+ span.resource = "#{consumer}##{action}"
42
+
43
+ if action == 'consume'
44
+ span.set_tag(Ext::TAG_MESSAGE_COUNT, job.messages.count)
45
+ span.set_tag(Ext::TAG_PARTITION, job.executor.partition)
46
+ span.set_tag(Ext::TAG_OFFSET, job.messages.first.metadata.offset)
47
+ span.set_tag(Ext::TAG_CONSUMER, consumer)
48
+ span.set_tag(Contrib::Ext::Messaging::TAG_DESTINATION, job.executor.topic.name)
49
+ span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Ext::TAG_SYSTEM)
50
+ end
51
+
52
+ super
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def fetch_job_type(job_class)
59
+ @job_types_cache ||= {}
60
+ @job_types_cache[job_class] ||= job_class.to_s.split('::').last
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../patcher'
4
+ require_relative 'ext'
5
+ require_relative 'distributed/propagation'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ module Karafka
11
+ # Patch to add tracing to Karafka::Messages::Messages
12
+ module MessagesPatch
13
+ def configuration
14
+ Datadog.configuration.tracing[:karafka]
15
+ end
16
+
17
+ def propagation
18
+ @propagation ||= Contrib::Karafka::Distributed::Propagation.new
19
+ end
20
+
21
+ # `each` is the most popular access point to Karafka messages,
22
+ # but not the only one
23
+ # Other access patterns do not have a straightforward tracing avenue
24
+ # (e.g. `my_batch_operation messages.payloads`)
25
+ # @see https://github.com/karafka/karafka/blob/b06d1f7c17818e1605f80c2bb573454a33376b40/README.md?plain=1#L29-L35
26
+ def each(&block)
27
+ @messages_array.each do |message|
28
+ if configuration[:distributed_tracing]
29
+ headers = if message.metadata.respond_to?(:raw_headers)
30
+ message.metadata.raw_headers
31
+ else
32
+ message.metadata.headers
33
+ end
34
+ trace_digest = Karafka.extract(headers)
35
+ Datadog::Tracing.continue_trace!(trace_digest) if trace_digest
36
+ end
37
+
38
+ Tracing.trace(Ext::SPAN_MESSAGE_CONSUME) do |span|
39
+ span.set_tag(Ext::TAG_OFFSET, message.metadata.offset)
40
+ span.set_tag(Contrib::Ext::Messaging::TAG_DESTINATION, message.topic)
41
+ span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Ext::TAG_SYSTEM)
42
+
43
+ span.resource = message.topic
44
+
45
+ yield message
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ # Patcher enables patching of 'karafka' module.
52
+ module Patcher
53
+ include Contrib::Patcher
54
+
55
+ module_function
56
+
57
+ def target_version
58
+ Integration.version
59
+ end
60
+
61
+ def patch
62
+ require_relative 'monitor'
63
+
64
+ ::Karafka::Instrumentation::Monitor.prepend(Monitor)
65
+ ::Karafka::Messages::Messages.prepend(MessagesPatch)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'component'
4
+ require_relative 'karafka/integration'
5
+ require_relative 'karafka/distributed/propagation'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ # `Karafka` integration public API
11
+ module Karafka
12
+ def self.inject(digest, data)
13
+ raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
14
+
15
+ @propagation.inject!(digest, data)
16
+ end
17
+
18
+ def self.extract(data)
19
+ raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
20
+
21
+ @propagation.extract(data)
22
+ end
23
+
24
+ Contrib::Component.register('karafka') do |config|
25
+ tracing = config.tracing
26
+ tracing.propagation_style
27
+
28
+ @propagation = Karafka::Distributed::Propagation.new(
29
+ propagation_style_inject: tracing.propagation_style_inject,
30
+ propagation_style_extract: tracing.propagation_style_extract,
31
+ propagation_extract_first: tracing.propagation_extract_first
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -25,10 +25,12 @@ module Datadog
25
25
  return super(&block) unless Tracing.enabled?
26
26
 
27
27
  datadog_trace_request(uri) do |_span, trace|
28
- if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
29
- trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
28
+ if Tracing::Distributed::PropagationPolicy.enabled?(
29
+ global_config: datadog_configuration,
30
+ trace: trace
31
+ )
32
+ Contrib::HTTP.inject(trace, processed_headers)
30
33
  end
31
- Contrib::HTTP.inject(trace, processed_headers) if datadog_configuration[:distributed_tracing]
32
34
 
33
35
  super(&block)
34
36
  end
@@ -24,7 +24,12 @@ module Datadog
24
24
  resource = job_resource(job)
25
25
 
26
26
  Datadog::Tracing.trace(Ext::SPAN_PUSH, service: @sidekiq_service) do |span, trace_op|
27
- Sidekiq.inject(trace_op, job) if configuration[:distributed_tracing]
27
+ if Tracing::Distributed::PropagationPolicy.enabled?(
28
+ global_config: configuration,
29
+ trace: trace_op
30
+ )
31
+ Sidekiq.inject(trace_op, job)
32
+ end
28
33
 
29
34
  span.resource = resource
30
35