ddtrace 0.43.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.
- checksums.yaml +5 -5
- data/.circleci/config.yml +148 -130
- data/.circleci/images/primary/Dockerfile-3.0.0 +73 -0
- data/.github/workflows/add-milestone-to-pull-requests.yml +1 -1
- data/.simplecov +4 -1
- data/Appraisals +215 -14
- data/CHANGELOG.md +1048 -377
- data/Gemfile +4 -2
- data/README.md +1 -0
- data/Rakefile +172 -6
- data/ddtrace.gemspec +6 -8
- data/docker-compose.yml +30 -0
- data/docs/GettingStarted.md +112 -14
- data/lib/ddtrace.rb +8 -0
- data/lib/ddtrace/auto_instrument.rb +3 -0
- data/lib/ddtrace/auto_instrument_base.rb +6 -0
- data/lib/ddtrace/contrib/action_cable/integration.rb +7 -0
- data/lib/ddtrace/contrib/action_pack/integration.rb +7 -0
- data/lib/ddtrace/contrib/action_view/event.rb +0 -4
- data/lib/ddtrace/contrib/action_view/events/render_partial.rb +1 -0
- data/lib/ddtrace/contrib/action_view/events/render_template.rb +1 -0
- data/lib/ddtrace/contrib/action_view/integration.rb +7 -0
- data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
- data/lib/ddtrace/contrib/active_record/utils.rb +67 -21
- data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
- data/lib/ddtrace/contrib/auto_instrument.rb +48 -0
- data/lib/ddtrace/contrib/aws/services.rb +1 -0
- data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +2 -0
- data/lib/ddtrace/contrib/cucumber/integration.rb +5 -0
- data/lib/ddtrace/contrib/ethon/easy_patch.rb +6 -5
- data/lib/ddtrace/contrib/ethon/ext.rb +1 -0
- data/lib/ddtrace/contrib/extensions.rb +27 -1
- data/lib/ddtrace/contrib/grape/endpoint.rb +29 -11
- data/lib/ddtrace/contrib/grape/ext.rb +1 -0
- data/lib/ddtrace/contrib/httpclient/configuration/settings.rb +32 -0
- data/lib/ddtrace/contrib/httpclient/ext.rb +17 -0
- data/lib/ddtrace/contrib/httpclient/instrumentation.rb +152 -0
- data/lib/ddtrace/contrib/httpclient/integration.rb +43 -0
- data/lib/ddtrace/contrib/httpclient/patcher.rb +35 -0
- data/lib/ddtrace/contrib/httprb/instrumentation.rb +1 -1
- data/lib/ddtrace/contrib/patchable.rb +18 -7
- data/lib/ddtrace/contrib/qless/configuration/settings.rb +35 -0
- data/lib/ddtrace/contrib/qless/ext.rb +20 -0
- data/lib/ddtrace/contrib/qless/integration.rb +38 -0
- data/lib/ddtrace/contrib/qless/patcher.rb +35 -0
- data/lib/ddtrace/contrib/qless/qless_job.rb +72 -0
- data/lib/ddtrace/contrib/qless/tracer_cleaner.rb +32 -0
- data/lib/ddtrace/contrib/rack/integration.rb +7 -0
- data/lib/ddtrace/contrib/rack/middlewares.rb +1 -1
- data/lib/ddtrace/contrib/rack/request_queue.rb +6 -1
- data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +10 -0
- data/lib/ddtrace/contrib/rails/utils.rb +4 -0
- data/lib/ddtrace/contrib/rake/integration.rb +1 -1
- data/lib/ddtrace/contrib/redis/configuration/resolver.rb +3 -1
- data/lib/ddtrace/contrib/redis/configuration/settings.rb +5 -0
- data/lib/ddtrace/contrib/redis/ext.rb +1 -0
- data/lib/ddtrace/contrib/redis/patcher.rb +20 -3
- data/lib/ddtrace/contrib/redis/quantize.rb +27 -0
- data/lib/ddtrace/contrib/redis/tags.rb +5 -1
- data/lib/ddtrace/contrib/rspec/integration.rb +5 -0
- data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +2 -2
- data/lib/ddtrace/ext/ci.rb +42 -10
- data/lib/ddtrace/ext/git.rb +0 -1
- data/lib/ddtrace/propagation/http_propagator.rb +17 -2
- data/lib/ddtrace/version.rb +1 -1
- data/lib/ddtrace/workers/runtime_metrics.rb +7 -3
- metadata +91 -20
@@ -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,77 @@ module Datadog
|
|
21
23
|
connection_config[:port]
|
22
24
|
end
|
23
25
|
|
24
|
-
#
|
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
|
-
#
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
+
|
96
|
+
# @return [Hash]
|
60
97
|
def self.default_connection_config
|
61
98
|
return @default_connection_config if instance_variable_defined?(:@default_connection_config)
|
62
99
|
current_connection_name = if ::ActiveRecord::Base.respond_to?(:connection_specification_name)
|
@@ -66,10 +103,19 @@ module Datadog
|
|
66
103
|
end
|
67
104
|
|
68
105
|
connection_pool = ::ActiveRecord::Base.connection_handler.retrieve_connection_pool(current_connection_name)
|
69
|
-
connection_pool.nil? ? EMPTY_CONFIG : (@default_connection_config = connection_pool
|
106
|
+
connection_pool.nil? ? EMPTY_CONFIG : (@default_connection_config = db_config(connection_pool))
|
70
107
|
rescue StandardError
|
71
108
|
EMPTY_CONFIG
|
72
109
|
end
|
110
|
+
|
111
|
+
# @return [Hash]
|
112
|
+
def self.db_config(connection_pool)
|
113
|
+
if ::Rails::VERSION::MAJOR >= 6 && ::Rails::VERSION::MINOR >= 1
|
114
|
+
connection_pool.db_config.configuration_hash
|
115
|
+
else
|
116
|
+
connection_pool.spec.config
|
117
|
+
end
|
118
|
+
end
|
73
119
|
end
|
74
120
|
end
|
75
121
|
end
|
@@ -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
|
@@ -8,6 +8,8 @@ module Datadog
|
|
8
8
|
# Matches strings against Regexps.
|
9
9
|
class PatternResolver < Datadog::Contrib::Configuration::Resolver
|
10
10
|
def resolve(name)
|
11
|
+
return if patterns.empty?
|
12
|
+
|
11
13
|
# Try to find a matching pattern
|
12
14
|
matching_pattern = patterns.find do |pattern|
|
13
15
|
if pattern.is_a?(Proc)
|
@@ -99,7 +99,7 @@ module Datadog
|
|
99
99
|
|
100
100
|
def datadog_tag_request
|
101
101
|
span = @datadog_span
|
102
|
-
method =
|
102
|
+
method = Ext::NOT_APPLICABLE_METHOD
|
103
103
|
if instance_variable_defined?(:@datadog_method) && !@datadog_method.nil?
|
104
104
|
method = @datadog_method.to_s
|
105
105
|
end
|
@@ -109,11 +109,12 @@ module Datadog
|
|
109
109
|
# Set analytics sample rate
|
110
110
|
Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
|
111
111
|
|
112
|
-
|
113
|
-
|
112
|
+
this_uri = uri
|
113
|
+
return unless this_uri
|
114
|
+
span.set_tag(Datadog::Ext::HTTP::URL, this_uri.path)
|
114
115
|
span.set_tag(Datadog::Ext::HTTP::METHOD, method)
|
115
|
-
span.set_tag(Datadog::Ext::NET::TARGET_HOST,
|
116
|
-
span.set_tag(Datadog::Ext::NET::TARGET_PORT,
|
116
|
+
span.set_tag(Datadog::Ext::NET::TARGET_HOST, this_uri.host)
|
117
|
+
span.set_tag(Datadog::Ext::NET::TARGET_PORT, this_uri.port)
|
117
118
|
end
|
118
119
|
|
119
120
|
def set_span_error_message(message)
|
@@ -27,8 +27,26 @@ module Datadog
|
|
27
27
|
|
28
28
|
# Activate integrations
|
29
29
|
if target.respond_to?(:integrations_pending_activation)
|
30
|
+
reduce_verbosity = target.respond_to?(:reduce_verbosity?) ? target.reduce_verbosity? : false
|
30
31
|
target.integrations_pending_activation.each do |integration|
|
31
|
-
|
32
|
+
next unless integration.respond_to?(:patch)
|
33
|
+
# integration.patch returns either true or a hash of details on why patching failed
|
34
|
+
patch_results = integration.patch
|
35
|
+
|
36
|
+
next if patch_results == true
|
37
|
+
|
38
|
+
# if patching failed, only log output if verbosity is unset
|
39
|
+
# or if patching failure is due to compatibility or integration specific reasons
|
40
|
+
next unless !reduce_verbosity ||
|
41
|
+
((patch_results[:available] && patch_results[:loaded]) &&
|
42
|
+
(!patch_results[:compatible] || !patch_results[:patchable]))
|
43
|
+
|
44
|
+
desc = "Available?: #{patch_results[:available]}"
|
45
|
+
desc += ", Loaded? #{patch_results[:loaded]}"
|
46
|
+
desc += ", Compatible? #{patch_results[:compatible]}"
|
47
|
+
desc += ", Patchable? #{patch_results[:patchable]}"
|
48
|
+
|
49
|
+
Datadog.logger.warn("Unable to patch #{patch_results['name']} (#{desc})")
|
32
50
|
end
|
33
51
|
|
34
52
|
target.integrations_pending_activation.clear
|
@@ -86,6 +104,14 @@ module Datadog
|
|
86
104
|
registry[name] ||
|
87
105
|
raise(InvalidIntegrationError, "'#{name}' is not a valid integration.")
|
88
106
|
end
|
107
|
+
|
108
|
+
def reduce_verbosity?
|
109
|
+
defined?(@reduce_verbosity) ? @reduce_verbosity : false
|
110
|
+
end
|
111
|
+
|
112
|
+
def reduce_log_verbosity
|
113
|
+
@reduce_verbosity ||= true
|
114
|
+
end
|
89
115
|
end
|
90
116
|
end
|
91
117
|
end
|
@@ -61,17 +61,12 @@ module Datadog
|
|
61
61
|
begin
|
62
62
|
# collect endpoint details
|
63
63
|
api = payload[:endpoint].options[:for]
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
api.to_s
|
71
|
-
end
|
72
|
-
|
73
|
-
path = payload[:endpoint].options[:path].join('/')
|
74
|
-
resource = "#{api_view}##{path}"
|
64
|
+
|
65
|
+
api_view = api_view(api)
|
66
|
+
|
67
|
+
request_method = payload[:endpoint].options[:method].first
|
68
|
+
path = endpoint_expand_path(payload[:endpoint])
|
69
|
+
resource = "#{api_view} #{request_method} #{path}"
|
75
70
|
span.resource = resource
|
76
71
|
|
77
72
|
# set the request span resource if it's a `rack.request` span
|
@@ -97,6 +92,10 @@ module Datadog
|
|
97
92
|
# override the current span with this notification values
|
98
93
|
span.set_tag(Ext::TAG_ROUTE_ENDPOINT, api_view) unless api_view.nil?
|
99
94
|
span.set_tag(Ext::TAG_ROUTE_PATH, path)
|
95
|
+
span.set_tag(Ext::TAG_ROUTE_METHOD, request_method)
|
96
|
+
|
97
|
+
span.set_tag(Datadog::Ext::HTTP::METHOD, request_method)
|
98
|
+
span.set_tag(Datadog::Ext::HTTP::URL, path)
|
100
99
|
ensure
|
101
100
|
span.start(start)
|
102
101
|
span.finish(finish)
|
@@ -187,6 +186,25 @@ module Datadog
|
|
187
186
|
|
188
187
|
private
|
189
188
|
|
189
|
+
def api_view(api)
|
190
|
+
# If the API inherits from Grape::API in version >= 1.2.0
|
191
|
+
# then the API will be an instance and the name must be derived from the base.
|
192
|
+
# See https://github.com/ruby-grape/grape/issues/1825
|
193
|
+
if defined?(::Grape::API::Instance) && api <= ::Grape::API::Instance
|
194
|
+
api.base.to_s
|
195
|
+
else
|
196
|
+
api.to_s
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def endpoint_expand_path(endpoint)
|
201
|
+
route_path = endpoint.options[:path]
|
202
|
+
namespace = endpoint.routes.first && endpoint.routes.first.namespace || ''
|
203
|
+
|
204
|
+
parts = (namespace.split('/') + route_path).reject { |p| p.blank? || p.eql?('/') }
|
205
|
+
parts.join('/').prepend('/')
|
206
|
+
end
|
207
|
+
|
190
208
|
def tracer
|
191
209
|
datadog_configuration[:tracer]
|
192
210
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'ddtrace/contrib/configuration/settings'
|
2
|
+
require 'ddtrace/contrib/httpclient/ext'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module Contrib
|
6
|
+
module Httpclient
|
7
|
+
module Configuration
|
8
|
+
# Custom settings for the Httpclient integration
|
9
|
+
class Settings < Contrib::Configuration::Settings
|
10
|
+
option :enabled do |o|
|
11
|
+
o.default { env_to_bool(Ext::ENV_ENABLED, true) }
|
12
|
+
o.lazy
|
13
|
+
end
|
14
|
+
|
15
|
+
option :analytics_enabled do |o|
|
16
|
+
o.default { env_to_bool([Ext::ENV_ANALYTICS_ENABLED, Ext::ENV_ANALYTICS_ENABLED_OLD], false) }
|
17
|
+
o.lazy
|
18
|
+
end
|
19
|
+
|
20
|
+
option :analytics_sample_rate do |o|
|
21
|
+
o.default { env_to_float([Ext::ENV_ANALYTICS_SAMPLE_RATE, Ext::ENV_ANALYTICS_SAMPLE_RATE_OLD], 1.0) }
|
22
|
+
o.lazy
|
23
|
+
end
|
24
|
+
|
25
|
+
option :distributed_tracing, default: true
|
26
|
+
option :service_name, default: Ext::SERVICE_NAME
|
27
|
+
option :split_by_domain, default: false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|