ddtrace 0.34.1 → 0.36.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 +58 -9
- data/.circleci/images/primary/Dockerfile-jruby-9.2 +77 -0
- data/.rubocop.yml +4 -0
- data/Appraisals +9 -7
- data/CHANGELOG.md +89 -3
- data/Rakefile +11 -2
- data/ddtrace.gemspec +5 -3
- data/docker-compose.yml +35 -0
- data/docs/DevelopmentGuide.md +1 -1
- data/docs/GettingStarted.md +89 -36
- data/lib/ddtrace.rb +1 -1
- data/lib/ddtrace/buffer.rb +9 -9
- data/lib/ddtrace/chunker.rb +34 -0
- data/lib/ddtrace/configuration.rb +28 -5
- data/lib/ddtrace/configuration/base.rb +1 -1
- data/lib/ddtrace/configuration/components.rb +154 -0
- data/lib/ddtrace/configuration/options.rb +1 -1
- data/lib/ddtrace/configuration/settings.rb +131 -63
- data/lib/ddtrace/context.rb +6 -6
- data/lib/ddtrace/context_flush.rb +1 -1
- data/lib/ddtrace/contrib/action_cable/instrumentation.rb +1 -1
- data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +2 -2
- data/lib/ddtrace/contrib/action_view/events/render_partial.rb +1 -1
- data/lib/ddtrace/contrib/action_view/events/render_template.rb +1 -1
- data/lib/ddtrace/contrib/action_view/instrumentation/partial_renderer.rb +1 -1
- data/lib/ddtrace/contrib/action_view/instrumentation/template_renderer.rb +2 -2
- data/lib/ddtrace/contrib/action_view/patcher.rb +1 -1
- data/lib/ddtrace/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/ddtrace/contrib/active_record/events/sql.rb +1 -1
- data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +2 -2
- data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/ddtrace/contrib/analytics.rb +1 -1
- data/lib/ddtrace/contrib/configuration/settings.rb +1 -1
- data/lib/ddtrace/contrib/dalli/patcher.rb +1 -1
- data/lib/ddtrace/contrib/dalli/quantize.rb +1 -1
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -1
- data/lib/ddtrace/contrib/excon/middleware.rb +2 -2
- data/lib/ddtrace/contrib/extensions.rb +29 -5
- data/lib/ddtrace/contrib/faraday/patcher.rb +1 -1
- data/lib/ddtrace/contrib/grape/endpoint.rb +5 -5
- data/lib/ddtrace/contrib/grape/patcher.rb +1 -1
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +1 -1
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +2 -2
- data/lib/ddtrace/contrib/grpc/patcher.rb +1 -1
- data/lib/ddtrace/contrib/http/circuit_breaker.rb +8 -32
- data/lib/ddtrace/contrib/http/instrumentation.rb +2 -2
- data/lib/ddtrace/contrib/mongodb/subscribers.rb +2 -2
- data/lib/ddtrace/contrib/patchable.rb +1 -1
- data/lib/ddtrace/contrib/patcher.rb +3 -3
- data/lib/ddtrace/contrib/presto/instrumentation.rb +3 -3
- data/lib/ddtrace/contrib/presto/patcher.rb +1 -1
- data/lib/ddtrace/contrib/rack/middlewares.rb +2 -2
- data/lib/ddtrace/contrib/rack/patcher.rb +2 -2
- data/lib/ddtrace/contrib/rack/request_queue.rb +1 -1
- data/lib/ddtrace/contrib/rails/configuration/settings.rb +14 -0
- data/lib/ddtrace/contrib/rails/framework.rb +54 -48
- data/lib/ddtrace/contrib/rails/integration.rb +1 -1
- data/lib/ddtrace/contrib/rake/instrumentation.rb +2 -2
- data/lib/ddtrace/contrib/redis/quantize.rb +1 -1
- data/lib/ddtrace/contrib/resque/resque_job.rb +2 -2
- data/lib/ddtrace/contrib/sidekiq/tracing.rb +1 -1
- data/lib/ddtrace/contrib/sinatra/env.rb +20 -0
- data/lib/ddtrace/contrib/sinatra/ext.rb +6 -0
- data/lib/ddtrace/contrib/sinatra/patcher.rb +1 -0
- data/lib/ddtrace/contrib/sinatra/tracer.rb +98 -35
- data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +16 -13
- data/lib/ddtrace/correlation.rb +9 -6
- data/lib/ddtrace/diagnostics/health.rb +2 -6
- data/lib/ddtrace/encoding.rb +13 -39
- data/lib/ddtrace/event.rb +1 -1
- data/lib/ddtrace/ext/correlation.rb +1 -0
- data/lib/ddtrace/ext/diagnostics.rb +2 -0
- data/lib/ddtrace/ext/environment.rb +1 -0
- data/lib/ddtrace/ext/forced_tracing.rb +1 -1
- data/lib/ddtrace/logger.rb +3 -44
- data/lib/ddtrace/metrics.rb +5 -5
- data/lib/ddtrace/monkey.rb +1 -1
- data/lib/ddtrace/opentracer/global_tracer.rb +1 -1
- data/lib/ddtrace/pin.rb +18 -17
- data/lib/ddtrace/pipeline.rb +1 -1
- data/lib/ddtrace/propagation/http_propagator.rb +2 -2
- data/lib/ddtrace/runtime/cgroup.rb +1 -1
- data/lib/ddtrace/runtime/container.rb +1 -1
- data/lib/ddtrace/runtime/metrics.rb +5 -2
- data/lib/ddtrace/sampler.rb +2 -2
- data/lib/ddtrace/sampling/rule.rb +1 -1
- data/lib/ddtrace/sampling/rule_sampler.rb +1 -1
- data/lib/ddtrace/span.rb +4 -4
- data/lib/ddtrace/sync_writer.rb +3 -8
- data/lib/ddtrace/tracer.rb +26 -31
- data/lib/ddtrace/transport/http.rb +1 -1
- data/lib/ddtrace/transport/http/api/instance.rb +4 -0
- data/lib/ddtrace/transport/http/builder.rb +3 -5
- data/lib/ddtrace/transport/http/client.rb +7 -64
- data/lib/ddtrace/transport/http/response.rb +1 -1
- data/lib/ddtrace/transport/http/statistics.rb +1 -1
- data/lib/ddtrace/transport/http/traces.rb +10 -7
- data/lib/ddtrace/transport/io.rb +1 -1
- data/lib/ddtrace/transport/io/client.rb +2 -2
- data/lib/ddtrace/transport/io/response.rb +3 -1
- data/lib/ddtrace/transport/io/traces.rb +50 -3
- data/lib/ddtrace/transport/parcel.rb +0 -4
- data/lib/ddtrace/transport/statistics.rb +2 -2
- data/lib/ddtrace/transport/traces.rb +160 -10
- data/lib/ddtrace/utils.rb +1 -1
- data/lib/ddtrace/version.rb +2 -2
- data/lib/ddtrace/workers.rb +5 -13
- data/lib/ddtrace/workers/async.rb +2 -2
- data/lib/ddtrace/workers/runtime_metrics.rb +47 -0
- data/lib/ddtrace/workers/trace_writer.rb +199 -0
- data/lib/ddtrace/writer.rb +20 -27
- metadata +22 -32
@@ -37,7 +37,7 @@ module Datadog
|
|
37
37
|
pin = datadog_pin(request_options)
|
38
38
|
return super(req, body, &block) unless pin && pin.tracer
|
39
39
|
|
40
|
-
if Datadog::Contrib::HTTP.should_skip_tracing?(req,
|
40
|
+
if Datadog::Contrib::HTTP.should_skip_tracing?(req, pin.tracer)
|
41
41
|
return super(req, body, &block)
|
42
42
|
end
|
43
43
|
|
@@ -58,7 +58,7 @@ module Datadog
|
|
58
58
|
# Add additional request specific tags to the span.
|
59
59
|
annotate_span_with_request!(span, req, request_options)
|
60
60
|
rescue StandardError => e
|
61
|
-
Datadog
|
61
|
+
Datadog.logger.error("error preparing span for http request: #{e}")
|
62
62
|
ensure
|
63
63
|
response = super(req, body, &block)
|
64
64
|
end
|
@@ -50,7 +50,7 @@ module Datadog
|
|
50
50
|
# the framework itself, so we set only the error and the message
|
51
51
|
span.set_error(event)
|
52
52
|
rescue StandardError => e
|
53
|
-
Datadog
|
53
|
+
Datadog.logger.debug("error when handling MongoDB 'failed' event: #{e}")
|
54
54
|
ensure
|
55
55
|
# whatever happens, the Span must be removed from the local storage and
|
56
56
|
# it must be finished to prevent any leak
|
@@ -66,7 +66,7 @@ module Datadog
|
|
66
66
|
rows = event.reply.fetch('n', nil)
|
67
67
|
span.set_tag(Ext::TAG_ROWS, rows) unless rows.nil?
|
68
68
|
rescue StandardError => e
|
69
|
-
Datadog
|
69
|
+
Datadog.logger.debug("error when handling MongoDB 'succeeded' event: #{e}")
|
70
70
|
ensure
|
71
71
|
# whatever happens, the Span must be removed from the local storage and
|
72
72
|
# it must be finished to prevent any leak
|
@@ -47,7 +47,7 @@ module Datadog
|
|
47
47
|
desc += ", Compatible? #{self.class.compatible?}"
|
48
48
|
desc += ", Patchable? #{self.class.patchable?}"
|
49
49
|
|
50
|
-
Datadog
|
50
|
+
Datadog.logger.warn("Unable to patch #{self.class.name} (#{desc})")
|
51
51
|
return
|
52
52
|
end
|
53
53
|
|
@@ -28,17 +28,17 @@ module Datadog
|
|
28
28
|
begin
|
29
29
|
super.tap do
|
30
30
|
# Emit a metric
|
31
|
-
|
31
|
+
Datadog.health_metrics.instrumentation_patched(1, tags: default_tags)
|
32
32
|
end
|
33
33
|
rescue StandardError => e
|
34
34
|
# Log the error
|
35
|
-
Datadog
|
35
|
+
Datadog.logger.error("Failed to apply #{patch_name} patch. Cause: #{e} Location: #{e.backtrace.first}")
|
36
36
|
|
37
37
|
# Emit a metric
|
38
38
|
tags = default_tags
|
39
39
|
tags << "error:#{e.class.name}"
|
40
40
|
|
41
|
-
|
41
|
+
Datadog.health_metrics.error_instrumentation_patch(1, tags: tags)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -24,7 +24,7 @@ module Datadog
|
|
24
24
|
span.span_type = Datadog::Ext::SQL::TYPE
|
25
25
|
span.set_tag(Ext::TAG_QUERY_ASYNC, false)
|
26
26
|
rescue StandardError => e
|
27
|
-
Datadog
|
27
|
+
Datadog.logger.debug("error preparing span for presto: #{e}")
|
28
28
|
end
|
29
29
|
|
30
30
|
super(query)
|
@@ -39,7 +39,7 @@ module Datadog
|
|
39
39
|
span.span_type = Datadog::Ext::SQL::TYPE
|
40
40
|
span.set_tag(Ext::TAG_QUERY_ASYNC, !blk.nil?)
|
41
41
|
rescue StandardError => e
|
42
|
-
Datadog
|
42
|
+
Datadog.logger.debug("error preparing span for presto: #{e}")
|
43
43
|
end
|
44
44
|
|
45
45
|
super(query, &blk)
|
@@ -55,7 +55,7 @@ module Datadog
|
|
55
55
|
# ^ not an SQL type span, since there's no SQL query
|
56
56
|
span.set_tag(Ext::TAG_QUERY_ID, query_id)
|
57
57
|
rescue StandardError => e
|
58
|
-
Datadog
|
58
|
+
Datadog.logger.debug("error preparing span for presto: #{e}")
|
59
59
|
end
|
60
60
|
|
61
61
|
super(query_id)
|
@@ -20,7 +20,7 @@ module Datadog
|
|
20
20
|
begin
|
21
21
|
::Presto::Client::Client.send(:include, Instrumentation::Client)
|
22
22
|
rescue StandardError => e
|
23
|
-
Datadog
|
23
|
+
Datadog.logger.error("Unable to apply Presto integration: #{e}")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -222,7 +222,7 @@ module Datadog
|
|
222
222
|
if key == :datadog_rack_request_span \
|
223
223
|
&& @datadog_span_warning \
|
224
224
|
&& @datadog_deprecation_warnings
|
225
|
-
Datadog
|
225
|
+
Datadog.logger.warn(REQUEST_SPAN_DEPRECATION_WARNING)
|
226
226
|
@datadog_span_warning = true
|
227
227
|
end
|
228
228
|
super
|
@@ -232,7 +232,7 @@ module Datadog
|
|
232
232
|
if key == :datadog_rack_request_span \
|
233
233
|
&& @datadog_span_warning \
|
234
234
|
&& @datadog_deprecation_warnings
|
235
|
-
Datadog
|
235
|
+
Datadog.logger.warn(REQUEST_SPAN_DEPRECATION_WARNING)
|
236
236
|
@datadog_span_warning = true
|
237
237
|
end
|
238
238
|
super
|
@@ -38,7 +38,7 @@ module Datadog
|
|
38
38
|
# context of middleware patching outside a Rails server process (eg. a
|
39
39
|
# process that doesn't serve HTTP requests but has Rails environment
|
40
40
|
# loaded such as a Resque master process)
|
41
|
-
|
41
|
+
Datadog.logger.debug("Error patching middleware stack: #{e}")
|
42
42
|
end
|
43
43
|
|
44
44
|
def retain_middleware_name(middleware)
|
@@ -90,7 +90,7 @@ module Datadog
|
|
90
90
|
if get_option(:application)
|
91
91
|
MiddlewareNamePatcher.patch
|
92
92
|
else
|
93
|
-
Datadog
|
93
|
+
Datadog.logger.warn(%(
|
94
94
|
Rack :middleware_names requires you to also pass :application.
|
95
95
|
Middleware names have NOT been patched; please provide :application.
|
96
96
|
e.g. use: :rack, middleware_names: true, application: my_rack_app).freeze)
|
@@ -30,7 +30,7 @@ module Datadog
|
|
30
30
|
rescue StandardError => e
|
31
31
|
# in case of an Exception we don't create a
|
32
32
|
# `request.queuing` span
|
33
|
-
Datadog
|
33
|
+
Datadog.logger.debug("[rack] unable to parse request queue headers: #{e}")
|
34
34
|
nil
|
35
35
|
end
|
36
36
|
end
|
@@ -6,6 +6,19 @@ module Datadog
|
|
6
6
|
module Configuration
|
7
7
|
# Custom settings for the Rails integration
|
8
8
|
class Settings < Contrib::Configuration::Settings
|
9
|
+
def initialize(options = {})
|
10
|
+
super(options)
|
11
|
+
|
12
|
+
# NOTE: Eager load these
|
13
|
+
# Rails integration is responsible for orchestrating other integrations.
|
14
|
+
# When using environment variables, settings will not be automatically
|
15
|
+
# filled because nothing explicitly calls them. They must though, so
|
16
|
+
# integrations like ActionPack can receive the value as it should.
|
17
|
+
# Trigger these manually to force an eager load and propagate them.
|
18
|
+
analytics_enabled
|
19
|
+
analytics_sample_rate
|
20
|
+
end
|
21
|
+
|
9
22
|
option :analytics_enabled do |o|
|
10
23
|
o.default { env_to_bool(Ext::ENV_ANALYTICS_ENABLED, nil) }
|
11
24
|
o.lazy
|
@@ -72,6 +85,7 @@ module Datadog
|
|
72
85
|
Datadog.configuration[:active_support][:tracer] = value
|
73
86
|
Datadog.configuration[:action_pack][:tracer] = value
|
74
87
|
Datadog.configuration[:action_view][:tracer] = value
|
88
|
+
Datadog.configuration[:rack][:tracer] = value
|
75
89
|
end
|
76
90
|
end
|
77
91
|
end
|
@@ -21,30 +21,32 @@ module Datadog
|
|
21
21
|
module Framework
|
22
22
|
# configure Datadog settings
|
23
23
|
def self.setup
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
24
|
+
rails_config = config_with_defaults
|
25
|
+
|
26
|
+
# NOTE: #configure has the side effect of rebuilding trace components.
|
27
|
+
# During a typical Rails application lifecycle, we will see trace
|
28
|
+
# components initialized twice because of this. This is necessary
|
29
|
+
# because key configuration is not available until after the Rails
|
30
|
+
# application has fully loaded, and some of this configuration is
|
31
|
+
# used to reconfigure tracer components with Rails-sourced defaults.
|
32
|
+
# This is a trade-off we take to get nice defaults.
|
33
|
+
Datadog.configure do |datadog_config|
|
34
|
+
# By default, default service would be guessed from the script
|
35
|
+
# being executed, but here we know better, get it from Rails config.
|
36
|
+
# Don't set this if service has been explicitly provided by the user.
|
37
|
+
datadog_config.service ||= rails_config[:service_name]
|
38
|
+
|
39
|
+
activate_rack!(datadog_config, rails_config)
|
40
|
+
activate_action_cable!(datadog_config, rails_config)
|
41
|
+
activate_active_support!(datadog_config, rails_config)
|
42
|
+
activate_action_pack!(datadog_config, rails_config)
|
43
|
+
activate_action_view!(datadog_config, rails_config)
|
44
|
+
activate_active_record!(datadog_config, rails_config)
|
45
|
+
end
|
41
46
|
|
42
47
|
# Update the tracer if its not the default tracer.
|
43
|
-
if
|
44
|
-
|
45
|
-
|
46
|
-
env = Datadog.configuration.env || (::Rails.respond_to?(:env) && ::Rails.env)
|
47
|
-
config[:tracer].set_tags('env' => env) if env
|
48
|
+
if rails_config[:tracer] != Datadog.configuration.tracer
|
49
|
+
rails_config[:tracer].default_service = rails_config[:service_name]
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -59,64 +61,68 @@ module Datadog
|
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
|
-
def self.activate_rack!(
|
63
|
-
|
64
|
+
def self.activate_rack!(datadog_config, rails_config)
|
65
|
+
datadog_config.use(
|
64
66
|
:rack,
|
65
|
-
tracer:
|
67
|
+
tracer: rails_config[:tracer],
|
66
68
|
application: ::Rails.application,
|
67
|
-
service_name:
|
68
|
-
middleware_names:
|
69
|
-
distributed_tracing:
|
69
|
+
service_name: rails_config[:service_name],
|
70
|
+
middleware_names: rails_config[:middleware_names],
|
71
|
+
distributed_tracing: rails_config[:distributed_tracing]
|
70
72
|
)
|
71
73
|
end
|
72
74
|
|
73
|
-
def self.activate_active_support!(
|
75
|
+
def self.activate_active_support!(datadog_config, rails_config)
|
74
76
|
return unless defined?(::ActiveSupport)
|
75
77
|
|
76
|
-
|
78
|
+
datadog_config.use(
|
77
79
|
:active_support,
|
78
|
-
cache_service:
|
79
|
-
tracer:
|
80
|
+
cache_service: rails_config[:cache_service],
|
81
|
+
tracer: rails_config[:tracer]
|
80
82
|
)
|
81
83
|
end
|
82
84
|
|
83
|
-
def self.activate_action_cable!(
|
85
|
+
def self.activate_action_cable!(datadog_config, rails_config)
|
84
86
|
return unless defined?(::ActionCable)
|
85
87
|
|
86
|
-
|
88
|
+
datadog_config.use(
|
87
89
|
:action_cable,
|
88
|
-
service_name: "#{
|
89
|
-
tracer:
|
90
|
+
service_name: "#{rails_config[:service_name]}-#{Contrib::ActionCable::Ext::SERVICE_NAME}",
|
91
|
+
tracer: rails_config[:tracer]
|
90
92
|
)
|
91
93
|
end
|
92
94
|
|
93
|
-
def self.activate_action_pack!(
|
95
|
+
def self.activate_action_pack!(datadog_config, rails_config)
|
94
96
|
return unless defined?(::ActionPack)
|
95
97
|
|
96
|
-
|
98
|
+
# TODO: This is configuring ActionPack but not patching. It will queue ActionPack
|
99
|
+
# for patching, but patching won't take place until Datadog.configure completes.
|
100
|
+
# Should we manually patch here?
|
101
|
+
|
102
|
+
datadog_config.use(
|
97
103
|
:action_pack,
|
98
|
-
service_name:
|
99
|
-
tracer:
|
104
|
+
service_name: rails_config[:service_name],
|
105
|
+
tracer: rails_config[:tracer]
|
100
106
|
)
|
101
107
|
end
|
102
108
|
|
103
|
-
def self.activate_action_view!(
|
109
|
+
def self.activate_action_view!(datadog_config, rails_config)
|
104
110
|
return unless defined?(::ActionView)
|
105
111
|
|
106
|
-
|
112
|
+
datadog_config.use(
|
107
113
|
:action_view,
|
108
|
-
service_name:
|
109
|
-
tracer:
|
114
|
+
service_name: rails_config[:service_name],
|
115
|
+
tracer: rails_config[:tracer]
|
110
116
|
)
|
111
117
|
end
|
112
118
|
|
113
|
-
def self.activate_active_record!(
|
119
|
+
def self.activate_active_record!(datadog_config, rails_config)
|
114
120
|
return unless defined?(::ActiveRecord)
|
115
121
|
|
116
|
-
|
122
|
+
datadog_config.use(
|
117
123
|
:active_record,
|
118
|
-
service_name:
|
119
|
-
tracer:
|
124
|
+
service_name: rails_config[:database_service],
|
125
|
+
tracer: rails_config[:tracer]
|
120
126
|
)
|
121
127
|
end
|
122
128
|
end
|
@@ -51,14 +51,14 @@ module Datadog
|
|
51
51
|
span.set_tag(Ext::TAG_TASK_ARG_NAMES, arg_names)
|
52
52
|
span.set_tag(Ext::TAG_INVOKE_ARGS, quantize_args(args)) unless args.nil?
|
53
53
|
rescue StandardError => e
|
54
|
-
Datadog
|
54
|
+
Datadog.logger.debug("Error while tracing Rake invoke: #{e.message}")
|
55
55
|
end
|
56
56
|
|
57
57
|
def annotate_execute!(span, args)
|
58
58
|
span.resource = name
|
59
59
|
span.set_tag(Ext::TAG_EXECUTE_ARGS, quantize_args(args.to_hash)) unless args.nil?
|
60
60
|
rescue StandardError => e
|
61
|
-
Datadog
|
61
|
+
Datadog.logger.debug("Error while tracing Rake execute: #{e.message}")
|
62
62
|
end
|
63
63
|
|
64
64
|
def quantize_args(args)
|
@@ -15,7 +15,7 @@ module Datadog
|
|
15
15
|
str = Utils.utf8_encode(str, binary: true, placeholder: PLACEHOLDER)
|
16
16
|
Utils.truncate(str, VALUE_MAX_LEN, TOO_LONG_MARK)
|
17
17
|
rescue => e
|
18
|
-
Datadog
|
18
|
+
Datadog.logger.debug("non formattable Redis arg #{str}: #{e}")
|
19
19
|
PLACEHOLDER
|
20
20
|
end
|
21
21
|
|
@@ -9,11 +9,11 @@ module Datadog
|
|
9
9
|
module Resque
|
10
10
|
# Uses Resque job hooks to create traces
|
11
11
|
module ResqueJob
|
12
|
-
def around_perform(*
|
12
|
+
def around_perform(*args)
|
13
13
|
return yield unless datadog_configuration && tracer
|
14
14
|
|
15
15
|
tracer.trace(Ext::SPAN_JOB, span_options) do |span|
|
16
|
-
span.resource = name
|
16
|
+
span.resource = args.first.is_a?(Hash) && args.first['job_class'] || name
|
17
17
|
span.span_type = Datadog::Ext::AppTypes::WORKER
|
18
18
|
# Set analytics sample rate
|
19
19
|
if Contrib::Analytics.enabled?(datadog_configuration[:analytics_enabled])
|
@@ -26,7 +26,7 @@ module Datadog
|
|
26
26
|
job['class'].to_s
|
27
27
|
end
|
28
28
|
rescue => e
|
29
|
-
Datadog
|
29
|
+
Datadog.logger.debug { "Error retrieving Sidekiq job class name (jid:#{job['jid']}): #{e}" }
|
30
30
|
|
31
31
|
job['class'].to_s
|
32
32
|
end
|
@@ -32,6 +32,26 @@ module Datadog
|
|
32
32
|
def header_to_rack_header(name)
|
33
33
|
"HTTP_#{name.to_s.upcase.gsub(/[-\s]/, '_')}"
|
34
34
|
end
|
35
|
+
|
36
|
+
# Was a Sinatra already traced in this request?
|
37
|
+
# We don't want to create spans for intermediate Sinatra
|
38
|
+
# middlewares that don't match the request at hand.
|
39
|
+
def middleware_traced?(env)
|
40
|
+
env[Ext::RACK_ENV_MIDDLEWARE_TRACED]
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_middleware_traced(env, bool)
|
44
|
+
env[Ext::RACK_ENV_MIDDLEWARE_TRACED] = bool
|
45
|
+
end
|
46
|
+
|
47
|
+
# The start time of the top-most Sinatra middleware.
|
48
|
+
def middleware_start_time(env)
|
49
|
+
env[Ext::RACK_ENV_MIDDLEWARE_START_TIME]
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_middleware_start_time(env, time = Time.now.utc)
|
53
|
+
env[Ext::RACK_ENV_MIDDLEWARE_START_TIME] = time
|
54
|
+
end
|
35
55
|
end
|
36
56
|
end
|
37
57
|
end
|
@@ -7,10 +7,16 @@ module Datadog
|
|
7
7
|
ENV_ANALYTICS_ENABLED = 'DD_SINATRA_ANALYTICS_ENABLED'.freeze
|
8
8
|
ENV_ANALYTICS_SAMPLE_RATE = 'DD_SINATRA_ANALYTICS_SAMPLE_RATE'.freeze
|
9
9
|
RACK_ENV_REQUEST_SPAN = 'datadog.sinatra_request_span'.freeze
|
10
|
+
RACK_ENV_MIDDLEWARE_START_TIME = 'datadog.sinatra_middleware_start_time'.freeze
|
11
|
+
RACK_ENV_MIDDLEWARE_TRACED = 'datadog.sinatra_middleware_traced'.freeze
|
10
12
|
SERVICE_NAME = 'sinatra'.freeze
|
11
13
|
SPAN_RENDER_TEMPLATE = 'sinatra.render_template'.freeze
|
12
14
|
SPAN_REQUEST = 'sinatra.request'.freeze
|
15
|
+
SPAN_ROUTE = 'sinatra.route'.freeze
|
16
|
+
TAG_APP_NAME = 'sinatra.app.name'.freeze
|
13
17
|
TAG_ROUTE_PATH = 'sinatra.route.path'.freeze
|
18
|
+
TAG_SCRIPT_NAME = 'sinatra.script_name'.freeze
|
19
|
+
TAG_TEMPLATE_ENGINE = 'sinatra.template_engine'.freeze
|
14
20
|
TAG_TEMPLATE_NAME = 'sinatra.template_name'.freeze
|
15
21
|
end
|
16
22
|
end
|
@@ -21,6 +21,10 @@ module Datadog
|
|
21
21
|
condition do
|
22
22
|
# If the option to prepend script names is enabled, then
|
23
23
|
# prepend the script name from the request onto the action.
|
24
|
+
#
|
25
|
+
# DEV: env['sinatra.route'] already exists with very similar information,
|
26
|
+
# DEV: but doesn't account for our `resource_script_names` logic.
|
27
|
+
#
|
24
28
|
@datadog_route = if Datadog.configuration[:sinatra][:resource_script_names]
|
25
29
|
"#{request.script_name}#{action}"
|
26
30
|
else
|
@@ -32,53 +36,112 @@ module Datadog
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def self.registered(app)
|
35
|
-
|
36
|
-
def render(engine, data, *)
|
37
|
-
output = ''
|
38
|
-
tracer = Datadog.configuration[:sinatra][:tracer]
|
39
|
-
if tracer.enabled
|
40
|
-
tracer.trace(Ext::SPAN_RENDER_TEMPLATE, span_type: Datadog::Ext::HTTP::TEMPLATE) do |span|
|
41
|
-
# If data is a string, it is a literal template and we don't
|
42
|
-
# want to record it.
|
43
|
-
span.set_tag(Ext::TAG_TEMPLATE_NAME, data) if data.is_a? Symbol
|
44
|
-
|
45
|
-
# Measure service stats
|
46
|
-
Contrib::Analytics.set_measured(span)
|
47
|
-
|
48
|
-
output = super
|
49
|
-
end
|
50
|
-
else
|
51
|
-
output = super
|
52
|
-
end
|
39
|
+
app.use TracerMiddleware
|
53
40
|
|
54
|
-
|
55
|
-
|
56
|
-
|
41
|
+
app.after do
|
42
|
+
configuration = Datadog.configuration[:sinatra]
|
43
|
+
next unless configuration[:tracer].enabled
|
57
44
|
|
58
|
-
|
45
|
+
# Ensures we only create a span for the top-most Sinatra middleware.
|
46
|
+
#
|
47
|
+
# If we traced all Sinatra middleware apps, we would have a chain
|
48
|
+
# of nested spans that were not responsible for handling this request,
|
49
|
+
# adding little value to users.
|
50
|
+
next if Sinatra::Env.middleware_traced?(env)
|
51
|
+
|
52
|
+
span = Sinatra::Env.datadog_span(env) || Sinatra::Tracer.create_middleware_span(env, configuration)
|
53
|
+
|
54
|
+
route = if defined?(@datadog_route)
|
55
|
+
@datadog_route
|
56
|
+
else
|
57
|
+
# Fallback in case no routes have matched
|
58
|
+
request.path
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
return unless Datadog.configuration[:sinatra][:tracer].enabled
|
61
|
+
span.resource = "#{request.request_method} #{route}"
|
62
62
|
|
63
|
-
span = Sinatra::Env.datadog_span(env)
|
64
63
|
span.set_tag(Datadog::Ext::HTTP::URL, request.path)
|
65
64
|
span.set_tag(Datadog::Ext::HTTP::METHOD, request.request_method)
|
65
|
+
span.set_tag(Ext::TAG_APP_NAME, app.settings.name)
|
66
|
+
span.set_tag(Ext::TAG_ROUTE_PATH, route)
|
67
|
+
if request.script_name && !request.script_name.empty?
|
68
|
+
span.set_tag(Ext::TAG_SCRIPT_NAME, request.script_name)
|
69
|
+
end
|
70
|
+
|
71
|
+
span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.status)
|
72
|
+
span.set_error(env['sinatra.error']) if response.server_error?
|
73
|
+
|
74
|
+
Sinatra::Env.set_middleware_traced(env, true)
|
66
75
|
end
|
76
|
+
end
|
67
77
|
|
68
|
-
|
69
|
-
|
78
|
+
# Initializes a span for the top-most Sinatra middleware.
|
79
|
+
def self.create_middleware_span(env, configuration)
|
80
|
+
tracer = configuration[:tracer]
|
81
|
+
span = tracer.trace(
|
82
|
+
Ext::SPAN_REQUEST,
|
83
|
+
service: configuration[:service_name],
|
84
|
+
span_type: Datadog::Ext::HTTP::TYPE_INBOUND,
|
85
|
+
start_time: Sinatra::Env.middleware_start_time(env)
|
86
|
+
)
|
87
|
+
|
88
|
+
Sinatra::Env.set_datadog_span(env, span)
|
89
|
+
span
|
90
|
+
end
|
91
|
+
|
92
|
+
# Method overrides for Sinatra::Base
|
93
|
+
module Base
|
94
|
+
def render(engine, data, *)
|
95
|
+
tracer = Datadog.configuration[:sinatra][:tracer]
|
96
|
+
return super unless tracer.enabled
|
97
|
+
|
98
|
+
tracer.trace(Ext::SPAN_RENDER_TEMPLATE, span_type: Datadog::Ext::HTTP::TEMPLATE) do |span|
|
99
|
+
span.set_tag(Ext::TAG_TEMPLATE_ENGINE, engine)
|
100
|
+
|
101
|
+
# If data is a string, it is a literal template and we don't
|
102
|
+
# want to record it.
|
103
|
+
span.set_tag(Ext::TAG_TEMPLATE_NAME, data) if data.is_a? Symbol
|
70
104
|
|
71
|
-
|
105
|
+
# Measure service stats
|
106
|
+
Contrib::Analytics.set_measured(span)
|
72
107
|
|
73
|
-
|
74
|
-
Datadog::Logger.log.error('missing request span in :after hook')
|
75
|
-
return
|
108
|
+
super
|
76
109
|
end
|
110
|
+
end
|
77
111
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
112
|
+
# Invoked when a matching route is found.
|
113
|
+
# This method yields directly to user code.
|
114
|
+
def route_eval
|
115
|
+
configuration = Datadog.configuration[:sinatra]
|
116
|
+
tracer = configuration[:tracer]
|
117
|
+
|
118
|
+
return super unless tracer.enabled
|
119
|
+
|
120
|
+
# For initialization of Sinatra middleware span in order
|
121
|
+
# guarantee that the Ext::SPAN_ROUTE span being created below
|
122
|
+
# has the middleware span as its parent.
|
123
|
+
Sinatra::Tracer.create_middleware_span(env, configuration) unless Sinatra::Env.datadog_span(env)
|
124
|
+
|
125
|
+
tracer.trace(
|
126
|
+
Ext::SPAN_ROUTE,
|
127
|
+
service: configuration[:service_name],
|
128
|
+
span_type: Datadog::Ext::HTTP::TYPE_INBOUND
|
129
|
+
) do |span|
|
130
|
+
span.resource = "#{request.request_method} #{@datadog_route}"
|
131
|
+
|
132
|
+
span.set_tag(Ext::TAG_APP_NAME, settings.name || settings.superclass.name)
|
133
|
+
span.set_tag(Ext::TAG_ROUTE_PATH, @datadog_route)
|
134
|
+
if request.script_name && !request.script_name.empty?
|
135
|
+
span.set_tag(Ext::TAG_SCRIPT_NAME, request.script_name)
|
136
|
+
end
|
137
|
+
|
138
|
+
rack_request_span = env[Datadog::Contrib::Rack::TraceMiddleware::RACK_REQUEST_SPAN]
|
139
|
+
rack_request_span.resource = span.resource if rack_request_span
|
140
|
+
|
141
|
+
Contrib::Analytics.set_measured(span)
|
142
|
+
|
143
|
+
super
|
144
|
+
end
|
82
145
|
end
|
83
146
|
end
|
84
147
|
end
|