ddtrace 0.12.0 → 0.12.1

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 (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
@@ -221,6 +221,16 @@ def finish(name, id, payload)
221
221
  end
222
222
  end
223
223
  ```
224
+ #####Enriching traces from nested methods
225
+
226
+ You can tag additional information to current active span from any method. Note however that if the method is called and there is no span currently active `active_span` will be nil.
227
+
228
+ ```ruby
229
+ # e.g. adding tag to active span
230
+
231
+ current_span = Datadog.tracer.active_span
232
+ current_span.set_tag('my_tag', 'my_value') unless current_span.nil?
233
+ ```
224
234
 
225
235
  ## Integration instrumentation
226
236
 
@@ -514,8 +524,10 @@ Where `options` is an optional `Hash` that accepts the following parameters:
514
524
 
515
525
  | Key | Description | Default |
516
526
  | --- | --- | --- |
517
- | ``service_name`` | Service name used for `http` instrumentation | http |
527
+ | ``service_name`` | Service name used for `http` instrumentation | net/http |
518
528
  | ``distributed_tracing`` | Enables distributed tracing | ``false`` |
529
+ | ``tracer`` | A ``Datadog::Tracer`` instance used to instrument the application. Usually you don't need to set that. | ``Datadog.tracer`` |
530
+
519
531
 
520
532
  If you wish to configure each connection object individually, you may use the ``Datadog.configure`` as it follows:
521
533
 
@@ -9,6 +9,7 @@ gem "redis", "< 4.0"
9
9
  gem "hiredis"
10
10
  gem "rack", "1.4.7"
11
11
  gem "rack-test", "0.7.0"
12
+ gem "rack-cache", "1.7.1"
12
13
  gem "sinatra", "1.4.5"
13
14
  gem "sqlite3"
14
15
  gem "activerecord", "3.2.22.5"
@@ -7,5 +7,6 @@ gem "test-unit"
7
7
  gem "rails", "3.0.20"
8
8
  gem "pg", "0.15.1", platform: :ruby
9
9
  gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
10
+ gem "rack-cache", "1.7.1"
10
11
 
11
12
  gemspec path: "../"
@@ -8,5 +8,6 @@ gem "rails", "3.0.20"
8
8
  gem "pg", "0.15.1", platform: :ruby
9
9
  gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
10
10
  gem "sidekiq", "4.0.0"
11
+ gem "rack-cache", "1.7.1"
11
12
 
12
13
  gemspec path: "../"
@@ -8,5 +8,6 @@ gem "rails", "3.2.22.5"
8
8
  gem "mysql2", "0.3.21", platform: :ruby
9
9
  gem "activerecord-mysql-adapter", platform: :ruby
10
10
  gem "activerecord-jdbcmysql-adapter", platform: :jruby
11
+ gem "rack-cache", "1.7.1"
11
12
 
12
13
  gemspec path: "../"
@@ -7,5 +7,6 @@ gem "test-unit"
7
7
  gem "rails", "3.2.22.5"
8
8
  gem "pg", "0.15.1", platform: :ruby
9
9
  gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
10
+ gem "rack-cache", "1.7.1"
10
11
 
11
12
  gemspec path: "../"
@@ -9,5 +9,6 @@ gem "pg", "0.15.1", platform: :ruby
9
9
  gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
10
10
  gem "redis-rails"
11
11
  gem "redis", "< 4.0"
12
+ gem "rack-cache", "1.7.1"
12
13
 
13
14
  gemspec path: "../"
@@ -8,5 +8,6 @@ gem "rails", "3.2.22.5"
8
8
  gem "pg", "0.15.1", platform: :ruby
9
9
  gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
10
10
  gem "sidekiq", "4.0.0"
11
+ gem "rack-cache", "1.7.1"
11
12
 
12
13
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.1.5"
6
+ gem "rails", "~> 5.1.6"
7
7
  gem "mysql2", "< 0.5", platform: :ruby
8
8
 
9
9
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.1.5"
6
+ gem "rails", "~> 5.1.6"
7
7
  gem "pg", "< 1.0", platform: :ruby
8
8
 
9
9
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.1.5"
6
+ gem "rails", "~> 5.1.6"
7
7
  gem "pg", "< 1.0", platform: :ruby
8
8
  gem "redis-rails"
9
9
  gem "redis"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.1.5"
6
+ gem "rails", "~> 5.1.6"
7
7
  gem "pg", "< 1.0", platform: :ruby
8
8
  gem "sidekiq"
9
9
  gem "activejob"
@@ -9,11 +9,11 @@ module Datadog
9
9
 
10
10
  def initialize(options = {})
11
11
  @registry = options.fetch(:registry, Datadog.registry)
12
+ @wrapped_registry = {}
12
13
  end
13
14
 
14
15
  def [](integration_name)
15
- integration = fetch_integration(integration_name)
16
- Proxy.new(integration)
16
+ @wrapped_registry[integration_name] ||= Proxy.new(fetch_integration(integration_name))
17
17
  end
18
18
 
19
19
  def use(integration_name, options = {})
@@ -89,13 +89,13 @@ module Datadog
89
89
  # Find out if the SQL query has been cached in this request. This meta is really
90
90
  # helpful to users because some spans may have 0ns of duration because the query
91
91
  # is simply cached from memory, so the notification is fired with start == finish.
92
- cached = payload[:cached] || (payload[:name] == 'CACHE')
92
+ cached = payload[:cached] || (payload[:name] == 'CACHE'.freeze)
93
93
 
94
- span.set_tag('active_record.db.vendor', connection_config[:adapter_name])
95
- span.set_tag('active_record.db.name', connection_config[:database_name])
96
- span.set_tag('active_record.db.cached', cached) if cached
97
- span.set_tag('out.host', connection_config[:adapter_host])
98
- span.set_tag('out.port', connection_config[:adapter_port])
94
+ span.set_tag('active_record.db.vendor'.freeze, connection_config[:adapter_name])
95
+ span.set_tag('active_record.db.name'.freeze, connection_config[:database_name])
96
+ span.set_tag('active_record.db.cached'.freeze, cached) if cached
97
+ span.set_tag('out.host'.freeze, connection_config[:adapter_host])
98
+ span.set_tag('out.port'.freeze, connection_config[:adapter_port])
99
99
  rescue StandardError => e
100
100
  Datadog::Tracer.log.debug(e.message)
101
101
  end
@@ -107,13 +107,13 @@ module Datadog
107
107
  elsif span.parent
108
108
  span.parent.service
109
109
  else
110
- 'active_record'
110
+ 'active_record'.freeze
111
111
  end
112
112
 
113
113
  span.resource = payload.fetch(:class_name)
114
- span.span_type = 'custom'
115
- span.set_tag('active_record.instantiation.class_name', payload.fetch(:class_name))
116
- span.set_tag('active_record.instantiation.record_count', payload.fetch(:record_count))
114
+ span.span_type = 'custom'.freeze
115
+ span.set_tag('active_record.instantiation.class_name'.freeze, payload.fetch(:class_name))
116
+ span.set_tag('active_record.instantiation.record_count'.freeze, payload.fetch(:record_count))
117
117
  rescue StandardError => e
118
118
  Datadog::Tracer.log.debug(e.message)
119
119
  end
@@ -27,8 +27,8 @@ module Datadog
27
27
  def annotate!(span, pin, context)
28
28
  span.service = pin.service
29
29
  span.span_type = pin.app_type
30
- span.name = context.safely(:resource)
31
- span.resource = RESOURCE
30
+ span.name = RESOURCE
31
+ span.resource = context.safely(:resource)
32
32
  span.set_tag('aws.agent', AGENT)
33
33
  span.set_tag('aws.operation', context.safely(:operation))
34
34
  span.set_tag('aws.region', context.safely(:region))
@@ -52,11 +52,11 @@ module Datadog
52
52
  remove_method :initialize
53
53
  end
54
54
 
55
- def initialize(*args)
55
+ def initialize(*args, &block)
56
56
  service = Datadog.configuration[:elasticsearch][:service_name]
57
57
  pin = Datadog::Pin.new(service, app: 'elasticsearch', app_type: Datadog::Ext::AppTypes::DB)
58
58
  pin.onto(self)
59
- initialize_without_datadog(*args)
59
+ initialize_without_datadog(*args, &block)
60
60
  end
61
61
 
62
62
  alias_method :perform_request_without_datadog, :perform_request
@@ -48,6 +48,8 @@ module Datadog
48
48
  include Base
49
49
  register_as :http, auto_patch: true
50
50
  option :distributed_tracing, default: false
51
+ option :service_name, default: SERVICE
52
+ option :tracer, default: Datadog.tracer
51
53
 
52
54
  @patched = false
53
55
 
@@ -64,7 +66,7 @@ module Datadog
64
66
  require 'ddtrace/ext/net'
65
67
  require 'ddtrace/ext/distributed'
66
68
 
67
- patch_http()
69
+ patch_http
68
70
 
69
71
  @patched = true
70
72
  rescue StandardError => e
@@ -74,7 +76,7 @@ module Datadog
74
76
  @patched
75
77
  end
76
78
 
77
- # patched? tells wether patch has been successfully applied
79
+ # patched? tells whether patch has been successfully applied
78
80
  def patched?
79
81
  @patched
80
82
  end
@@ -84,27 +86,27 @@ module Datadog
84
86
  # rubocop:disable Metrics/AbcSize
85
87
  def patch_http
86
88
  ::Net::HTTP.class_eval do
87
- alias_method :initialize_without_datadog, :initialize
88
- Datadog::Patcher.without_warnings do
89
- remove_method :initialize
90
- end
91
-
92
- def initialize(*args)
93
- pin = Datadog::Pin.new(SERVICE, app: APP, app_type: Datadog::Ext::AppTypes::WEB)
94
- pin.onto(self)
95
- initialize_without_datadog(*args)
96
- end
97
-
98
89
  alias_method :request_without_datadog, :request
99
90
  remove_method :request
100
91
 
92
+ def datadog_pin
93
+ @datadog_pindatadog_pin ||= begin
94
+ service = Datadog.configuration[:http][:service_name]
95
+ tracer = Datadog.configuration[:http][:tracer]
96
+
97
+ Datadog::Pin.new(service, app: APP, app_type: Datadog::Ext::AppTypes::WEB, tracer: tracer)
98
+ end
99
+ end
100
+
101
101
  def request(req, body = nil, &block) # :yield: +response+
102
- pin = Datadog::Pin.get_from(self)
102
+ pin = datadog_pin
103
103
  return request_without_datadog(req, body, &block) unless pin && pin.tracer
104
104
 
105
105
  transport = pin.tracer.writer.transport
106
- return request_without_datadog(req, body, &block) if
107
- Datadog::Contrib::HTTP.should_skip_tracing?(req, @address, @port, transport, pin)
106
+
107
+ if Datadog::Contrib::HTTP.should_skip_tracing?(req, @address, @port, transport, pin)
108
+ return request_without_datadog(req, body, &block)
109
+ end
108
110
 
109
111
  pin.tracer.trace(NAME) do |span|
110
112
  begin
@@ -0,0 +1,77 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Rails
4
+ # Instrument ActiveController processing
5
+ module ActionControllerPatch
6
+ def self.included(base)
7
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
8
+ base.send(:prepend, ProcessActionPatch)
9
+ else
10
+ base.class_eval do
11
+ alias_method :process_action_without_datadog, :process_action
12
+
13
+ include ProcessActionPatch
14
+ end
15
+ end
16
+ end
17
+
18
+ # Compatibility module for Ruby versions not supporting #prepend
19
+ module ProcessActionCompatibilityPatch
20
+ def process_action(*args)
21
+ process_action_without_datadog(*args)
22
+ end
23
+ end
24
+
25
+ # ActionController patch
26
+ module ProcessActionPatch
27
+ # compatibility module for Ruby versions not supporting #prepend
28
+ include ProcessActionCompatibilityPatch unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
29
+
30
+ def process_action(*args)
31
+ # mutable payload with a tracing context that is used in two different
32
+ # signals; it propagates the request span so that it can be finished
33
+ # no matter what
34
+ payload = {
35
+ controller: self.class,
36
+ action: action_name,
37
+ headers: {
38
+ # The exception this controller was given in the request,
39
+ # which is typical if the controller is configured to handle exceptions.
40
+ request_exception: request.headers['action_dispatch.exception']
41
+ },
42
+ tracing_context: {}
43
+ }
44
+
45
+ begin
46
+ # process and catch request exceptions
47
+ Datadog::Contrib::Rails::ActionController.start_processing(payload)
48
+ result = super(*args)
49
+ status = datadog_response_status
50
+ payload[:status] = status unless status.nil?
51
+ result
52
+ # rubocop:disable Lint/RescueException
53
+ rescue Exception => e
54
+ payload[:exception] = [e.class.name, e.message]
55
+ payload[:exception_object] = e
56
+ raise e
57
+ end
58
+ # rubocop:enable Lint/RescueException
59
+ ensure
60
+ Datadog::Contrib::Rails::ActionController.finish_processing(payload)
61
+ end
62
+
63
+ def datadog_response_status
64
+ case response
65
+ when ActionDispatch::Response
66
+ response.status
67
+ when Array
68
+ # Likely a Rack response array: first element is the status.
69
+ status = response.first
70
+ status.class <= Integer ? status : nil
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -13,71 +13,6 @@ module Datadog
13
13
  Datadog::RailsRendererPatcher.patch_renderer
14
14
  end
15
15
  end
16
-
17
- def self.start_render_template(payload)
18
- # retrieve the tracing context
19
- tracing_context = payload.fetch(:tracing_context)
20
-
21
- # create a new Span and add it to the tracing context
22
- tracer = Datadog.configuration[:rails][:tracer]
23
- span = tracer.trace('rails.render_template', span_type: Datadog::Ext::HTTP::TEMPLATE)
24
- tracing_context[:dd_rails_template_span] = span
25
- rescue StandardError => e
26
- Datadog::Tracer.log.debug(e.message)
27
- end
28
-
29
- def self.finish_render_template(payload)
30
- # retrieve the tracing context and the latest active span
31
- tracing_context = payload.fetch(:tracing_context)
32
- span = tracing_context[:dd_rails_template_span]
33
- return if !span || span.finished?
34
-
35
- # finish the tracing and update the execution time
36
- begin
37
- template_name = tracing_context[:template_name]
38
- layout = tracing_context[:layout]
39
- exception = tracing_context[:exception]
40
-
41
- span.set_tag('rails.template_name', template_name) if template_name
42
- span.set_tag('rails.layout', layout) if layout
43
- span.set_error(exception) if exception
44
- ensure
45
- span.finish()
46
- end
47
- rescue StandardError => e
48
- Datadog::Tracer.log.debug(e.message)
49
- end
50
-
51
- def self.start_render_partial(payload)
52
- # retrieve the tracing context
53
- tracing_context = payload.fetch(:tracing_context)
54
-
55
- tracer = Datadog.configuration[:rails][:tracer]
56
- span = tracer.trace('rails.render_partial', span_type: Datadog::Ext::HTTP::TEMPLATE)
57
- tracing_context[:dd_rails_partial_span] = span
58
- rescue StandardError => e
59
- Datadog::Tracer.log.debug(e.message)
60
- end
61
-
62
- def self.finish_render_partial(payload)
63
- # retrieve the tracing context and the latest active span
64
- tracing_context = payload.fetch(:tracing_context)
65
- span = tracing_context[:dd_rails_partial_span]
66
- return if !span || span.finished?
67
-
68
- # finish the tracing and update the execution time
69
- begin
70
- template_name = tracing_context[:template_name]
71
- exception = tracing_context[:exception]
72
-
73
- span.set_tag('rails.template_name', template_name) if template_name
74
- span.set_error(exception) if exception
75
- ensure
76
- span.finish()
77
- end
78
- rescue StandardError => e
79
- Datadog::Tracer.log.debug(e.message)
80
- end
81
16
  end
82
17
  end
83
18
  end
@@ -17,7 +17,6 @@ module Datadog
17
17
 
18
18
  def self.start_trace_cache(payload)
19
19
  tracer = Datadog.configuration[:rails][:tracer]
20
- tracing_context = payload.fetch(:tracing_context)
21
20
 
22
21
  # In most of the cases Rails ``fetch()`` and ``read()`` calls are nested.
23
22
  # This check ensures that two reads are not nested since they don't provide
@@ -25,14 +24,16 @@ module Datadog
25
24
  # NOTE: the ``finish_trace_cache()`` is fired but it already has a safe-guard
26
25
  # to avoid any kind of issue.
27
26
  current_span = tracer.active_span
28
- return if current_span.try('name') == 'rails.cache' &&
29
- current_span.try('resource') == 'GET' &&
30
- payload[:action] == 'GET'
27
+ return if payload[:action] == 'GET'.freeze &&
28
+ current_span.try(:name) == 'rails.cache'.freeze &&
29
+ current_span.try(:resource) == 'GET'.freeze
30
+
31
+ tracing_context = payload.fetch(:tracing_context)
31
32
 
32
33
  # create a new ``Span`` and add it to the tracing context
33
34
  service = Datadog.configuration[:rails][:cache_service]
34
35
  type = Datadog::Ext::CACHE::TYPE
35
- span = tracer.trace('rails.cache', service: service, span_type: type)
36
+ span = tracer.trace('rails.cache'.freeze, service: service, span_type: type)
36
37
  span.resource = payload.fetch(:action)
37
38
  tracing_context[:dd_cache_span] = span
38
39
  rescue StandardError => e
@@ -48,12 +49,12 @@ module Datadog
48
49
  begin
49
50
  # discard parameters from the cache_store configuration
50
51
  store, = *Array.wrap(::Rails.configuration.cache_store).flatten
51
- span.set_tag('rails.cache.backend', store)
52
+ span.set_tag('rails.cache.backend'.freeze, store)
52
53
  cache_key = Datadog::Utils.truncate(payload.fetch(:key), Ext::CACHE::MAX_KEY_SIZE)
53
- span.set_tag('rails.cache.key', cache_key)
54
+ span.set_tag('rails.cache.key'.freeze, cache_key)
54
55
  span.set_error(payload[:exception]) if payload[:exception]
55
56
  ensure
56
- span.finish()
57
+ span.finish
57
58
  end
58
59
  rescue StandardError => e
59
60
  Datadog::Tracer.log.debug(e.message)