ddtrace 0.38.0 → 0.43.0

Sign up to get free protection for your applications and to get access to all the features.
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