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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +48 -1
- data/Appraisals +16 -7
- data/CHANGELOG.md +43 -1
- data/README.md +1 -0
- data/Rakefile +51 -2
- data/ddtrace.gemspec +1 -0
- data/docs/GettingStarted.md +65 -6
- data/lib/ddtrace.rb +7 -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/integration.rb +7 -0
- data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
- data/lib/ddtrace/contrib/active_record/utils.rb +56 -20
- data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
- data/lib/ddtrace/contrib/auto_instrument.rb +48 -0
- data/lib/ddtrace/contrib/cucumber/integration.rb +5 -0
- data/lib/ddtrace/contrib/ethon/easy_patch.rb +5 -4
- data/lib/ddtrace/contrib/extensions.rb +27 -1
- 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/patchable.rb +18 -7
- 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/rspec/integration.rb +5 -0
- data/lib/ddtrace/ext/ci.rb +42 -9
- data/lib/ddtrace/ext/git.rb +0 -1
- data/lib/ddtrace/propagation/http_propagator.rb +17 -2
- data/lib/ddtrace/version.rb +1 -1
- metadata +29 -6
@@ -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
|
@@ -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
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Datadog
|
2
|
+
module Contrib
|
3
|
+
module Httpclient
|
4
|
+
# Httpclient integration constants
|
5
|
+
module Ext
|
6
|
+
APP = 'httpclient'.freeze
|
7
|
+
ENV_ENABLED = 'DD_TRACE_HTTPCLIENT_ENABLED'.freeze
|
8
|
+
ENV_ANALYTICS_ENABLED = 'DD_TRACE_HTTPCLIENT_ANALYTICS_ENABLED'.freeze
|
9
|
+
ENV_ANALYTICS_ENABLED_OLD = 'DD_HTTPCLIENT_ANALYTICS_ENABLED'.freeze
|
10
|
+
ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_HTTPCLIENT_ANALYTICS_SAMPLE_RATE'.freeze
|
11
|
+
ENV_ANALYTICS_SAMPLE_RATE_OLD = 'DD_HTTPCLIENT_ANALYTICS_SAMPLE_RATE'.freeze
|
12
|
+
SERVICE_NAME = 'httpclient'.freeze
|
13
|
+
SPAN_REQUEST = 'httpclient.request'.freeze
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'ddtrace/ext/app_types'
|
2
|
+
require 'ddtrace/ext/http'
|
3
|
+
require 'ddtrace/ext/net'
|
4
|
+
require 'ddtrace/ext/distributed'
|
5
|
+
require 'ddtrace/contrib/analytics'
|
6
|
+
require 'ddtrace/propagation/http_propagator'
|
7
|
+
require 'ddtrace/contrib/http_annotation_helper'
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
module Contrib
|
11
|
+
module Httpclient
|
12
|
+
# Instrumentation for Httpclient
|
13
|
+
module Instrumentation
|
14
|
+
def self.included(base)
|
15
|
+
base.send(:prepend, InstanceMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Instance methods for configuration
|
19
|
+
module InstanceMethods
|
20
|
+
include Datadog::Contrib::HttpAnnotationHelper
|
21
|
+
|
22
|
+
def do_get_block(req, proxy, conn, &block)
|
23
|
+
host = req.header.request_uri.host
|
24
|
+
request_options = datadog_configuration(host)
|
25
|
+
pin = datadog_pin(request_options)
|
26
|
+
|
27
|
+
return super unless pin && pin.tracer
|
28
|
+
|
29
|
+
pin.tracer.trace(Ext::SPAN_REQUEST, on_error: method(:annotate_span_with_error!)) do |span|
|
30
|
+
begin
|
31
|
+
request_options[:service_name] = pin.service_name
|
32
|
+
span.service = service_name(host, request_options)
|
33
|
+
span.span_type = Datadog::Ext::HTTP::TYPE_OUTBOUND
|
34
|
+
|
35
|
+
if pin.tracer.enabled && !should_skip_distributed_tracing?(pin)
|
36
|
+
Datadog::HTTPPropagator.inject!(span.context, req.header)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Add additional request specific tags to the span.
|
40
|
+
annotate_span_with_request!(span, req, request_options)
|
41
|
+
rescue StandardError => e
|
42
|
+
logger.error("error preparing span for httpclient request: #{e}, Source: #{e.backtrace}")
|
43
|
+
ensure
|
44
|
+
res = super
|
45
|
+
end
|
46
|
+
|
47
|
+
# Add additional response specific tags to the span.
|
48
|
+
annotate_span_with_response!(span, res)
|
49
|
+
|
50
|
+
res
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def annotate_span_with_request!(span, req, req_options)
|
57
|
+
http_method = req.header.request_method.upcase
|
58
|
+
uri = req.header.request_uri
|
59
|
+
|
60
|
+
span.resource = http_method
|
61
|
+
span.set_tag(Datadog::Ext::HTTP::METHOD, http_method)
|
62
|
+
span.set_tag(Datadog::Ext::HTTP::URL, uri.path)
|
63
|
+
span.set_tag(Datadog::Ext::NET::TARGET_HOST, uri.host)
|
64
|
+
span.set_tag(Datadog::Ext::NET::TARGET_PORT, uri.port)
|
65
|
+
|
66
|
+
# Tag as an external peer service
|
67
|
+
span.set_tag(Datadog::Ext::Integration::TAG_PEER_SERVICE, span.service)
|
68
|
+
|
69
|
+
set_analytics_sample_rate(span, req_options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def annotate_span_with_response!(span, response)
|
73
|
+
return unless response && response.status
|
74
|
+
|
75
|
+
span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.status)
|
76
|
+
|
77
|
+
case response.status.to_i
|
78
|
+
when 400...599
|
79
|
+
span.set_error(["Error #{response.status}", response.body])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def annotate_span_with_error!(span, error)
|
84
|
+
span.set_error(error)
|
85
|
+
end
|
86
|
+
|
87
|
+
def datadog_pin(config = Datadog.configuration[:httprb])
|
88
|
+
service = config[:service_name]
|
89
|
+
tracer = config[:tracer]
|
90
|
+
|
91
|
+
@datadog_pin ||= begin
|
92
|
+
Datadog::Pin.new(
|
93
|
+
service,
|
94
|
+
app: Ext::APP,
|
95
|
+
app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
|
96
|
+
tracer: -> { config[:tracer] }
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
if @datadog_pin.service_name == default_datadog_pin.service_name && @datadog_pin.service_name != service
|
101
|
+
@datadog_pin.service = service
|
102
|
+
end
|
103
|
+
if @datadog_pin.tracer == default_datadog_pin.tracer && @datadog_pin.tracer != tracer
|
104
|
+
@datadog_pin.tracer = tracer
|
105
|
+
end
|
106
|
+
|
107
|
+
@datadog_pin
|
108
|
+
end
|
109
|
+
|
110
|
+
def default_datadog_pin
|
111
|
+
config = Datadog.configuration[:httpclient]
|
112
|
+
service = config[:service_name]
|
113
|
+
|
114
|
+
@default_datadog_pin ||= begin
|
115
|
+
Datadog::Pin.new(
|
116
|
+
service,
|
117
|
+
app: Ext::APP,
|
118
|
+
app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
|
119
|
+
tracer: -> { config[:tracer] }
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def datadog_configuration(host = :default)
|
125
|
+
Datadog.configuration[:httpclient, host]
|
126
|
+
end
|
127
|
+
|
128
|
+
def analytics_enabled?(request_options)
|
129
|
+
Contrib::Analytics.enabled?(request_options[:analytics_enabled])
|
130
|
+
end
|
131
|
+
|
132
|
+
def logger
|
133
|
+
Datadog.logger
|
134
|
+
end
|
135
|
+
|
136
|
+
def should_skip_distributed_tracing?(pin)
|
137
|
+
if pin.config && pin.config.key?(:distributed_tracing)
|
138
|
+
return !pin.config[:distributed_tracing]
|
139
|
+
end
|
140
|
+
|
141
|
+
!Datadog.configuration[:httpclient][:distributed_tracing]
|
142
|
+
end
|
143
|
+
|
144
|
+
def set_analytics_sample_rate(span, request_options)
|
145
|
+
return unless analytics_enabled?(request_options)
|
146
|
+
Contrib::Analytics.set_sample_rate(span, request_options[:analytics_sample_rate])
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'ddtrace/contrib/integration'
|
2
|
+
require 'ddtrace/contrib/httpclient/configuration/settings'
|
3
|
+
require 'ddtrace/contrib/configuration/resolvers/pattern_resolver'
|
4
|
+
require 'ddtrace/contrib/httpclient/patcher'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module Contrib
|
8
|
+
module Httpclient
|
9
|
+
# Description of Httpclient integration
|
10
|
+
class Integration
|
11
|
+
include Contrib::Integration
|
12
|
+
|
13
|
+
MINIMUM_VERSION = Gem::Version.new('2.2.0')
|
14
|
+
|
15
|
+
register_as :httpclient
|
16
|
+
|
17
|
+
def self.version
|
18
|
+
Gem.loaded_specs['httpclient'] && Gem.loaded_specs['httpclient'].version
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.loaded?
|
22
|
+
!defined?(::HTTPClient).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.compatible?
|
26
|
+
super && version >= MINIMUM_VERSION
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_configuration
|
30
|
+
Configuration::Settings.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def patcher
|
34
|
+
Patcher
|
35
|
+
end
|
36
|
+
|
37
|
+
def resolver
|
38
|
+
@resolver ||= Contrib::Configuration::Resolvers::PatternResolver.new
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'ddtrace/contrib/patcher'
|
2
|
+
require 'ddtrace/contrib/httpclient/instrumentation'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module Contrib
|
6
|
+
# Datadog Httpclient integration.
|
7
|
+
module Httpclient
|
8
|
+
# Patcher enables patching of 'httpclient' module.
|
9
|
+
module Patcher
|
10
|
+
include Contrib::Patcher
|
11
|
+
|
12
|
+
module_function
|
13
|
+
|
14
|
+
def patched?
|
15
|
+
done?(:httpclient)
|
16
|
+
end
|
17
|
+
|
18
|
+
def target_version
|
19
|
+
Integration.version
|
20
|
+
end
|
21
|
+
|
22
|
+
# patch applies our patch
|
23
|
+
def patch
|
24
|
+
do_once(:httpclient) do
|
25
|
+
begin
|
26
|
+
::HTTPClient.send(:include, Instrumentation)
|
27
|
+
rescue StandardError => e
|
28
|
+
Datadog::Logger.error("Unable to apply httpclient integration: #{e}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -42,16 +42,27 @@ module Datadog
|
|
42
42
|
|
43
43
|
def patch
|
44
44
|
if !self.class.patchable? || patcher.nil?
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
return {
|
46
|
+
name: self.class.name,
|
47
|
+
available: self.class.available?,
|
48
|
+
loaded: self.class.loaded?,
|
49
|
+
compatible: self.class.compatible?,
|
50
|
+
patchable: self.class.patchable?
|
51
|
+
}
|
52
52
|
end
|
53
53
|
|
54
54
|
patcher.patch
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
# Can the patch for this integration be applied automatically?
|
59
|
+
# For example: test integrations should only be applied
|
60
|
+
# by the user explicitly setting `c.use :rspec`
|
61
|
+
# and rails sub-modules are auto-instrumented by enabling rails
|
62
|
+
# so auto-instrumenting them on their own will cause changes in
|
63
|
+
# service naming behavior
|
64
|
+
def auto_instrument?
|
65
|
+
true
|
55
66
|
end
|
56
67
|
end
|
57
68
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'ddtrace/contrib/integration'
|
2
2
|
require 'ddtrace/contrib/rack/configuration/settings'
|
3
3
|
require 'ddtrace/contrib/rack/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
|
@@ -53,7 +53,7 @@ module Datadog
|
|
53
53
|
tracer.provider.context = context if context.trace_id
|
54
54
|
end
|
55
55
|
|
56
|
-
#
|
56
|
+
# Create a root Span to keep track of frontend web servers
|
57
57
|
# (i.e. Apache, nginx) if the header is properly set
|
58
58
|
frontend_span = compute_queue_time(env, tracer)
|
59
59
|
|
@@ -1,7 +1,12 @@
|
|
1
1
|
module Datadog
|
2
2
|
module Contrib
|
3
3
|
module Rack
|
4
|
-
#
|
4
|
+
# Retrieves the time spent in an upstream proxy
|
5
|
+
# for the current Rack request.
|
6
|
+
#
|
7
|
+
# This time captures the request delay introduced but
|
8
|
+
# such proxy before the request made it to the Ruby
|
9
|
+
# process.
|
5
10
|
module QueueTime
|
6
11
|
REQUEST_START = 'HTTP_X_REQUEST_START'.freeze
|
7
12
|
QUEUE_START = 'HTTP_X_QUEUE_START'.freeze
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'ddtrace'
|
2
|
+
|
3
|
+
# Railtie to include AutoInstrumentation in rails loading
|
4
|
+
class DatadogAutoInstrumentRailtie < Rails::Railtie
|
5
|
+
# we want to load before config initializers so that any user supplied config
|
6
|
+
# in config/initializers/datadog.rb will take precedence
|
7
|
+
initializer 'datadog.start_tracer', before: :load_config_initializers do
|
8
|
+
Datadog::Contrib::AutoInstrument.patch_all
|
9
|
+
end
|
10
|
+
end
|