ddtrace 0.12.0 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +456 -0
  3. data/.circleci/images/primary/Dockerfile-1.9.3 +69 -0
  4. data/.circleci/images/primary/Dockerfile-2.0.0 +69 -0
  5. data/.circleci/images/primary/Dockerfile-2.1.10 +69 -0
  6. data/.circleci/images/primary/Dockerfile-2.2.10 +69 -0
  7. data/.circleci/images/primary/Dockerfile-2.3.7 +73 -0
  8. data/.circleci/images/primary/Dockerfile-2.4.4 +73 -0
  9. data/.env +21 -11
  10. data/.rubocop.yml +4 -1
  11. data/Appraisals +439 -66
  12. data/CHANGELOG.md +25 -2
  13. data/Rakefile +256 -75
  14. data/ddtrace.gemspec +6 -6
  15. data/docker-compose.yml +222 -37
  16. data/docs/GettingStarted.md +13 -1
  17. data/gemfiles/contrib_old.gemfile +1 -0
  18. data/gemfiles/rails30_postgres.gemfile +1 -0
  19. data/gemfiles/rails30_postgres_sidekiq.gemfile +1 -0
  20. data/gemfiles/rails32_mysql2.gemfile +1 -0
  21. data/gemfiles/rails32_postgres.gemfile +1 -0
  22. data/gemfiles/rails32_postgres_redis.gemfile +1 -0
  23. data/gemfiles/rails32_postgres_sidekiq.gemfile +1 -0
  24. data/gemfiles/rails5_mysql2.gemfile +1 -1
  25. data/gemfiles/rails5_postgres.gemfile +1 -1
  26. data/gemfiles/rails5_postgres_redis.gemfile +1 -1
  27. data/gemfiles/rails5_postgres_sidekiq.gemfile +1 -1
  28. data/lib/ddtrace/configuration.rb +2 -2
  29. data/lib/ddtrace/contrib/active_record/patcher.rb +10 -10
  30. data/lib/ddtrace/contrib/aws/instrumentation.rb +2 -2
  31. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +2 -2
  32. data/lib/ddtrace/contrib/http/patcher.rb +18 -16
  33. data/lib/ddtrace/contrib/rails/action_controller_patch.rb +77 -0
  34. data/lib/ddtrace/contrib/rails/action_view.rb +0 -65
  35. data/lib/ddtrace/contrib/rails/active_support.rb +9 -8
  36. data/lib/ddtrace/contrib/rails/core_extensions.rb +74 -115
  37. data/lib/ddtrace/tracer.rb +4 -1
  38. data/lib/ddtrace/utils.rb +10 -2
  39. data/lib/ddtrace/version.rb +1 -1
  40. metadata +11 -4
  41. data/circle.yml +0 -69
@@ -6,6 +6,11 @@ module Datadog
6
6
  module RailsRendererPatcher
7
7
  include Datadog::Patcher
8
8
 
9
+ SPAN_NAME_RENDER_PARTIAL = 'rails.render_partial'.freeze
10
+ SPAN_NAME_RENDER_TEMPLATE = 'rails.render_template'.freeze
11
+ TAG_LAYOUT = 'rails.layout'.freeze
12
+ TAG_TEMPLATE_NAME = 'rails.template_name'.freeze
13
+
9
14
  module_function
10
15
 
11
16
  def patch_renderer
@@ -24,25 +29,22 @@ module Datadog
24
29
  end
25
30
 
26
31
  def patch_template_renderer(klass)
32
+ # rubocop:disable Metrics/BlockLength
27
33
  do_once(:patch_template_renderer) do
28
34
  klass.class_eval do
29
35
  def render_with_datadog(*args, &block)
30
- # create a tracing context and start the rendering span
31
- # NOTE: Rails < 3.1 compatibility: preserve the tracing
32
- # context when a partial is rendered
33
- @tracing_context ||= {}
34
- if @tracing_context.empty?
35
- Datadog::Contrib::Rails::ActionView.start_render_template(tracing_context: @tracing_context)
36
+ # NOTE: This check exists purely for Rails 3.0 compatibility.
37
+ # The 'if' part can be removed when support for Rails 3.0 is removed.
38
+ if active_datadog_span
39
+ render_without_datadog(*args, &block)
40
+ else
41
+ datadog_tracer.trace(
42
+ Datadog::RailsRendererPatcher::SPAN_NAME_RENDER_TEMPLATE,
43
+ span_type: Datadog::Ext::HTTP::TEMPLATE
44
+ ) do |span|
45
+ with_datadog_span(span) { render_without_datadog(*args, &block) }
46
+ end
36
47
  end
37
-
38
- render_without_datadog(*args, &block)
39
- rescue Exception => e
40
- # attach the exception to the tracing context if any
41
- @tracing_context[:exception] = e
42
- raise e
43
- ensure
44
- # ensure that the template `Span` is finished even during exceptions
45
- Datadog::Contrib::Rails::ActionView.finish_render_template(tracing_context: @tracing_context)
46
48
  end
47
49
 
48
50
  def render_template_with_datadog(*args)
@@ -60,8 +62,19 @@ module Datadog
60
62
  else
61
63
  layout_name.try(:[], 'virtual_path')
62
64
  end
63
- @tracing_context[:template_name] = template_name
64
- @tracing_context[:layout] = layout
65
+ if template_name
66
+ active_datadog_span.set_tag(
67
+ Datadog::RailsRendererPatcher::TAG_TEMPLATE_NAME,
68
+ template_name
69
+ )
70
+ end
71
+
72
+ if layout
73
+ active_datadog_span.set_tag(
74
+ Datadog::RailsRendererPatcher::TAG_LAYOUT,
75
+ layout
76
+ )
77
+ end
65
78
  rescue StandardError => e
66
79
  Datadog::Tracer.log.debug(e.message)
67
80
  end
@@ -70,6 +83,21 @@ module Datadog
70
83
  render_template_without_datadog(*args)
71
84
  end
72
85
 
86
+ private
87
+
88
+ attr_accessor :active_datadog_span
89
+
90
+ def datadog_tracer
91
+ Datadog.configuration[:rails][:tracer]
92
+ end
93
+
94
+ def with_datadog_span(span)
95
+ self.active_datadog_span = span
96
+ yield
97
+ ensure
98
+ self.active_datadog_span = nil
99
+ end
100
+
73
101
  # method aliasing to patch the class
74
102
  alias_method :render_without_datadog, :render
75
103
  alias_method :render, :render_with_datadog
@@ -90,30 +118,23 @@ module Datadog
90
118
  do_once(:patch_partial_renderer) do
91
119
  klass.class_eval do
92
120
  def render_with_datadog(*args, &block)
93
- # Create a tracing context and start the rendering span
94
- tracing_context = {}
95
- Datadog::Contrib::Rails::ActionView.start_render_partial(tracing_context: tracing_context)
96
- tracing_contexts[current_span_id] = tracing_context
97
-
98
- render_without_datadog(*args)
99
- rescue Exception => e
100
- # attach the exception to the tracing context if any
101
- tracing_contexts[current_span_id][:exception] = e
102
- raise e
103
- ensure
104
- # Ensure that the template `Span` is finished even during exceptions
105
- # Remove the existing tracing context (to avoid leaks)
106
- tracing_contexts.delete(current_span_id)
107
-
108
- # Then finish the span associated with the context
109
- Datadog::Contrib::Rails::ActionView.finish_render_partial(tracing_context: tracing_context)
121
+ datadog_tracer.trace(
122
+ Datadog::RailsRendererPatcher::SPAN_NAME_RENDER_PARTIAL,
123
+ span_type: Datadog::Ext::HTTP::TEMPLATE
124
+ ) do |span|
125
+ with_datadog_span(span) { render_without_datadog(*args) }
126
+ end
110
127
  end
111
128
 
112
129
  def render_partial_with_datadog(*args)
113
130
  begin
114
- # update the tracing context with computed values before the rendering
115
131
  template_name = Datadog::Contrib::Rails::Utils.normalize_template_name(@template.try('identifier'))
116
- tracing_contexts[current_span_id][:template_name] = template_name
132
+ if template_name
133
+ active_datadog_span.set_tag(
134
+ Datadog::RailsRendererPatcher::TAG_TEMPLATE_NAME,
135
+ template_name
136
+ )
137
+ end
117
138
  rescue StandardError => e
118
139
  Datadog::Tracer.log.debug(e.message)
119
140
  end
@@ -122,15 +143,19 @@ module Datadog
122
143
  render_partial_without_datadog(*args)
123
144
  end
124
145
 
125
- # Table of tracing contexts, one per partial/span, keyed by span_id
126
- # because there will be multiple concurrent contexts, depending on how
127
- # many partials are nested within one another.
128
- def tracing_contexts
129
- @tracing_contexts ||= {}
146
+ private
147
+
148
+ attr_accessor :active_datadog_span
149
+
150
+ def datadog_tracer
151
+ Datadog.configuration[:rails][:tracer]
130
152
  end
131
153
 
132
- def current_span_id
133
- Datadog.configuration[:rails][:tracer].call_context.current_span.span_id
154
+ def with_datadog_span(span)
155
+ self.active_datadog_span = span
156
+ yield
157
+ ensure
158
+ self.active_datadog_span = nil
134
159
  end
135
160
 
136
161
  # method aliasing to patch the class
@@ -157,79 +182,9 @@ module Datadog
157
182
 
158
183
  def patch_process_action
159
184
  do_once(:patch_process_action) do
160
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
161
- # Patch Rails controller base class
162
- ::ActionController::Metal.send(:prepend, ActionControllerPatch)
163
- else
164
- # Rewrite module that gets composed into the Rails controller base class
165
- ::ActionController::Instrumentation.class_eval do
166
- def process_action_with_datadog(*args)
167
- # mutable payload with a tracing context that is used in two different
168
- # signals; it propagates the request span so that it can be finished
169
- # no matter what
170
- payload = {
171
- controller: self.class,
172
- action: action_name,
173
- headers: {
174
- # The exception this controller was given in the request,
175
- # which is typical if the controller is configured to handle exceptions.
176
- request_exception: request.headers['action_dispatch.exception']
177
- },
178
- tracing_context: {}
179
- }
180
-
181
- begin
182
- # process and catch request exceptions
183
- Datadog::Contrib::Rails::ActionController.start_processing(payload)
184
- result = process_action_without_datadog(*args)
185
- payload[:status] = response.status
186
- result
187
- rescue Exception => e
188
- payload[:exception] = [e.class.name, e.message]
189
- payload[:exception_object] = e
190
- raise e
191
- end
192
- ensure
193
- Datadog::Contrib::Rails::ActionController.finish_processing(payload)
194
- end
185
+ require 'ddtrace/contrib/rails/action_controller_patch'
195
186
 
196
- alias_method :process_action_without_datadog, :process_action
197
- alias_method :process_action, :process_action_with_datadog
198
- end
199
- end
200
- end
201
- end
202
-
203
- # ActionController patch for Ruby 2.0+
204
- module ActionControllerPatch
205
- def process_action(*args)
206
- # mutable payload with a tracing context that is used in two different
207
- # signals; it propagates the request span so that it can be finished
208
- # no matter what
209
- payload = {
210
- controller: self.class,
211
- action: action_name,
212
- headers: {
213
- # The exception this controller was given in the request,
214
- # which is typical if the controller is configured to handle exceptions.
215
- request_exception: request.headers['action_dispatch.exception']
216
- },
217
- tracing_context: {}
218
- }
219
-
220
- begin
221
- # process and catch request exceptions
222
- Datadog::Contrib::Rails::ActionController.start_processing(payload)
223
- result = super(*args)
224
- payload[:status] = response.status
225
- result
226
- rescue Exception => e
227
- payload[:exception] = [e.class.name, e.message]
228
- payload[:exception_object] = e
229
- raise e
230
- end
231
- ensure
232
- Datadog::Contrib::Rails::ActionController.finish_processing(payload)
187
+ ::ActionController::Metal.send(:include, Datadog::Contrib::Rails::ActionControllerPatch)
233
188
  end
234
189
  end
235
190
  end
@@ -270,6 +225,7 @@ module Datadog
270
225
  do_once(:patch_cache_store_read) do
271
226
  cache_store_class(:read).class_eval do
272
227
  alias_method :read_without_datadog, :read
228
+
273
229
  def read(*args, &block)
274
230
  payload = {
275
231
  action: 'GET',
@@ -297,6 +253,7 @@ module Datadog
297
253
  do_once(:patch_cache_store_fetch) do
298
254
  cache_store_class(:fetch).class_eval do
299
255
  alias_method :fetch_without_datadog, :fetch
256
+
300
257
  def fetch(*args, &block)
301
258
  payload = {
302
259
  action: 'GET',
@@ -324,6 +281,7 @@ module Datadog
324
281
  do_once(:patch_cache_store_write) do
325
282
  cache_store_class(:write).class_eval do
326
283
  alias_method :write_without_datadog, :write
284
+
327
285
  def write(*args, &block)
328
286
  payload = {
329
287
  action: 'SET',
@@ -351,6 +309,7 @@ module Datadog
351
309
  do_once(:patch_cache_store_delete) do
352
310
  cache_store_class(:delete).class_eval do
353
311
  alias_method :delete_without_datadog, :delete
312
+
354
313
  def delete(*args, &block)
355
314
  payload = {
356
315
  action: 'DELETE',
@@ -23,6 +23,8 @@ module Datadog
23
23
  attr_accessor :enabled, :writer
24
24
  attr_writer :default_service
25
25
 
26
+ ALLOWED_SPAN_OPTIONS = [:service, :resource, :span_type].freeze
27
+
26
28
  # Global, memoized, lazy initialized instance of a logger that is used within the the Datadog
27
29
  # namespace. This logger outputs to +STDOUT+ by default, and is considered thread-safe.
28
30
  def self.log
@@ -204,12 +206,13 @@ module Datadog
204
206
  # * +tags+: extra tags which should be added to the span.
205
207
  def start_span(name, options = {})
206
208
  start_time = options.fetch(:start_time, Time.now.utc)
209
+
207
210
  tags = options.fetch(:tags, {})
208
211
 
209
212
  opts = options.select do |k, _v|
210
213
  # Filter options, we want no side effects with unexpected args.
211
214
  # Plus, this documents the code (Ruby 2 named args would be better but we're Ruby 1.9 compatible)
212
- [:service, :resource, :span_type].include?(k)
215
+ ALLOWED_SPAN_OPTIONS.include?(k)
213
216
  end
214
217
 
215
218
  ctx, parent = guess_context_and_parent(options[:child_of])
data/lib/ddtrace/utils.rb CHANGED
@@ -26,12 +26,20 @@ module Datadog
26
26
 
27
27
  reset!
28
28
 
29
- def self.truncate(value, size, omission = '...')
29
+ def self.truncate(value, size, omission = '...'.freeze)
30
30
  string = value.to_s
31
31
 
32
32
  return string if string.size <= size
33
33
 
34
- string.slice(0, size - omission.size) + omission
34
+ string = string.slice(0, size - 1)
35
+
36
+ if size < omission.size
37
+ string[0, size] = omission
38
+ else
39
+ string[size - omission.size, size] = omission
40
+ end
41
+
42
+ string
35
43
  end
36
44
 
37
45
  def self.utf8_encode(str, options = {})
@@ -2,7 +2,7 @@ module Datadog
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 12
5
- PATCH = 0
5
+ PATCH = 1
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
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.12.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-08 00:00:00.000000000 Z
11
+ date: 2018-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -216,6 +216,13 @@ executables: []
216
216
  extensions: []
217
217
  extra_rdoc_files: []
218
218
  files:
219
+ - ".circleci/config.yml"
220
+ - ".circleci/images/primary/Dockerfile-1.9.3"
221
+ - ".circleci/images/primary/Dockerfile-2.0.0"
222
+ - ".circleci/images/primary/Dockerfile-2.1.10"
223
+ - ".circleci/images/primary/Dockerfile-2.2.10"
224
+ - ".circleci/images/primary/Dockerfile-2.3.7"
225
+ - ".circleci/images/primary/Dockerfile-2.4.4"
219
226
  - ".env"
220
227
  - ".gitignore"
221
228
  - ".rspec"
@@ -227,7 +234,6 @@ files:
227
234
  - LICENSE
228
235
  - README.md
229
236
  - Rakefile
230
- - circle.yml
231
237
  - ddtrace.gemspec
232
238
  - docker-compose.yml
233
239
  - docs/GettingStarted.md
@@ -283,6 +289,7 @@ files:
283
289
  - lib/ddtrace/contrib/rack/middlewares.rb
284
290
  - lib/ddtrace/contrib/rack/patcher.rb
285
291
  - lib/ddtrace/contrib/rails/action_controller.rb
292
+ - lib/ddtrace/contrib/rails/action_controller_patch.rb
286
293
  - lib/ddtrace/contrib/rails/action_view.rb
287
294
  - lib/ddtrace/contrib/rails/active_support.rb
288
295
  - lib/ddtrace/contrib/rails/core_extensions.rb
@@ -357,7 +364,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
357
364
  version: '0'
358
365
  requirements: []
359
366
  rubyforge_project:
360
- rubygems_version: 2.6.14
367
+ rubygems_version: 2.5.1
361
368
  signing_key:
362
369
  specification_version: 4
363
370
  summary: Datadog tracing code for your Ruby applications
data/circle.yml DELETED
@@ -1,69 +0,0 @@
1
- machine:
2
- services:
3
- - docker
4
- ruby:
5
- version:
6
- 2.2.7
7
- environment:
8
- LAST_STABLE: 2.4.1
9
- EARLY_STABLE: 2.2.7
10
- MRI_VERSIONS: 2.4.1,2.3.4,2.2.7
11
- MRI_OLD_VERSIONS: 2.1.10,2.0.0,1.9.3
12
- SIDEKIQ_OLD_VERSIONS: 2.1.10,2.0.0
13
- RAILS3_VERSIONS: 2.3.4,2.2.7,2.1.10,2.0.0,1.9.3
14
- RAILS4_VERSIONS: 2.3.4,2.2.7,2.1.10
15
- RAILS5_VERSIONS: 2.3.4,2.2.7
16
- RAILS3_SIDEKIQ_VERSIONS: 2.1.10,2.0.0
17
- RAILS4_SIDEKIQ_VERSIONS: 2.3.4,2.2.7
18
- JRUBY_VERSIONS: jruby-9.1.13.0
19
- AGENT_BUILD_PATH: "/home/ubuntu/agent"
20
- TEST_DATADOG_INTEGRATION: 1
21
-
22
- dependencies:
23
- cache_directories:
24
- # Cache Ruby binaries and gems
25
- - "/opt/circleci/.rvm/"
26
- - ~/rubies_cache
27
- pre:
28
- - mkdir -p ~/rubies_cache
29
- - rsync -a -v --ignore-existing ~/rubies_cache/ /opt/circleci/.rvm/rubies
30
- # we should use an old docker-compose because CircleCI supports
31
- # only docker-engine==1.9
32
- - pip install docker-compose==1.7.1
33
- - docker-compose up -d | cat
34
- # installing dev dependencies
35
- - |
36
- for version in $(echo "$MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS" | tr "," "\n"); do
37
- $(rvm list | grep -q $version) || rvm install $version --rubygems 2.6.11
38
- done
39
- - gem install bundler
40
- # remove line below once `msgpack` have a consistent version for jruby
41
- - bundle inject msgpack 1.1.0 && sed -i "y/\"/'/" Gemfile
42
- - bundle install
43
- override:
44
- - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do gem install bundler
45
- - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do bundle install
46
- # [FIXME] appraisal does not work with jruby (problem with native ext, eg sqlite3)
47
- - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS --verbose do bundle exec appraisal install || echo FIX-ME: Ignoring non-zero exit status
48
- post:
49
- - rsync -a -v --ignore-existing /opt/circleci/.rvm/rubies/ ~/rubies_cache
50
-
51
- test:
52
- override:
53
- - rvm $EARLY_STABLE --verbose do bundle exec rake rubocop
54
- # TODO: integration tests should run with the master branch of the agent
55
- - bundle exec rake ci:
56
- parallel: true
57
-
58
- deployment:
59
- develop:
60
- branch: /(master)|(develop)/
61
- # CircleCI is configured to provide VERSION_SUFFIX=$CIRCLE_BUILD_NUM
62
- commands:
63
- - S3_DIR=trace-dev bundle exec rake release:docs
64
- - S3_DIR=trace-dev bundle exec rake release:gem
65
- - cp -r ./rubygems/* $CIRCLE_ARTIFACTS
66
- public:
67
- tag: /v[0-9]+(\.[0-9]+)*/
68
- commands:
69
- - S3_DIR=trace bundle exec rake release:docs