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