ddtrace 0.34.1 → 0.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +58 -9
  3. data/.circleci/images/primary/Dockerfile-jruby-9.2 +77 -0
  4. data/.rubocop.yml +4 -0
  5. data/Appraisals +9 -7
  6. data/CHANGELOG.md +89 -3
  7. data/Rakefile +11 -2
  8. data/ddtrace.gemspec +5 -3
  9. data/docker-compose.yml +35 -0
  10. data/docs/DevelopmentGuide.md +1 -1
  11. data/docs/GettingStarted.md +89 -36
  12. data/lib/ddtrace.rb +1 -1
  13. data/lib/ddtrace/buffer.rb +9 -9
  14. data/lib/ddtrace/chunker.rb +34 -0
  15. data/lib/ddtrace/configuration.rb +28 -5
  16. data/lib/ddtrace/configuration/base.rb +1 -1
  17. data/lib/ddtrace/configuration/components.rb +154 -0
  18. data/lib/ddtrace/configuration/options.rb +1 -1
  19. data/lib/ddtrace/configuration/settings.rb +131 -63
  20. data/lib/ddtrace/context.rb +6 -6
  21. data/lib/ddtrace/context_flush.rb +1 -1
  22. data/lib/ddtrace/contrib/action_cable/instrumentation.rb +1 -1
  23. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +2 -2
  24. data/lib/ddtrace/contrib/action_view/events/render_partial.rb +1 -1
  25. data/lib/ddtrace/contrib/action_view/events/render_template.rb +1 -1
  26. data/lib/ddtrace/contrib/action_view/instrumentation/partial_renderer.rb +1 -1
  27. data/lib/ddtrace/contrib/action_view/instrumentation/template_renderer.rb +2 -2
  28. data/lib/ddtrace/contrib/action_view/patcher.rb +1 -1
  29. data/lib/ddtrace/contrib/active_record/events/instantiation.rb +1 -1
  30. data/lib/ddtrace/contrib/active_record/events/sql.rb +1 -1
  31. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +2 -2
  32. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +2 -2
  33. data/lib/ddtrace/contrib/analytics.rb +1 -1
  34. data/lib/ddtrace/contrib/configuration/settings.rb +1 -1
  35. data/lib/ddtrace/contrib/dalli/patcher.rb +1 -1
  36. data/lib/ddtrace/contrib/dalli/quantize.rb +1 -1
  37. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -1
  38. data/lib/ddtrace/contrib/excon/middleware.rb +2 -2
  39. data/lib/ddtrace/contrib/extensions.rb +29 -5
  40. data/lib/ddtrace/contrib/faraday/patcher.rb +1 -1
  41. data/lib/ddtrace/contrib/grape/endpoint.rb +5 -5
  42. data/lib/ddtrace/contrib/grape/patcher.rb +1 -1
  43. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +1 -1
  44. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +2 -2
  45. data/lib/ddtrace/contrib/grpc/patcher.rb +1 -1
  46. data/lib/ddtrace/contrib/http/circuit_breaker.rb +8 -32
  47. data/lib/ddtrace/contrib/http/instrumentation.rb +2 -2
  48. data/lib/ddtrace/contrib/mongodb/subscribers.rb +2 -2
  49. data/lib/ddtrace/contrib/patchable.rb +1 -1
  50. data/lib/ddtrace/contrib/patcher.rb +3 -3
  51. data/lib/ddtrace/contrib/presto/instrumentation.rb +3 -3
  52. data/lib/ddtrace/contrib/presto/patcher.rb +1 -1
  53. data/lib/ddtrace/contrib/rack/middlewares.rb +2 -2
  54. data/lib/ddtrace/contrib/rack/patcher.rb +2 -2
  55. data/lib/ddtrace/contrib/rack/request_queue.rb +1 -1
  56. data/lib/ddtrace/contrib/rails/configuration/settings.rb +14 -0
  57. data/lib/ddtrace/contrib/rails/framework.rb +54 -48
  58. data/lib/ddtrace/contrib/rails/integration.rb +1 -1
  59. data/lib/ddtrace/contrib/rake/instrumentation.rb +2 -2
  60. data/lib/ddtrace/contrib/redis/quantize.rb +1 -1
  61. data/lib/ddtrace/contrib/resque/resque_job.rb +2 -2
  62. data/lib/ddtrace/contrib/sidekiq/tracing.rb +1 -1
  63. data/lib/ddtrace/contrib/sinatra/env.rb +20 -0
  64. data/lib/ddtrace/contrib/sinatra/ext.rb +6 -0
  65. data/lib/ddtrace/contrib/sinatra/patcher.rb +1 -0
  66. data/lib/ddtrace/contrib/sinatra/tracer.rb +98 -35
  67. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +16 -13
  68. data/lib/ddtrace/correlation.rb +9 -6
  69. data/lib/ddtrace/diagnostics/health.rb +2 -6
  70. data/lib/ddtrace/encoding.rb +13 -39
  71. data/lib/ddtrace/event.rb +1 -1
  72. data/lib/ddtrace/ext/correlation.rb +1 -0
  73. data/lib/ddtrace/ext/diagnostics.rb +2 -0
  74. data/lib/ddtrace/ext/environment.rb +1 -0
  75. data/lib/ddtrace/ext/forced_tracing.rb +1 -1
  76. data/lib/ddtrace/logger.rb +3 -44
  77. data/lib/ddtrace/metrics.rb +5 -5
  78. data/lib/ddtrace/monkey.rb +1 -1
  79. data/lib/ddtrace/opentracer/global_tracer.rb +1 -1
  80. data/lib/ddtrace/pin.rb +18 -17
  81. data/lib/ddtrace/pipeline.rb +1 -1
  82. data/lib/ddtrace/propagation/http_propagator.rb +2 -2
  83. data/lib/ddtrace/runtime/cgroup.rb +1 -1
  84. data/lib/ddtrace/runtime/container.rb +1 -1
  85. data/lib/ddtrace/runtime/metrics.rb +5 -2
  86. data/lib/ddtrace/sampler.rb +2 -2
  87. data/lib/ddtrace/sampling/rule.rb +1 -1
  88. data/lib/ddtrace/sampling/rule_sampler.rb +1 -1
  89. data/lib/ddtrace/span.rb +4 -4
  90. data/lib/ddtrace/sync_writer.rb +3 -8
  91. data/lib/ddtrace/tracer.rb +26 -31
  92. data/lib/ddtrace/transport/http.rb +1 -1
  93. data/lib/ddtrace/transport/http/api/instance.rb +4 -0
  94. data/lib/ddtrace/transport/http/builder.rb +3 -5
  95. data/lib/ddtrace/transport/http/client.rb +7 -64
  96. data/lib/ddtrace/transport/http/response.rb +1 -1
  97. data/lib/ddtrace/transport/http/statistics.rb +1 -1
  98. data/lib/ddtrace/transport/http/traces.rb +10 -7
  99. data/lib/ddtrace/transport/io.rb +1 -1
  100. data/lib/ddtrace/transport/io/client.rb +2 -2
  101. data/lib/ddtrace/transport/io/response.rb +3 -1
  102. data/lib/ddtrace/transport/io/traces.rb +50 -3
  103. data/lib/ddtrace/transport/parcel.rb +0 -4
  104. data/lib/ddtrace/transport/statistics.rb +2 -2
  105. data/lib/ddtrace/transport/traces.rb +160 -10
  106. data/lib/ddtrace/utils.rb +1 -1
  107. data/lib/ddtrace/version.rb +2 -2
  108. data/lib/ddtrace/workers.rb +5 -13
  109. data/lib/ddtrace/workers/async.rb +2 -2
  110. data/lib/ddtrace/workers/runtime_metrics.rb +47 -0
  111. data/lib/ddtrace/workers/trace_writer.rb +199 -0
  112. data/lib/ddtrace/writer.rb +20 -27
  113. metadata +22 -32
@@ -0,0 +1,199 @@
1
+ require 'ddtrace/logger'
2
+ require 'ddtrace/transport/http'
3
+
4
+ require 'ddtrace/event'
5
+ require 'ddtrace/worker'
6
+ require 'ddtrace/workers/polling'
7
+ require 'ddtrace/workers/queue'
8
+
9
+ module Datadog
10
+ module Workers
11
+ # Writes traces to transport synchronously
12
+ class TraceWriter < Worker
13
+ attr_reader \
14
+ :transport
15
+
16
+ def initialize(options = {})
17
+ transport_options = options.fetch(:transport_options, {})
18
+
19
+ if transport_options.is_a?(Proc)
20
+ transport_options = { on_build: transport_options }
21
+ end
22
+
23
+ transport_options[:hostname] = options[:hostname] if options.key?(:hostname)
24
+ transport_options[:port] = options[:port] if options.key?(:port)
25
+
26
+ @transport = options.fetch(:transport) do
27
+ Transport::HTTP.default(transport_options)
28
+ end
29
+ end
30
+
31
+ def perform(traces)
32
+ write_traces(traces)
33
+ end
34
+
35
+ def write(trace)
36
+ write_traces([trace])
37
+ end
38
+
39
+ def write_traces(traces)
40
+ traces = process_traces(traces)
41
+ flush_traces(traces)
42
+ rescue StandardError => e
43
+ Datadog.logger.error(
44
+ "Error while writing traces: dropped #{traces.length} items. Cause: #{e} Location: #{e.backtrace.first}"
45
+ )
46
+ end
47
+
48
+ def process_traces(traces)
49
+ # Run traces through the processing pipeline
50
+ traces = Pipeline.process!(traces)
51
+
52
+ # Inject hostname if configured to do so
53
+ inject_hostname!(traces) if Datadog.configuration.report_hostname
54
+
55
+ traces
56
+ end
57
+
58
+ def flush_traces(traces)
59
+ transport.send_traces(traces).tap do |response|
60
+ flush_completed.publish(response)
61
+ end
62
+ end
63
+
64
+ def inject_hostname!(traces)
65
+ traces.each do |trace|
66
+ next if trace.first.nil?
67
+
68
+ hostname = Datadog::Runtime::Socket.hostname
69
+ unless hostname.nil? || hostname.empty?
70
+ trace.first.set_tag(Ext::NET::TAG_HOSTNAME, hostname)
71
+ end
72
+ end
73
+ end
74
+
75
+ def flush_completed
76
+ @flush_completed ||= FlushCompleted.new
77
+ end
78
+
79
+ # Flush completed event for worker
80
+ class FlushCompleted < Event
81
+ def initialize
82
+ super(:flush_completed)
83
+ end
84
+
85
+ def publish(response)
86
+ super(response)
87
+ end
88
+ end
89
+ end
90
+
91
+ # Writes traces to transport asynchronously,
92
+ # using a thread & buffer.
93
+ class AsyncTraceWriter < TraceWriter
94
+ include Workers::Queue
95
+ include Workers::Polling
96
+
97
+ DEFAULT_BUFFER_MAX_SIZE = 1000
98
+ FORK_POLICY_ASYNC = :async
99
+ FORK_POLICY_SYNC = :sync
100
+
101
+ attr_writer \
102
+ :async
103
+
104
+ def initialize(options = {})
105
+ # Workers::TraceWriter settings
106
+ super
107
+
108
+ # Workers::Polling settings
109
+ self.enabled = options.fetch(:enabled, true)
110
+
111
+ # Workers::Async::Thread settings
112
+ @async = true
113
+ self.fork_policy = options.fetch(:fork_policy, FORK_POLICY_ASYNC)
114
+
115
+ # Workers::IntervalLoop settings
116
+ self.loop_base_interval = options[:interval] if options.key?(:interval)
117
+ self.loop_back_off_ratio = options[:back_off_ratio] if options.key?(:back_off_ratio)
118
+ self.loop_back_off_max = options[:back_off_max] if options.key?(:back_off_max)
119
+
120
+ # Workers::Queue settings
121
+ @buffer_size = options.fetch(:buffer_size, DEFAULT_BUFFER_MAX_SIZE)
122
+ self.buffer = TraceBuffer.new(@buffer_size)
123
+ end
124
+
125
+ # NOTE: #perform is wrapped by other modules:
126
+ # Polling --> Async --> IntervalLoop --> AsyncTraceWriter --> TraceWriter
127
+ def perform(traces)
128
+ super(traces).tap do |responses|
129
+ loop_back_off! if responses.find(&:server_error?)
130
+ end
131
+ end
132
+
133
+ def stop(*args)
134
+ buffer.close if running?
135
+ super
136
+ end
137
+
138
+ def enqueue(trace)
139
+ buffer.push(trace)
140
+ end
141
+
142
+ def dequeue
143
+ # Wrap results in Array because they are
144
+ # splatted as args against TraceWriter#perform.
145
+ [buffer.pop]
146
+ end
147
+
148
+ def work_pending?
149
+ !buffer.empty?
150
+ end
151
+
152
+ def async?
153
+ @async == true
154
+ end
155
+
156
+ def fork_policy=(policy)
157
+ # Translate to Workers::Async::Thread policy
158
+ thread_fork_policy = case policy
159
+ when Workers::Async::Thread::FORK_POLICY_STOP
160
+ policy
161
+ when FORK_POLICY_SYNC
162
+ # Stop the async thread because the writer
163
+ # will bypass and run synchronously.
164
+ Workers::Async::Thread::FORK_POLICY_STOP
165
+ else
166
+ Workers::Async::Thread::FORK_POLICY_RESTART
167
+ end
168
+
169
+ # Update thread fork policy
170
+ super(thread_fork_policy)
171
+
172
+ # Update local policy
173
+ @writer_fork_policy = policy
174
+ end
175
+
176
+ def after_fork
177
+ # In multiprocess environments, forks will share the same buffer until its written to.
178
+ # A.K.A. copy-on-write. We don't want forks to write traces generated from another process.
179
+ # Instead, we reset it after the fork. (Make sure any enqueue operations happen after this.)
180
+ self.buffer = TraceBuffer.new(@buffer_size)
181
+
182
+ # Switch to synchronous mode if configured to do so.
183
+ # In some cases synchronous writing is preferred because the fork will be short lived.
184
+ @async = false if @writer_fork_policy == FORK_POLICY_SYNC
185
+ end
186
+
187
+ def write(trace)
188
+ # Start worker thread. If the process has forked, it will trigger #after_fork to
189
+ # reconfigure the worker accordingly.
190
+ # NOTE: It's important we do this before queuing or it will drop the current trace,
191
+ # because #after_fork resets the buffer.
192
+ perform
193
+
194
+ # Queue the trace if running asynchronously, otherwise short-circuit and write it directly.
195
+ async? ? enqueue(trace) : write_traces([trace])
196
+ end
197
+ end
198
+ end
199
+ end
@@ -13,7 +13,6 @@ module Datadog
13
13
  class Writer
14
14
  attr_reader \
15
15
  :priority_sampler,
16
- :runtime_metrics,
17
16
  :transport,
18
17
  :worker
19
18
 
@@ -34,11 +33,6 @@ module Datadog
34
33
  Transport::HTTP.default(transport_options)
35
34
  end
36
35
 
37
- # Runtime metrics
38
- @runtime_metrics = options.fetch(:runtime_metrics) do
39
- Runtime::Metrics.new
40
- end
41
-
42
36
  # handles the thread creation after an eventual fork
43
37
  @mutex_after_fork = Mutex.new
44
38
  @pid = nil
@@ -53,12 +47,10 @@ module Datadog
53
47
  def start
54
48
  @pid = Process.pid
55
49
  @trace_handler = ->(items, transport) { send_spans(items, transport) }
56
- @runtime_metrics_handler = -> { send_runtime_metrics }
57
50
  @worker = Datadog::Workers::AsyncTransport.new(
58
51
  transport: @transport,
59
52
  buffer_size: @buff_size,
60
53
  on_trace: @trace_handler,
61
- on_runtime_metrics: @runtime_metrics_handler,
62
54
  interval: @flush_interval
63
55
  )
64
56
 
@@ -80,33 +72,26 @@ module Datadog
80
72
  # Inject hostname if configured to do so
81
73
  inject_hostname!(traces) if Datadog.configuration.report_hostname
82
74
 
83
- # Send traces an get a response.
84
- response = transport.send_traces(traces)
85
-
86
- unless response.internal_error?
87
- @traces_flushed += traces.length unless response.server_error?
75
+ # Send traces and get responses
76
+ responses = transport.send_traces(traces)
88
77
 
89
- # Update priority sampler
90
- unless priority_sampler.nil? || response.service_rates.nil?
91
- priority_sampler.update(response.service_rates)
92
- end
78
+ # Tally up successful flushes
79
+ responses.reject { |x| x.internal_error? || x.server_error? }.each do |response|
80
+ @traces_flushed += response.trace_count
93
81
  end
94
82
 
95
- # Return if server error occurred.
96
- !response.server_error?
97
- end
83
+ # Update priority sampler
84
+ update_priority_sampler(responses.last)
98
85
 
99
- def send_runtime_metrics
100
- return unless Datadog.configuration.runtime_metrics_enabled
101
-
102
- runtime_metrics.flush
86
+ # Return if server error occurred.
87
+ !responses.find(&:server_error?)
103
88
  end
104
89
 
105
90
  # enqueue the trace for submission to the API
106
91
  def write(trace, services = nil)
107
92
  unless services.nil?
108
93
  Datadog::Patcher.do_once('Writer#write') do
109
- Datadog::Logger.log.warn(%(
94
+ Datadog.logger.warn(%(
110
95
  write: Writing services has been deprecated and no longer need to be provided.
111
96
  write(traces, services) can be updated to write(traces)
112
97
  ))
@@ -129,9 +114,11 @@ module Datadog
129
114
  end
130
115
  end
131
116
 
117
+ # TODO: Remove this, and have the tracer pump traces directly to runtime metrics
118
+ # instead of working through the trace writer.
132
119
  # Associate root span with runtime metrics
133
- if Datadog.configuration.runtime_metrics_enabled && !trace.empty?
134
- runtime_metrics.associate_with_span(trace.first)
120
+ if Datadog.configuration.runtime_metrics.enabled && !trace.empty?
121
+ Datadog.runtime_metrics.associate_with_span(trace.first)
135
122
  end
136
123
 
137
124
  @worker.enqueue_trace(trace)
@@ -157,5 +144,11 @@ module Datadog
157
144
  end
158
145
  end
159
146
  end
147
+
148
+ def update_priority_sampler(response)
149
+ return unless response && !response.internal_error? && priority_sampler && response.service_rates
150
+
151
+ priority_sampler.update(response.service_rates)
152
+ end
160
153
  end
161
154
  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.34.1
4
+ version: 0.36.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-04-02 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -136,20 +136,6 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '2.2'
139
- - !ruby/object:Gem::Dependency
140
- name: bundler
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "<="
144
- - !ruby/object:Gem::Version
145
- version: 2.1.2
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "<="
151
- - !ruby/object:Gem::Version
152
- version: 2.1.2
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: yard
155
141
  requirement: !ruby/object:Gem::Requirement
@@ -192,20 +178,6 @@ dependencies:
192
178
  - - ">="
193
179
  - !ruby/object:Gem::Version
194
180
  version: '0'
195
- - !ruby/object:Gem::Dependency
196
- name: ruby-prof
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
181
  - !ruby/object:Gem::Dependency
210
182
  name: sqlite3
211
183
  requirement: !ruby/object:Gem::Requirement
@@ -290,6 +262,20 @@ dependencies:
290
262
  - - "~>"
291
263
  - !ruby/object:Gem::Version
292
264
  version: 0.4.9.2
265
+ - !ruby/object:Gem::Dependency
266
+ name: warning
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '1'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '1'
293
279
  description: |
294
280
  ddtrace is Datadog’s tracing client for Ruby. It is used to trace requests
295
281
  as they flow across web servers, databases and microservices so that developers
@@ -309,6 +295,7 @@ files:
309
295
  - ".circleci/images/primary/Dockerfile-2.5.6"
310
296
  - ".circleci/images/primary/Dockerfile-2.6.4"
311
297
  - ".circleci/images/primary/Dockerfile-2.7.0"
298
+ - ".circleci/images/primary/Dockerfile-jruby-9.2"
312
299
  - ".dockerignore"
313
300
  - ".env"
314
301
  - ".github/CODEOWNERS"
@@ -339,8 +326,10 @@ files:
339
326
  - lib/ddtrace/augmentation/method_wrapping.rb
340
327
  - lib/ddtrace/augmentation/shim.rb
341
328
  - lib/ddtrace/buffer.rb
329
+ - lib/ddtrace/chunker.rb
342
330
  - lib/ddtrace/configuration.rb
343
331
  - lib/ddtrace/configuration/base.rb
332
+ - lib/ddtrace/configuration/components.rb
344
333
  - lib/ddtrace/configuration/dependency_resolver.rb
345
334
  - lib/ddtrace/configuration/option.rb
346
335
  - lib/ddtrace/configuration/option_definition.rb
@@ -700,6 +689,8 @@ files:
700
689
  - lib/ddtrace/workers/loop.rb
701
690
  - lib/ddtrace/workers/polling.rb
702
691
  - lib/ddtrace/workers/queue.rb
692
+ - lib/ddtrace/workers/runtime_metrics.rb
693
+ - lib/ddtrace/workers/trace_writer.rb
703
694
  - lib/ddtrace/writer.rb
704
695
  - tasks/release_gem.rake
705
696
  homepage: https://github.com/DataDog/dd-trace-rb
@@ -722,8 +713,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
722
713
  - !ruby/object:Gem::Version
723
714
  version: 2.0.0
724
715
  requirements: []
725
- rubyforge_project:
726
- rubygems_version: 2.6.14
716
+ rubygems_version: 3.0.3
727
717
  signing_key:
728
718
  specification_version: 4
729
719
  summary: Datadog tracing code for your Ruby applications