ddtrace 0.38.0 → 0.43.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 (194) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +56 -0
  3. data/.github/workflows/add-milestone-to-pull-requests.yml +42 -0
  4. data/.github/workflows/create-next-milestone.yml +20 -0
  5. data/.gitlab-ci.yml +1 -0
  6. data/.simplecov +38 -0
  7. data/Appraisals +293 -105
  8. data/CHANGELOG.md +192 -1
  9. data/CONTRIBUTING.md +2 -2
  10. data/Rakefile +554 -480
  11. data/ddtrace.gemspec +3 -0
  12. data/docs/DevelopmentGuide.md +28 -2
  13. data/docs/GettingStarted.md +207 -82
  14. data/lib/ddtrace.rb +4 -0
  15. data/lib/ddtrace/buffer.rb +259 -52
  16. data/lib/ddtrace/configuration.rb +55 -5
  17. data/lib/ddtrace/configuration/components.rb +4 -7
  18. data/lib/ddtrace/configuration/options.rb +3 -1
  19. data/lib/ddtrace/configuration/settings.rb +18 -6
  20. data/lib/ddtrace/context.rb +18 -0
  21. data/lib/ddtrace/context_provider.rb +17 -5
  22. data/lib/ddtrace/contrib/action_cable/configuration/settings.rb +7 -2
  23. data/lib/ddtrace/contrib/action_cable/ext.rb +5 -2
  24. data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +7 -2
  25. data/lib/ddtrace/contrib/action_pack/ext.rb +5 -2
  26. data/lib/ddtrace/contrib/action_view/configuration/settings.rb +7 -2
  27. data/lib/ddtrace/contrib/action_view/ext.rb +5 -2
  28. data/lib/ddtrace/contrib/active_model_serializers/configuration/settings.rb +7 -2
  29. data/lib/ddtrace/contrib/active_model_serializers/ext.rb +5 -2
  30. data/lib/ddtrace/contrib/active_record/configuration/settings.rb +7 -2
  31. data/lib/ddtrace/contrib/active_record/events/sql.rb +4 -0
  32. data/lib/ddtrace/contrib/active_record/ext.rb +5 -2
  33. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +104 -3
  34. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +21 -0
  35. data/lib/ddtrace/contrib/active_support/configuration/settings.rb +7 -2
  36. data/lib/ddtrace/contrib/active_support/ext.rb +8 -2
  37. data/lib/ddtrace/contrib/active_support/notifications/event.rb +10 -0
  38. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +2 -2
  39. data/lib/ddtrace/contrib/aws/configuration/settings.rb +7 -2
  40. data/lib/ddtrace/contrib/aws/ext.rb +5 -2
  41. data/lib/ddtrace/contrib/aws/instrumentation.rb +6 -1
  42. data/lib/ddtrace/contrib/aws/patcher.rb +0 -1
  43. data/lib/ddtrace/contrib/concurrent_ruby/configuration/settings.rb +5 -0
  44. data/lib/ddtrace/contrib/concurrent_ruby/ext.rb +1 -0
  45. data/lib/ddtrace/contrib/configurable.rb +2 -0
  46. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +4 -5
  47. data/lib/ddtrace/contrib/configuration/settings.rb +1 -0
  48. data/lib/ddtrace/contrib/cucumber/configuration/settings.rb +38 -0
  49. data/lib/ddtrace/contrib/cucumber/ext.rb +19 -0
  50. data/lib/ddtrace/contrib/cucumber/formatter.rb +104 -0
  51. data/lib/ddtrace/contrib/cucumber/instrumentation.rb +24 -0
  52. data/lib/ddtrace/contrib/cucumber/integration.rb +40 -0
  53. data/lib/ddtrace/contrib/cucumber/patcher.rb +23 -0
  54. data/lib/ddtrace/contrib/dalli/configuration/settings.rb +7 -2
  55. data/lib/ddtrace/contrib/dalli/ext.rb +5 -2
  56. data/lib/ddtrace/contrib/dalli/instrumentation.rb +4 -0
  57. data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +9 -2
  58. data/lib/ddtrace/contrib/delayed_job/ext.rb +7 -2
  59. data/lib/ddtrace/contrib/delayed_job/plugin.rb +39 -15
  60. data/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb +7 -2
  61. data/lib/ddtrace/contrib/elasticsearch/ext.rb +5 -2
  62. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +4 -0
  63. data/lib/ddtrace/contrib/ethon/configuration/settings.rb +7 -2
  64. data/lib/ddtrace/contrib/ethon/easy_patch.rb +4 -2
  65. data/lib/ddtrace/contrib/ethon/ext.rb +5 -2
  66. data/lib/ddtrace/contrib/ethon/multi_patch.rb +4 -0
  67. data/lib/ddtrace/contrib/excon/configuration/settings.rb +7 -2
  68. data/lib/ddtrace/contrib/excon/ext.rb +5 -2
  69. data/lib/ddtrace/contrib/excon/middleware.rb +11 -1
  70. data/lib/ddtrace/contrib/extensions.rb +1 -1
  71. data/lib/ddtrace/contrib/faraday/configuration/settings.rb +7 -2
  72. data/lib/ddtrace/contrib/faraday/ext.rb +5 -2
  73. data/lib/ddtrace/contrib/faraday/middleware.rb +4 -0
  74. data/lib/ddtrace/contrib/faraday/patcher.rb +13 -4
  75. data/lib/ddtrace/contrib/grape/configuration/settings.rb +14 -3
  76. data/lib/ddtrace/contrib/grape/endpoint.rb +24 -7
  77. data/lib/ddtrace/contrib/grape/ext.rb +5 -2
  78. data/lib/ddtrace/contrib/graphql/configuration/settings.rb +7 -2
  79. data/lib/ddtrace/contrib/graphql/ext.rb +5 -2
  80. data/lib/ddtrace/contrib/grpc/configuration/settings.rb +7 -2
  81. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +5 -1
  82. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +4 -0
  83. data/lib/ddtrace/contrib/grpc/ext.rb +5 -2
  84. data/lib/ddtrace/contrib/http/configuration/settings.rb +7 -2
  85. data/lib/ddtrace/contrib/http/ext.rb +5 -2
  86. data/lib/ddtrace/contrib/http/instrumentation.rb +6 -2
  87. data/lib/ddtrace/contrib/httprb/configuration/settings.rb +7 -2
  88. data/lib/ddtrace/contrib/httprb/ext.rb +5 -2
  89. data/lib/ddtrace/contrib/httprb/instrumentation.rb +8 -8
  90. data/lib/ddtrace/contrib/kafka/configuration/settings.rb +7 -2
  91. data/lib/ddtrace/contrib/kafka/event.rb +1 -1
  92. data/lib/ddtrace/contrib/kafka/ext.rb +5 -2
  93. data/lib/ddtrace/contrib/mongodb/configuration/settings.rb +7 -2
  94. data/lib/ddtrace/contrib/mongodb/ext.rb +5 -2
  95. data/lib/ddtrace/contrib/mongodb/subscribers.rb +4 -0
  96. data/lib/ddtrace/contrib/mysql2/configuration/settings.rb +7 -2
  97. data/lib/ddtrace/contrib/mysql2/ext.rb +5 -2
  98. data/lib/ddtrace/contrib/mysql2/instrumentation.rb +4 -0
  99. data/lib/ddtrace/contrib/presto/configuration/settings.rb +7 -2
  100. data/lib/ddtrace/contrib/presto/ext.rb +5 -2
  101. data/lib/ddtrace/contrib/presto/instrumentation.rb +3 -0
  102. data/lib/ddtrace/contrib/que/configuration/settings.rb +43 -0
  103. data/lib/ddtrace/contrib/que/ext.rb +30 -0
  104. data/lib/ddtrace/contrib/que/integration.rb +42 -0
  105. data/lib/ddtrace/contrib/que/patcher.rb +24 -0
  106. data/lib/ddtrace/contrib/que/tracer.rb +57 -0
  107. data/lib/ddtrace/contrib/racecar/configuration/settings.rb +7 -2
  108. data/lib/ddtrace/contrib/racecar/event.rb +4 -0
  109. data/lib/ddtrace/contrib/racecar/events.rb +2 -0
  110. data/lib/ddtrace/contrib/racecar/events/consume.rb +27 -0
  111. data/lib/ddtrace/contrib/racecar/ext.rb +6 -2
  112. data/lib/ddtrace/contrib/rack/configuration/settings.rb +7 -2
  113. data/lib/ddtrace/contrib/rack/ext.rb +5 -2
  114. data/lib/ddtrace/contrib/rack/middlewares.rb +2 -0
  115. data/lib/ddtrace/contrib/rails/configuration/settings.rb +12 -2
  116. data/lib/ddtrace/contrib/rails/ext.rb +6 -2
  117. data/lib/ddtrace/contrib/rails/log_injection.rb +81 -0
  118. data/lib/ddtrace/contrib/rails/middlewares.rb +7 -2
  119. data/lib/ddtrace/contrib/rails/patcher.rb +29 -0
  120. data/lib/ddtrace/contrib/rake/configuration/settings.rb +7 -3
  121. data/lib/ddtrace/contrib/rake/ext.rb +5 -2
  122. data/lib/ddtrace/contrib/redis/configuration/settings.rb +7 -2
  123. data/lib/ddtrace/contrib/redis/ext.rb +5 -2
  124. data/lib/ddtrace/contrib/redis/tags.rb +4 -0
  125. data/lib/ddtrace/contrib/resque/configuration/settings.rb +8 -2
  126. data/lib/ddtrace/contrib/resque/ext.rb +5 -2
  127. data/lib/ddtrace/contrib/resque/integration.rb +1 -1
  128. data/lib/ddtrace/contrib/resque/resque_job.rb +1 -1
  129. data/lib/ddtrace/contrib/rest_client/configuration/settings.rb +7 -2
  130. data/lib/ddtrace/contrib/rest_client/ext.rb +5 -2
  131. data/lib/ddtrace/contrib/rest_client/request_patch.rb +4 -0
  132. data/lib/ddtrace/contrib/rspec/configuration/settings.rb +38 -0
  133. data/lib/ddtrace/contrib/rspec/example.rb +61 -0
  134. data/lib/ddtrace/contrib/rspec/example_group.rb +61 -0
  135. data/lib/ddtrace/contrib/rspec/ext.rb +19 -0
  136. data/lib/ddtrace/contrib/rspec/integration.rb +41 -0
  137. data/lib/ddtrace/contrib/rspec/patcher.rb +25 -0
  138. data/lib/ddtrace/contrib/sequel/configuration/settings.rb +7 -2
  139. data/lib/ddtrace/contrib/sequel/database.rb +3 -1
  140. data/lib/ddtrace/contrib/sequel/dataset.rb +3 -2
  141. data/lib/ddtrace/contrib/sequel/ext.rb +6 -2
  142. data/lib/ddtrace/contrib/sequel/utils.rb +35 -6
  143. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +8 -2
  144. data/lib/ddtrace/contrib/shoryuken/ext.rb +5 -2
  145. data/lib/ddtrace/contrib/shoryuken/tracer.rb +4 -1
  146. data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +8 -2
  147. data/lib/ddtrace/contrib/sidekiq/ext.rb +5 -2
  148. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +4 -1
  149. data/lib/ddtrace/contrib/sinatra/configuration/settings.rb +7 -2
  150. data/lib/ddtrace/contrib/sinatra/env.rb +5 -4
  151. data/lib/ddtrace/contrib/sinatra/ext.rb +5 -2
  152. data/lib/ddtrace/contrib/sinatra/tracer.rb +21 -42
  153. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +50 -23
  154. data/lib/ddtrace/contrib/sneakers/configuration/settings.rb +33 -0
  155. data/lib/ddtrace/contrib/sneakers/ext.rb +22 -0
  156. data/lib/ddtrace/contrib/sneakers/integration.rb +41 -0
  157. data/lib/ddtrace/contrib/sneakers/patcher.rb +24 -0
  158. data/lib/ddtrace/contrib/sneakers/tracer.rb +55 -0
  159. data/lib/ddtrace/contrib/status_code_matcher.rb +67 -0
  160. data/lib/ddtrace/contrib/sucker_punch/configuration/settings.rb +7 -2
  161. data/lib/ddtrace/contrib/sucker_punch/ext.rb +5 -2
  162. data/lib/ddtrace/diagnostics/environment_logger.rb +1 -1
  163. data/lib/ddtrace/environment.rb +14 -4
  164. data/lib/ddtrace/ext/app_types.rb +1 -0
  165. data/lib/ddtrace/ext/ci.rb +265 -0
  166. data/lib/ddtrace/ext/diagnostics.rb +2 -1
  167. data/lib/ddtrace/ext/distributed.rb +8 -2
  168. data/lib/ddtrace/ext/git.rb +12 -0
  169. data/lib/ddtrace/ext/integration.rb +8 -0
  170. data/lib/ddtrace/ext/runtime.rb +2 -0
  171. data/lib/ddtrace/ext/test.rb +24 -0
  172. data/lib/ddtrace/ext/transport.rb +1 -0
  173. data/lib/ddtrace/logger.rb +1 -1
  174. data/lib/ddtrace/opentracer/distributed_headers.rb +1 -1
  175. data/lib/ddtrace/propagation/grpc_propagator.rb +18 -6
  176. data/lib/ddtrace/runtime/identity.rb +4 -5
  177. data/lib/ddtrace/runtime/metrics.rb +24 -6
  178. data/lib/ddtrace/sampler.rb +2 -2
  179. data/lib/ddtrace/sampling/rate_limiter.rb +65 -16
  180. data/lib/ddtrace/span.rb +152 -27
  181. data/lib/ddtrace/tracer.rb +25 -13
  182. data/lib/ddtrace/transport/http.rb +15 -0
  183. data/lib/ddtrace/transport/http/adapters/net.rb +8 -2
  184. data/lib/ddtrace/transport/http/adapters/test.rb +2 -0
  185. data/lib/ddtrace/transport/http/statistics.rb +14 -1
  186. data/lib/ddtrace/transport/traces.rb +7 -2
  187. data/lib/ddtrace/utils.rb +16 -13
  188. data/lib/ddtrace/utils/forking.rb +52 -0
  189. data/lib/ddtrace/version.rb +1 -1
  190. data/lib/ddtrace/workers/async.rb +2 -2
  191. data/lib/ddtrace/workers/loop.rb +1 -1
  192. data/lib/ddtrace/workers/polling.rb +1 -1
  193. data/lib/ddtrace/writer.rb +19 -1
  194. metadata +53 -6
@@ -1,4 +1,3 @@
1
- require 'pp'
2
1
  require 'thread'
3
2
  require 'logger'
4
3
  require 'pathname'
@@ -8,6 +7,7 @@ require 'ddtrace/span'
8
7
  require 'ddtrace/context'
9
8
  require 'ddtrace/logger'
10
9
  require 'ddtrace/writer'
10
+ require 'ddtrace/runtime/identity'
11
11
  require 'ddtrace/sampler'
12
12
  require 'ddtrace/sampling'
13
13
  require 'ddtrace/correlation'
@@ -60,8 +60,8 @@ module Datadog
60
60
  #
61
61
  # This method makes use of a \ContextProvider that is automatically set during the tracer
62
62
  # initialization, or while using a library instrumentation.
63
- def call_context
64
- @provider.context
63
+ def call_context(key = nil)
64
+ @provider.context(key)
65
65
  end
66
66
 
67
67
  # Initialize a new \Tracer used to create, sample and submit spans that measure the
@@ -186,8 +186,7 @@ module Datadog
186
186
  # * +start_time+: when the span actually starts (defaults to \now)
187
187
  # * +tags+: extra tags which should be added to the span.
188
188
  def start_span(name, options = {})
189
- start_time = options.fetch(:start_time, Time.now.utc)
190
-
189
+ start_time = options[:start_time]
191
190
  tags = options.fetch(:tags, {})
192
191
 
193
192
  span_options = options.select do |k, _v|
@@ -203,6 +202,7 @@ module Datadog
203
202
  # root span
204
203
  @sampler.sample!(span)
205
204
  span.set_tag('system.pid', Process.pid)
205
+ span.set_tag(Datadog::Ext::Runtime::TAG_ID, Datadog::Runtime::Identity.id)
206
206
 
207
207
  if ctx && ctx.trace_id
208
208
  span.trace_id = ctx.trace_id
@@ -212,9 +212,10 @@ module Datadog
212
212
  # child span
213
213
  span.parent = parent # sets service, trace_id, parent_id, sampled
214
214
  end
215
+
215
216
  span.set_tags(@tags) unless @tags.empty?
216
217
  span.set_tags(tags) unless tags.empty?
217
- span.start_time = start_time
218
+ span.start(start_time)
218
219
 
219
220
  # this could at some point be optional (start_active_span vs start_manual_span)
220
221
  ctx.add_span(span) unless ctx.nil?
@@ -288,8 +289,19 @@ module Datadog
288
289
  # and it is user code which should be executed no matter what.
289
290
  # It's not a problem since we re-raise it afterwards so for example a
290
291
  # SignalException::Interrupt would still bubble up.
292
+ # rubocop:disable Metrics/BlockNesting
291
293
  rescue Exception => e
292
- (options[:on_error] || DEFAULT_ON_ERROR).call(span, e)
294
+ if (on_error_handler = options[:on_error]) && on_error_handler.respond_to?(:call)
295
+ begin
296
+ on_error_handler.call(span, e)
297
+ rescue
298
+ Datadog.logger.debug('Custom on_error handler failed, falling back to default')
299
+ DEFAULT_ON_ERROR.call(span, e)
300
+ end
301
+ else
302
+ Datadog.logger.debug('Custom on_error handler must be a callable, falling back to default') if on_error_handler
303
+ DEFAULT_ON_ERROR.call(span, e)
304
+ end
293
305
  raise e
294
306
  ensure
295
307
  span.finish unless span.nil?
@@ -325,18 +337,18 @@ module Datadog
325
337
  end
326
338
 
327
339
  # Return the current active span or +nil+.
328
- def active_span
329
- call_context.current_span
340
+ def active_span(key = nil)
341
+ call_context(key).current_span
330
342
  end
331
343
 
332
344
  # Return the current active root span or +nil+.
333
- def active_root_span
334
- call_context.current_root_span
345
+ def active_root_span(key = nil)
346
+ call_context(key).current_root_span
335
347
  end
336
348
 
337
349
  # Return a CorrelationIdentifier for active span
338
- def active_correlation
339
- Datadog::Correlation.identifier_from_context(call_context)
350
+ def active_correlation(key = nil)
351
+ Datadog::Correlation.identifier_from_context(call_context(key))
340
352
  end
341
353
 
342
354
  # Send the trace to the writer to enqueue the spans list in the agent
@@ -10,6 +10,7 @@ require 'ddtrace/transport/http/api'
10
10
  require 'ddtrace/transport/http/adapters/net'
11
11
  require 'ddtrace/transport/http/adapters/test'
12
12
  require 'ddtrace/transport/http/adapters/unix_socket'
13
+ require 'uri'
13
14
 
14
15
  module Datadog
15
16
  module Transport
@@ -75,13 +76,27 @@ module Datadog
75
76
  end
76
77
 
77
78
  def default_hostname
79
+ return default_url.hostname if default_url
80
+
78
81
  ENV.fetch(Datadog::Ext::Transport::HTTP::ENV_DEFAULT_HOST, Datadog::Ext::Transport::HTTP::DEFAULT_HOST)
79
82
  end
80
83
 
81
84
  def default_port
85
+ return default_url.port if default_url
86
+
82
87
  ENV.fetch(Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT, Datadog::Ext::Transport::HTTP::DEFAULT_PORT).to_i
83
88
  end
84
89
 
90
+ def default_url
91
+ url_env = ENV.fetch(Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL, nil)
92
+
93
+ if url_env
94
+ uri_parsed = URI.parse(url_env)
95
+
96
+ uri_parsed if %w[http https].include?(uri_parsed.scheme)
97
+ end
98
+ end
99
+
85
100
  # Add adapters to registry
86
101
  Builder::REGISTRY.set(Adapters::Net, :net_http)
87
102
  Builder::REGISTRY.set(Adapters::Test, :test)
@@ -20,8 +20,14 @@ module Datadog
20
20
  end
21
21
 
22
22
  def open
23
- # Open connection
24
- ::Net::HTTP.start(hostname, port, open_timeout: timeout, read_timeout: timeout) do |http|
23
+ # DEV Initializing +Net::HTTP+ directly help us avoid expensive
24
+ # options processing done in +Net::HTTP.start+:
25
+ # https://github.com/ruby/ruby/blob/b2d96abb42abbe2e01f010ffc9ac51f0f9a50002/lib/net/http.rb#L614-L618
26
+ req = ::Net::HTTP.new(hostname, port, nil)
27
+
28
+ req.open_timeout = req.read_timeout = timeout
29
+
30
+ req.start do |http|
25
31
  yield(http)
26
32
  end
27
33
  end
@@ -33,6 +33,8 @@ module Datadog
33
33
  @status = status
34
34
  end
35
35
 
36
+ def url; end
37
+
36
38
  # Response for test adapter
37
39
  class Response
38
40
  include Datadog::Transport::Response
@@ -18,11 +18,24 @@ module Datadog
18
18
  # Add status code tag to api.responses metric
19
19
  if metrics.key?(:api_responses)
20
20
  (metrics[:api_responses].options[:tags] ||= []).tap do |tags|
21
- tags << "status_code:#{response.code}"
21
+ tags << metrics_tag_value(response.code)
22
22
  end
23
23
  end
24
24
  end
25
25
  end
26
+
27
+ private
28
+
29
+ # The most common status code on a healthy tracer
30
+ STATUS_CODE_200 = 'status_code:200'.freeze
31
+
32
+ def metrics_tag_value(status_code)
33
+ if status_code == 200
34
+ STATUS_CODE_200 # DEV Saves string concatenation/creation for common case
35
+ else
36
+ "status_code:#{status_code}"
37
+ end
38
+ end
26
39
  end
27
40
  end
28
41
  end
@@ -57,7 +57,12 @@ module Datadog
57
57
  # @return [Enumerable[Array[Bytes,Integer]]] list of encoded chunks: each containing a byte array and
58
58
  # number of traces
59
59
  def encode_in_chunks(traces)
60
- encoded_traces = traces.map { |t| encode_one(t) }.reject(&:nil?)
60
+ encoded_traces = if traces.respond_to?(:filter_map)
61
+ # DEV Supported since Ruby 2.7, saves an intermediate object creation
62
+ traces.filter_map { |t| encode_one(t) }
63
+ else
64
+ traces.map { |t| encode_one(t) }.reject(&:nil?)
65
+ end
61
66
 
62
67
  Datadog::Chunker.chunk_by_size(encoded_traces, max_size).map do |chunk|
63
68
  [encoder.join(chunk), chunk.size]
@@ -86,7 +91,7 @@ module Datadog
86
91
  module_function
87
92
 
88
93
  def encode_trace(encoder, trace)
89
- encoder.encode(trace.map(&:to_hash))
94
+ encoder.encode(trace)
90
95
  end
91
96
  end
92
97
 
@@ -1,32 +1,31 @@
1
1
  require 'ddtrace/utils/database'
2
+ require 'ddtrace/utils/forking'
2
3
 
3
4
  module Datadog
4
5
  # Utils contains low-level utilities, typically to provide pseudo-random trace IDs.
5
6
  module Utils
6
- STRING_PLACEHOLDER = ''.encode(::Encoding::UTF_8).freeze
7
+ extend Utils::Forking
8
+
9
+ EMPTY_STRING = ''.encode(::Encoding::UTF_8).freeze
7
10
  # We use a custom random number generator because we want no interference
8
11
  # with the default one. Using the default prng, we could break code that
9
12
  # would rely on srand/rand sequences.
10
13
 
11
14
  # Return a span id
12
15
  def self.next_id
13
- reset! if was_forked?
14
-
15
- @rnd.rand(Datadog::Span::MAX_ID)
16
+ after_fork! { reset! }
17
+ id_rng.rand(Datadog::Span::RUBY_MAX_ID)
16
18
  end
17
19
 
18
- def self.reset!
19
- @pid = Process.pid
20
- @rnd = Random.new
20
+ def self.id_rng
21
+ @id_rng ||= Random.new
21
22
  end
22
23
 
23
- def self.was_forked?
24
- Process.pid != @pid
24
+ def self.reset!
25
+ @id_rng = Random.new
25
26
  end
26
27
 
27
- private_class_method :reset!, :was_forked?
28
-
29
- reset!
28
+ private_class_method :id_rng, :reset!
30
29
 
31
30
  def self.truncate(value, size, omission = '...'.freeze)
32
31
  string = value.to_s
@@ -53,13 +52,17 @@ module Datadog
53
52
  str.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
54
53
  elsif str.encoding == ::Encoding::UTF_8
55
54
  str
55
+ elsif str.empty?
56
+ # DEV Optimization as `nil.to_s` is a very common source for an empty string,
57
+ # DEV but it comes encoded as US_ASCII.
58
+ EMPTY_STRING
56
59
  else
57
60
  str.encode(::Encoding::UTF_8)
58
61
  end
59
62
  rescue => e
60
63
  Datadog.logger.debug("Error encoding string in UTF-8: #{e}")
61
64
 
62
- options.fetch(:placeholder, STRING_PLACEHOLDER)
65
+ options.fetch(:placeholder, EMPTY_STRING)
63
66
  end
64
67
  end
65
68
  end
@@ -0,0 +1,52 @@
1
+ module Datadog
2
+ module Utils
3
+ # Helper methods for managing forking behavior
4
+ module Forking
5
+ def self.included(base)
6
+ base.send(:prepend, ClassExtensions) if base.is_a?(Class)
7
+ end
8
+
9
+ def self.extended(base)
10
+ # Explicitly update PID here because there's a case where
11
+ # the code path that lazily updates the PID may not be exercised
12
+ # until after a fork occurs, thus causing the event to be missed.
13
+ # By eagerly setting this, we avoid this scenario.
14
+ base.update_fork_pid!
15
+ end
16
+
17
+ def after_fork!
18
+ if forked?
19
+ yield
20
+ update_fork_pid!
21
+ true
22
+ else
23
+ false
24
+ end
25
+ end
26
+
27
+ def forked?
28
+ Process.pid != fork_pid
29
+ end
30
+
31
+ def update_fork_pid!
32
+ @fork_pid = Process.pid
33
+ end
34
+
35
+ def fork_pid
36
+ @fork_pid ||= Process.pid
37
+ end
38
+
39
+ # Adds additional functionality for Classes that implement Forking
40
+ module ClassExtensions
41
+ # Addresses an edge case where forking before invoking #update_fork_pid! on the
42
+ # object will cause forking to not be detected in the fork when it should have.
43
+ #
44
+ # This wrapper prevents this by initializing the fork PID when the object is created.
45
+ def initialize(*args, &block)
46
+ super
47
+ update_fork_pid!
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,7 +1,7 @@
1
1
  module Datadog
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 38
4
+ MINOR = 43
5
5
  PATCH = 0
6
6
  PRE = nil
7
7
 
@@ -42,7 +42,7 @@ module Datadog
42
42
  end
43
43
 
44
44
  def run_async?
45
- @run_async = false unless instance_variable_defined?(:@run_async)
45
+ return false unless instance_variable_defined?(:@run_async)
46
46
  @run_async == true
47
47
  end
48
48
 
@@ -55,7 +55,7 @@ module Datadog
55
55
  end
56
56
 
57
57
  def error?
58
- @error = nil unless instance_variable_defined?(:@error)
58
+ return false unless instance_variable_defined?(:@error)
59
59
  !@error.nil?
60
60
  end
61
61
 
@@ -33,7 +33,7 @@ module Datadog
33
33
  end
34
34
 
35
35
  def run_loop?
36
- @run_loop = false unless instance_variable_defined?(:@run_loop)
36
+ return false unless instance_variable_defined?(:@run_loop)
37
37
  @run_loop == true
38
38
  end
39
39
 
@@ -34,7 +34,7 @@ module Datadog
34
34
  end
35
35
 
36
36
  def enabled?
37
- @enabled = true unless instance_variable_defined?(:@enabled)
37
+ return true unless instance_variable_defined?(:@enabled)
38
38
  @enabled
39
39
  end
40
40
 
@@ -42,13 +42,22 @@ module Datadog
42
42
 
43
43
  # one worker for traces
44
44
  @worker = nil
45
+
46
+ # Once stopped, this writer instance cannot be restarted.
47
+ # This allow for graceful shutdown, while preventing
48
+ # the host application from inadvertently start new
49
+ # threads during shutdown.
50
+ @stopped = false
45
51
  end
46
52
 
47
53
  def start
48
54
  @mutex_after_fork.synchronize do
55
+ return false if @stopped
56
+
49
57
  pid = Process.pid
50
58
  return if @worker && pid == @pid
51
59
  @pid = pid
60
+
52
61
  start_worker
53
62
  true
54
63
  end
@@ -67,14 +76,23 @@ module Datadog
67
76
  @worker.start
68
77
  end
69
78
 
79
+ # Gracefully shuts down this writer.
80
+ #
81
+ # Once stopped methods calls won't fail, but
82
+ # no internal work will be performed.
83
+ #
84
+ # It is not possible to restart a stopped writer instance.
70
85
  def stop
71
86
  @mutex_after_fork.synchronize { stop_worker }
72
87
  end
73
88
 
74
89
  def stop_worker
90
+ @stopped = true
91
+
75
92
  return if @worker.nil?
76
93
  @worker.stop
77
94
  @worker = nil
95
+
78
96
  true
79
97
  end
80
98
 
@@ -136,7 +154,7 @@ module Datadog
136
154
 
137
155
  if worker_local
138
156
  worker_local.enqueue_trace(trace)
139
- else
157
+ elsif !@stopped
140
158
  Datadog.logger.debug('Writer either failed to start or was stopped before #write could complete')
141
159
  end
142
160
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.38.0
4
+ version: 0.43.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-21 00:00:00.000000000 Z
11
+ date: 2020-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.4.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: concurrent-ruby
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -333,19 +347,19 @@ dependencies:
333
347
  - !ruby/object:Gem::Version
334
348
  version: 0.4.9.2
335
349
  - !ruby/object:Gem::Dependency
336
- name: warning
350
+ name: simplecov
337
351
  requirement: !ruby/object:Gem::Requirement
338
352
  requirements:
339
353
  - - "~>"
340
354
  - !ruby/object:Gem::Version
341
- version: '1'
355
+ version: '0.17'
342
356
  type: :development
343
357
  prerelease: false
344
358
  version_requirements: !ruby/object:Gem::Requirement
345
359
  requirements:
346
360
  - - "~>"
347
361
  - !ruby/object:Gem::Version
348
- version: '1'
362
+ version: '0.17'
349
363
  description: |
350
364
  ddtrace is Datadog’s tracing client for Ruby. It is used to trace requests
351
365
  as they flow across web servers, databases and microservices so that developers
@@ -369,10 +383,13 @@ files:
369
383
  - ".dockerignore"
370
384
  - ".env"
371
385
  - ".github/CODEOWNERS"
386
+ - ".github/workflows/add-milestone-to-pull-requests.yml"
387
+ - ".github/workflows/create-next-milestone.yml"
372
388
  - ".gitignore"
373
389
  - ".gitlab-ci.yml"
374
390
  - ".rspec"
375
391
  - ".rubocop.yml"
392
+ - ".simplecov"
376
393
  - ".yardopts"
377
394
  - Appraisals
378
395
  - CHANGELOG.md
@@ -486,6 +503,12 @@ files:
486
503
  - lib/ddtrace/contrib/configuration/resolver.rb
487
504
  - lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb
488
505
  - lib/ddtrace/contrib/configuration/settings.rb
506
+ - lib/ddtrace/contrib/cucumber/configuration/settings.rb
507
+ - lib/ddtrace/contrib/cucumber/ext.rb
508
+ - lib/ddtrace/contrib/cucumber/formatter.rb
509
+ - lib/ddtrace/contrib/cucumber/instrumentation.rb
510
+ - lib/ddtrace/contrib/cucumber/integration.rb
511
+ - lib/ddtrace/contrib/cucumber/patcher.rb
489
512
  - lib/ddtrace/contrib/dalli/configuration/settings.rb
490
513
  - lib/ddtrace/contrib/dalli/ext.rb
491
514
  - lib/ddtrace/contrib/dalli/instrumentation.rb
@@ -588,10 +611,16 @@ files:
588
611
  - lib/ddtrace/contrib/presto/instrumentation.rb
589
612
  - lib/ddtrace/contrib/presto/integration.rb
590
613
  - lib/ddtrace/contrib/presto/patcher.rb
614
+ - lib/ddtrace/contrib/que/configuration/settings.rb
615
+ - lib/ddtrace/contrib/que/ext.rb
616
+ - lib/ddtrace/contrib/que/integration.rb
617
+ - lib/ddtrace/contrib/que/patcher.rb
618
+ - lib/ddtrace/contrib/que/tracer.rb
591
619
  - lib/ddtrace/contrib/racecar/configuration/settings.rb
592
620
  - lib/ddtrace/contrib/racecar/event.rb
593
621
  - lib/ddtrace/contrib/racecar/events.rb
594
622
  - lib/ddtrace/contrib/racecar/events/batch.rb
623
+ - lib/ddtrace/contrib/racecar/events/consume.rb
595
624
  - lib/ddtrace/contrib/racecar/events/message.rb
596
625
  - lib/ddtrace/contrib/racecar/ext.rb
597
626
  - lib/ddtrace/contrib/racecar/integration.rb
@@ -606,6 +635,7 @@ files:
606
635
  - lib/ddtrace/contrib/rails/ext.rb
607
636
  - lib/ddtrace/contrib/rails/framework.rb
608
637
  - lib/ddtrace/contrib/rails/integration.rb
638
+ - lib/ddtrace/contrib/rails/log_injection.rb
609
639
  - lib/ddtrace/contrib/rails/middlewares.rb
610
640
  - lib/ddtrace/contrib/rails/patcher.rb
611
641
  - lib/ddtrace/contrib/rails/railtie.rb
@@ -635,6 +665,12 @@ files:
635
665
  - lib/ddtrace/contrib/rest_client/integration.rb
636
666
  - lib/ddtrace/contrib/rest_client/patcher.rb
637
667
  - lib/ddtrace/contrib/rest_client/request_patch.rb
668
+ - lib/ddtrace/contrib/rspec/configuration/settings.rb
669
+ - lib/ddtrace/contrib/rspec/example.rb
670
+ - lib/ddtrace/contrib/rspec/example_group.rb
671
+ - lib/ddtrace/contrib/rspec/ext.rb
672
+ - lib/ddtrace/contrib/rspec/integration.rb
673
+ - lib/ddtrace/contrib/rspec/patcher.rb
638
674
  - lib/ddtrace/contrib/sequel/configuration/settings.rb
639
675
  - lib/ddtrace/contrib/sequel/database.rb
640
676
  - lib/ddtrace/contrib/sequel/dataset.rb
@@ -662,6 +698,12 @@ files:
662
698
  - lib/ddtrace/contrib/sinatra/patcher.rb
663
699
  - lib/ddtrace/contrib/sinatra/tracer.rb
664
700
  - lib/ddtrace/contrib/sinatra/tracer_middleware.rb
701
+ - lib/ddtrace/contrib/sneakers/configuration/settings.rb
702
+ - lib/ddtrace/contrib/sneakers/ext.rb
703
+ - lib/ddtrace/contrib/sneakers/integration.rb
704
+ - lib/ddtrace/contrib/sneakers/patcher.rb
705
+ - lib/ddtrace/contrib/sneakers/tracer.rb
706
+ - lib/ddtrace/contrib/status_code_matcher.rb
665
707
  - lib/ddtrace/contrib/sucker_punch/configuration/settings.rb
666
708
  - lib/ddtrace/contrib/sucker_punch/exception_handler.rb
667
709
  - lib/ddtrace/contrib/sucker_punch/ext.rb
@@ -682,13 +724,16 @@ files:
682
724
  - lib/ddtrace/event.rb
683
725
  - lib/ddtrace/ext/analytics.rb
684
726
  - lib/ddtrace/ext/app_types.rb
727
+ - lib/ddtrace/ext/ci.rb
685
728
  - lib/ddtrace/ext/correlation.rb
686
729
  - lib/ddtrace/ext/diagnostics.rb
687
730
  - lib/ddtrace/ext/distributed.rb
688
731
  - lib/ddtrace/ext/environment.rb
689
732
  - lib/ddtrace/ext/errors.rb
690
733
  - lib/ddtrace/ext/forced_tracing.rb
734
+ - lib/ddtrace/ext/git.rb
691
735
  - lib/ddtrace/ext/http.rb
736
+ - lib/ddtrace/ext/integration.rb
692
737
  - lib/ddtrace/ext/manual_tracing.rb
693
738
  - lib/ddtrace/ext/metrics.rb
694
739
  - lib/ddtrace/ext/net.rb
@@ -696,6 +741,7 @@ files:
696
741
  - lib/ddtrace/ext/runtime.rb
697
742
  - lib/ddtrace/ext/sampling.rb
698
743
  - lib/ddtrace/ext/sql.rb
744
+ - lib/ddtrace/ext/test.rb
699
745
  - lib/ddtrace/ext/transport.rb
700
746
  - lib/ddtrace/forced_tracing.rb
701
747
  - lib/ddtrace/logger.rb
@@ -774,6 +820,7 @@ files:
774
820
  - lib/ddtrace/transport/traces.rb
775
821
  - lib/ddtrace/utils.rb
776
822
  - lib/ddtrace/utils/database.rb
823
+ - lib/ddtrace/utils/forking.rb
777
824
  - lib/ddtrace/utils/time.rb
778
825
  - lib/ddtrace/vendor/active_record/connection_specification.rb
779
826
  - lib/ddtrace/version.rb
@@ -808,7 +855,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
808
855
  version: 2.0.0
809
856
  requirements: []
810
857
  rubyforge_project:
811
- rubygems_version: 2.7.6.2
858
+ rubygems_version: 2.2.5
812
859
  signing_key:
813
860
  specification_version: 4
814
861
  summary: Datadog tracing code for your Ruby applications