ddtrace 0.44.0 → 0.45.0

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