ddtrace 0.44.0 → 0.45.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +48 -1
  3. data/Appraisals +16 -7
  4. data/CHANGELOG.md +43 -1
  5. data/README.md +1 -0
  6. data/Rakefile +51 -2
  7. data/ddtrace.gemspec +1 -0
  8. data/docs/GettingStarted.md +65 -6
  9. data/lib/ddtrace.rb +7 -0
  10. data/lib/ddtrace/auto_instrument.rb +3 -0
  11. data/lib/ddtrace/auto_instrument_base.rb +6 -0
  12. data/lib/ddtrace/contrib/action_cable/integration.rb +7 -0
  13. data/lib/ddtrace/contrib/action_pack/integration.rb +7 -0
  14. data/lib/ddtrace/contrib/action_view/integration.rb +7 -0
  15. data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
  16. data/lib/ddtrace/contrib/active_record/utils.rb +56 -20
  17. data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
  18. data/lib/ddtrace/contrib/auto_instrument.rb +48 -0
  19. data/lib/ddtrace/contrib/cucumber/integration.rb +5 -0
  20. data/lib/ddtrace/contrib/ethon/easy_patch.rb +5 -4
  21. data/lib/ddtrace/contrib/extensions.rb +27 -1
  22. data/lib/ddtrace/contrib/httpclient/configuration/settings.rb +32 -0
  23. data/lib/ddtrace/contrib/httpclient/ext.rb +17 -0
  24. data/lib/ddtrace/contrib/httpclient/instrumentation.rb +152 -0
  25. data/lib/ddtrace/contrib/httpclient/integration.rb +43 -0
  26. data/lib/ddtrace/contrib/httpclient/patcher.rb +35 -0
  27. data/lib/ddtrace/contrib/patchable.rb +18 -7
  28. data/lib/ddtrace/contrib/rack/integration.rb +7 -0
  29. data/lib/ddtrace/contrib/rack/middlewares.rb +1 -1
  30. data/lib/ddtrace/contrib/rack/request_queue.rb +6 -1
  31. data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +10 -0
  32. data/lib/ddtrace/contrib/rails/utils.rb +4 -0
  33. data/lib/ddtrace/contrib/rake/integration.rb +1 -1
  34. data/lib/ddtrace/contrib/rspec/integration.rb +5 -0
  35. data/lib/ddtrace/ext/ci.rb +42 -9
  36. data/lib/ddtrace/ext/git.rb +0 -1
  37. data/lib/ddtrace/propagation/http_propagator.rb +17 -2
  38. data/lib/ddtrace/version.rb +1 -1
  39. metadata +29 -6
@@ -56,6 +56,7 @@ Gem::Specification.new do |spec|
56
56
  spec.add_development_dependency 'webmock', '>= 3.10.0'
57
57
  spec.add_development_dependency 'builder'
58
58
  spec.add_development_dependency 'climate_control', '~> 0.2.0'
59
+ spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4.1'
59
60
 
60
61
  # locking transitive dependency of webmock
61
62
  spec.add_development_dependency 'addressable', '~> 2.4.0'
@@ -45,6 +45,7 @@ To contribute, check out the [contribution guidelines][contribution docs] and [d
45
45
  - [GraphQL](#graphql)
46
46
  - [gRPC](#grpc)
47
47
  - [http.rb](#http-rb)
48
+ - [httpclient](#httpclient)
48
49
  - [MongoDB](#mongodb)
49
50
  - [MySQL2](#mysql2)
50
51
  - [Net/HTTP](#net-http)
@@ -144,6 +145,21 @@ Install and configure the Datadog Agent to receive traces from your now instrume
144
145
 
145
146
  ### Quickstart for Rails applications
146
147
 
148
+ #### Rails Auto Instrument all Integrations
149
+
150
+ 1. Add the `ddtrace` gem to your Gemfile:
151
+
152
+ ```ruby
153
+ source 'https://rubygems.org'
154
+ gem 'ddtrace', require: 'ddtrace/auto_instrument'
155
+ ```
156
+
157
+ 2. Install the gem with `bundle install`
158
+
159
+ 3. You can configure, override, or disable any specific integration settings by also adding a [Rails Manual Configuration](#rails-manual-configuration) file.
160
+
161
+ #### Rails Manual Configuration
162
+
147
163
  1. Add the `ddtrace` gem to your Gemfile:
148
164
 
149
165
  ```ruby
@@ -165,6 +181,25 @@ Install and configure the Datadog Agent to receive traces from your now instrume
165
181
 
166
182
  ### Quickstart for Ruby applications
167
183
 
184
+ #### Ruby Auto Instrument all Integrations
185
+
186
+ 1. Install the gem with `gem install ddtrace`
187
+ 2. Requiring any [supported libraries or frameworks](#integration-instrumentation) that should be instrumented.
188
+ 3. Add `require 'ddtrace/auto_instrument'` to your application. _Note:_ This must be done _after_ requiring any supported libraries or frameworks.
189
+
190
+ ```ruby
191
+ # Example frameworks and libraries
192
+ require 'sinatra'
193
+ require 'faraday'
194
+ require 'redis'
195
+
196
+ require 'ddtrace/auto_instrument'
197
+ ```
198
+
199
+ You can configure, override, or disable any specific integration settings by also adding a [Ruby Manual Configuration Block](#ruby-manual-configuration).
200
+
201
+ #### Ruby Manual Configuration
202
+
168
203
  1. Install the gem with `gem install ddtrace`
169
204
  2. Add a configuration block to your Ruby application:
170
205
 
@@ -362,6 +397,7 @@ For a list of available integrations, and their configuration options, please re
362
397
  | GraphQL | `graphql` | `>= 1.7.9` | `>= 1.7.9` | *[Link](#graphql)* | *[Link](https://github.com/rmosolgo/graphql-ruby)* |
363
398
  | gRPC | `grpc` | `>= 1.7` | *gem not available* | *[Link](#grpc)* | *[Link](https://github.com/grpc/grpc/tree/master/src/rubyc)* |
364
399
  | http.rb | `httprb` | `>= 2.0` | `>= 2.0` | *[Link](#http-rb)* | *[Link](https://github.com/httprb/http)* |
400
+ | httpclient | `httpclient` | `>= 2.2` | `>= 2.2` | *[Link](#httpclient)* | *[Link](https://github.com/nahi/httpclient)* |
365
401
  | Kafka | `ruby-kafka` | `>= 0.7.10` | `>= 0.7.10` | *[Link](#kafka)* | *[Link](https://github.com/zendesk/ruby-kafka)* |
366
402
  | MongoDB | `mongo` | `>= 2.1` | `>= 2.1` | *[Link](#mongodb)* | *[Link](https://github.com/mongodb/mongo-ruby-driver)* |
367
403
  | MySQL2 | `mysql2` | `>= 0.3.21` | *gem not available* | *[Link](#mysql2)* | *[Link](https://github.com/brianmario/mysql2)* |
@@ -1017,6 +1053,32 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1017
1053
  | `service_name` | Service name for `httprb` instrumentation. | `'httprb'` |
1018
1054
  | `split_by_domain` | Uses the request domain as the service name when set to `true`. | `false` |
1019
1055
 
1056
+ ### httpclient
1057
+
1058
+ The httpclient integration will trace any HTTP call using the httpclient gem.
1059
+
1060
+ ```ruby
1061
+ require 'http'
1062
+ require 'ddtrace'
1063
+ Datadog.configure do |c|
1064
+ c.use :httpclient, options
1065
+ # optionally, specify a different service name for hostnames matching a regex
1066
+ c.use :httpclient, describes: /user-[^.]+\.example\.com/ do |httpclient|
1067
+ httpclient.service_name = 'user.example.com'
1068
+ httpclient.split_by_domain = false # Only necessary if split_by_domain is true by default
1069
+ end
1070
+ end
1071
+ ```
1072
+
1073
+ Where `options` is an optional `Hash` that accepts the following parameters:
1074
+
1075
+ | Key | Description | Default |
1076
+ | --- | ----------- | ------- |
1077
+ | `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
1078
+ | `distributed_tracing` | Enables [distributed tracing](#distributed-tracing) | `true` |
1079
+ | `service_name` | Service name for `httpclient` instrumentation. | `'httpclient'` |
1080
+ | `split_by_domain` | Uses the request domain as the service name when set to `true`. | `false` |
1081
+
1020
1082
  ### Kafka
1021
1083
 
1022
1084
  The Kafka integration provides tracing of the `ruby-kafka` gem:
@@ -2025,6 +2087,7 @@ For more details on how to activate distributed tracing for integrations, see th
2025
2087
  - [Rails](#rails)
2026
2088
  - [Sinatra](#sinatra)
2027
2089
  - [http.rb](#http-rb)
2090
+ - [httpclient](#httpclient)
2028
2091
 
2029
2092
  **Using the HTTP propagator**
2030
2093
 
@@ -2053,9 +2116,7 @@ end
2053
2116
 
2054
2117
  Traces that originate from HTTP requests can be configured to include the time spent in a frontend web server or load balancer queue before the request reaches the Ruby application.
2055
2118
 
2056
- This functionality is **experimental** and deactivated by default.
2057
-
2058
- To activate this feature, you must add an `X-Request-Start` or `X-Queue-Start` header from your web server (i.e., Nginx). The following is an Nginx configuration example:
2119
+ This feature is disabled by default. To activate it, you must add an `X-Request-Start` or `X-Queue-Start` header from your web server (i.e., Nginx). The following is an Nginx configuration example:
2059
2120
 
2060
2121
  ```
2061
2122
  # /etc/nginx/conf.d/ruby_service.conf
@@ -2069,9 +2130,7 @@ server {
2069
2130
  }
2070
2131
  ```
2071
2132
 
2072
- Then you must enable the request queuing feature in the integration handling the request.
2073
-
2074
- For Rack-based applications, see the [documentation](#rack) for details for enabling this feature.
2133
+ Then you must enable the request queuing feature, by setting `request_queuing: true`, in the integration handling the request. For Rack-based applications, see the [documentation](#rack) for details.
2075
2134
 
2076
2135
  ### Processing Pipeline
2077
2136
 
@@ -17,11 +17,13 @@ require 'ddtrace/configuration'
17
17
  require 'ddtrace/patcher'
18
18
  require 'ddtrace/augmentation'
19
19
  require 'ddtrace/metrics'
20
+ require 'ddtrace/auto_instrument_base'
20
21
 
21
22
  # \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
22
23
  module Datadog
23
24
  extend Augmentation
24
25
  extend Configuration
26
+ extend AutoInstrumentBase
25
27
 
26
28
  # Load and extend Contrib by default
27
29
  require 'ddtrace/contrib/extensions'
@@ -31,6 +33,10 @@ module Datadog
31
33
  require 'ddtrace/opentelemetry/extensions'
32
34
  extend OpenTelemetry::Extensions
33
35
 
36
+ # Load and extend AutoInstrument
37
+ require 'ddtrace/contrib/auto_instrument'
38
+ extend Contrib::AutoInstrument
39
+
34
40
  # Add shutdown hook:
35
41
  # Ensures the tracer has an opportunity to flush traces
36
42
  # and cleanup before terminating the process.
@@ -56,6 +62,7 @@ require 'ddtrace/contrib/grape/integration'
56
62
  require 'ddtrace/contrib/graphql/integration'
57
63
  require 'ddtrace/contrib/grpc/integration'
58
64
  require 'ddtrace/contrib/http/integration'
65
+ require 'ddtrace/contrib/httpclient/integration'
59
66
  require 'ddtrace/contrib/httprb/integration'
60
67
  require 'ddtrace/contrib/integration'
61
68
  require 'ddtrace/contrib/kafka/integration'
@@ -0,0 +1,3 @@
1
+ require 'ddtrace'
2
+
3
+ Datadog.add_auto_instrument
@@ -0,0 +1,6 @@
1
+ module Datadog
2
+ # base methods stubbed for adding auto instrument extensions
3
+ module AutoInstrumentBase
4
+ def add_auto_instrument; end
5
+ end
6
+ end
@@ -1,6 +1,7 @@
1
1
  require 'ddtrace/contrib/integration'
2
2
  require 'ddtrace/contrib/action_cable/configuration/settings'
3
3
  require 'ddtrace/contrib/action_cable/patcher'
4
+ require 'ddtrace/contrib/rails/utils'
4
5
 
5
6
  module Datadog
6
7
  module Contrib
@@ -25,6 +26,12 @@ module Datadog
25
26
  super && version >= MINIMUM_VERSION
26
27
  end
27
28
 
29
+ # enabled by rails integration so should only auto instrument
30
+ # if detected that it is being used without rails
31
+ def auto_instrument?
32
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
33
+ end
34
+
28
35
  def default_configuration
29
36
  Configuration::Settings.new
30
37
  end
@@ -1,6 +1,7 @@
1
1
  require 'ddtrace/contrib/integration'
2
2
  require 'ddtrace/contrib/action_pack/configuration/settings'
3
3
  require 'ddtrace/contrib/action_pack/patcher'
4
+ require 'ddtrace/contrib/rails/utils'
4
5
 
5
6
  module Datadog
6
7
  module Contrib
@@ -25,6 +26,12 @@ module Datadog
25
26
  super && version >= MINIMUM_VERSION
26
27
  end
27
28
 
29
+ # enabled by rails integration so should only auto instrument
30
+ # if detected that it is being used without rails
31
+ def auto_instrument?
32
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
33
+ end
34
+
28
35
  def default_configuration
29
36
  Configuration::Settings.new
30
37
  end
@@ -1,6 +1,7 @@
1
1
  require 'ddtrace/contrib/integration'
2
2
  require 'ddtrace/contrib/action_view/configuration/settings'
3
3
  require 'ddtrace/contrib/action_view/patcher'
4
+ require 'ddtrace/contrib/rails/utils'
4
5
 
5
6
  module Datadog
6
7
  module Contrib
@@ -32,6 +33,12 @@ module Datadog
32
33
  super && version >= MINIMUM_VERSION
33
34
  end
34
35
 
36
+ # enabled by rails integration so should only auto instrument
37
+ # if detected that it is being used without rails
38
+ def auto_instrument?
39
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
40
+ end
41
+
35
42
  def default_configuration
36
43
  Configuration::Settings.new
37
44
  end
@@ -5,6 +5,7 @@ require 'ddtrace/contrib/active_record/events'
5
5
  require 'ddtrace/contrib/active_record/configuration/resolver'
6
6
  require 'ddtrace/contrib/active_record/configuration/settings'
7
7
  require 'ddtrace/contrib/active_record/patcher'
8
+ require 'ddtrace/contrib/rails/utils'
8
9
 
9
10
  module Datadog
10
11
  module Contrib
@@ -29,6 +30,12 @@ module Datadog
29
30
  super && version >= MINIMUM_VERSION
30
31
  end
31
32
 
33
+ # enabled by rails integration so should only auto instrument
34
+ # if detected that it is being used without rails
35
+ def auto_instrument?
36
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
37
+ end
38
+
32
39
  def default_configuration
33
40
  Configuration::Settings.new
34
41
  end
@@ -1,3 +1,5 @@
1
+ require 'ddtrace/ext/runtime'
2
+
1
3
  module Datadog
2
4
  module Contrib
3
5
  module ActiveRecord
@@ -21,42 +23,76 @@ module Datadog
21
23
  connection_config[:port]
22
24
  end
23
25
 
24
- # In newer Rails versions, the `payload` contains both the `connection` and its `object_id` named `connection_id`.
25
- #
26
- # So, if rails is recent we'll have a direct access to the connection.
27
- # Else, we'll find it thanks to the passed `connection_id`.
26
+ # Returns the connection configuration hash from the
27
+ # current connection
28
28
  #
29
- # See this PR for more details: https://github.com/rails/rails/pull/34602
29
+ # Since Rails 6.0, we have direct access to the object,
30
+ # while older versions of Rails only provide us the
31
+ # connection id.
30
32
  #
33
+ # @see https://github.com/rails/rails/pull/34602
31
34
  def self.connection_config(connection = nil, connection_id = nil)
32
35
  return default_connection_config if connection.nil? && connection_id.nil?
33
36
 
34
37
  conn = if !connection.nil?
38
+ # Since Rails 6.0, the connection object
39
+ # is directly available.
35
40
  connection
36
- # Rails 3.0 - 3.2
37
- elsif Gem.loaded_specs['activerecord'].version < Gem::Version.new('4.0')
38
- ::ActiveRecord::Base
39
- .connection_handler
40
- .connection_pools
41
- .values
42
- .flat_map(&:connections)
43
- .find { |c| c.object_id == connection_id }
44
- # Rails 4.2+
45
41
  else
46
- ::ActiveRecord::Base
47
- .connection_handler
48
- .connection_pool_list
49
- .flat_map(&:connections)
50
- .find { |c| c.object_id == connection_id }
42
+ # For Rails < 6.0, only the `connection_id`
43
+ # is available. We have to find the connection
44
+ # object from it.
45
+ connection_from_id(connection_id)
51
46
  end
52
47
 
53
- if conn.instance_variable_defined?(:@config)
48
+ if conn && conn.instance_variable_defined?(:@config)
54
49
  conn.instance_variable_get(:@config)
55
50
  else
56
51
  EMPTY_CONFIG
57
52
  end
58
53
  end
59
54
 
55
+ # DEV: JRuby responds to {ObjectSpace._id2ref}, despite raising an error
56
+ # DEV: when invoked. Thus, we have to explicitly check for Ruby runtime.
57
+ if Datadog::Ext::Runtime::RUBY_ENGINE != 'jruby'
58
+ # CRuby has access to {ObjectSpace._id2ref}, which allows for
59
+ # direct look up of the connection object.
60
+ def self.connection_from_id(connection_id)
61
+ # `connection_id` is the `#object_id` of the
62
+ # connection. We can perform an ObjectSpace
63
+ # lookup to find it.
64
+ #
65
+ # This works not only for ActiveRecord, but for
66
+ # extensions that might have their own connection
67
+ # pool (e.g. https://rubygems.org/gems/makara).
68
+ ObjectSpace._id2ref(connection_id)
69
+ rescue => e
70
+ # Because `connection_id` references a live connection
71
+ # present in the current stack, it is very unlikely that
72
+ # `_id2ref` will fail, but we add this safeguard just
73
+ # in case.
74
+ Datadog.logger.debug(
75
+ "connection_id #{connection_id} does not represent a valid object. " \
76
+ "Cause: #{e.message} Source: #{e.backtrace.first}"
77
+ )
78
+ end
79
+ else
80
+ # JRuby does not enable {ObjectSpace._id2ref} by default,
81
+ # as it has large performance impact:
82
+ # https://github.com/jruby/jruby/wiki/PerformanceTuning/cf155dd9#dont-enable-objectspace
83
+ #
84
+ # This fallback code does not support the makara gem,
85
+ # as its connections don't live in the ActiveRecord
86
+ # connection pool.
87
+ def self.connection_from_id(connection_id)
88
+ ::ActiveRecord::Base
89
+ .connection_handler
90
+ .connection_pool_list
91
+ .flat_map(&:connections)
92
+ .find { |c| c.object_id == connection_id }
93
+ end
94
+ end
95
+
60
96
  # @return [Hash]
61
97
  def self.default_connection_config
62
98
  return @default_connection_config if instance_variable_defined?(:@default_connection_config)
@@ -1,8 +1,8 @@
1
1
  require 'ddtrace/contrib/integration'
2
2
  require 'ddtrace/contrib/active_support/configuration/settings'
3
3
  require 'ddtrace/contrib/active_support/patcher'
4
-
5
4
  require 'ddtrace/contrib/active_support/cache/redis'
5
+ require 'ddtrace/contrib/rails/utils'
6
6
 
7
7
  module Datadog
8
8
  module Contrib
@@ -27,6 +27,12 @@ module Datadog
27
27
  super && version >= MINIMUM_VERSION
28
28
  end
29
29
 
30
+ # enabled by rails integration so should only auto instrument
31
+ # if detected that it is being used without rails
32
+ def auto_instrument?
33
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
34
+ end
35
+
30
36
  def default_configuration
31
37
  Configuration::Settings.new
32
38
  end
@@ -0,0 +1,48 @@
1
+ require 'ddtrace'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ # Extensions for auto instrumentation added to the base library
6
+ # AutoInstrumentation enables all integration
7
+ module AutoInstrument
8
+ def self.extended(base)
9
+ base.send(:extend, Patch)
10
+ end
11
+
12
+ # Patch adds method for invoking auto_instrumentation
13
+ module Patch
14
+ def add_auto_instrument
15
+ super
16
+
17
+ if Datadog::Contrib::Rails::Utils.railtie_supported?
18
+ require 'ddtrace/contrib/rails/auto_instrument_railtie'
19
+ else
20
+ AutoInstrument.patch_all
21
+ end
22
+ AutoInstrument.patch_all
23
+ end
24
+ end
25
+
26
+ def self.patch_all
27
+ integrations = []
28
+
29
+ Datadog.registry.each do |integration|
30
+ # some instrumentations are automatically enabled when the `rails` instrumentation is enabled,
31
+ # patching them on their own automatically outside of the rails integration context would
32
+ # cause undesirable service naming, so we exclude them based their auto_instrument? setting.
33
+ # we also don't want to mix rspec/cucumber integration in as rspec is env we run tests in.
34
+ next unless integration.klass.auto_instrument?
35
+ integrations << integration.name
36
+ end
37
+
38
+ Datadog.configure do |c|
39
+ c.reduce_log_verbosity
40
+ # This will activate auto-instrumentation for Rails
41
+ integrations.each do |integration_name|
42
+ c.use integration_name
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -27,6 +27,11 @@ module Datadog
27
27
  super && version >= MINIMUM_VERSION
28
28
  end
29
29
 
30
+ # test environments should not auto instrument test libraries
31
+ def auto_instrument?
32
+ false
33
+ end
34
+
30
35
  def default_configuration
31
36
  Configuration::Settings.new
32
37
  end