ddtrace 0.12.0.beta2 → 0.12.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Appraisals +8 -8
- data/CHANGELOG.md +293 -0
- data/README.md +11 -114
- data/Rakefile +26 -18
- data/docs/GettingStarted.md +704 -453
- data/gemfiles/contrib.gemfile +2 -2
- data/gemfiles/rails4_mysql2.gemfile +1 -1
- data/gemfiles/rails5_mysql2.gemfile +2 -2
- data/gemfiles/rails5_postgres.gemfile +1 -1
- data/gemfiles/rails5_postgres_redis.gemfile +1 -1
- data/gemfiles/rails5_postgres_sidekiq.gemfile +1 -1
- data/lib/ddtrace.rb +1 -0
- data/lib/ddtrace/context.rb +96 -34
- data/lib/ddtrace/context_flush.rb +132 -0
- data/lib/ddtrace/contrib/active_record/patcher.rb +55 -70
- data/lib/ddtrace/contrib/active_record/utils.rb +83 -0
- data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +66 -0
- data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +155 -0
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/ddtrace/contrib/elasticsearch/quantize.rb +89 -0
- data/lib/ddtrace/contrib/grape/endpoint.rb +1 -1
- data/lib/ddtrace/contrib/racecar/patcher.rb +43 -19
- data/lib/ddtrace/contrib/rack/middlewares.rb +58 -11
- data/lib/ddtrace/contrib/rack/patcher.rb +18 -11
- data/lib/ddtrace/contrib/rails/action_controller.rb +9 -11
- data/lib/ddtrace/contrib/rails/action_view.rb +5 -1
- data/lib/ddtrace/contrib/rails/active_support.rb +6 -2
- data/lib/ddtrace/contrib/rails/core_extensions.rb +280 -215
- data/lib/ddtrace/contrib/rails/framework.rb +38 -23
- data/lib/ddtrace/contrib/rails/middlewares.rb +7 -2
- data/lib/ddtrace/contrib/rails/patcher.rb +9 -6
- data/lib/ddtrace/contrib/rails/railtie.rb +4 -2
- data/lib/ddtrace/contrib/rails/utils.rb +9 -40
- data/lib/ddtrace/patcher.rb +32 -10
- data/lib/ddtrace/quantization/http.rb +86 -0
- data/lib/ddtrace/tracer.rb +29 -2
- data/lib/ddtrace/transport.rb +33 -20
- data/lib/ddtrace/version.rb +1 -1
- data/lib/ddtrace/writer.rb +11 -5
- metadata +8 -3
- data/lib/ddtrace/contrib/rails/active_record.rb +0 -80
@@ -0,0 +1,83 @@
|
|
1
|
+
module Datadog
|
2
|
+
module Contrib
|
3
|
+
module ActiveRecord
|
4
|
+
# Common utilities for Rails
|
5
|
+
module Utils
|
6
|
+
# Return a canonical name for a type of database
|
7
|
+
def self.normalize_vendor(vendor)
|
8
|
+
case vendor
|
9
|
+
when nil
|
10
|
+
'defaultdb'
|
11
|
+
when 'postgresql'
|
12
|
+
'postgres'
|
13
|
+
when 'sqlite3'
|
14
|
+
'sqlite'
|
15
|
+
else
|
16
|
+
vendor
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.adapter_name
|
21
|
+
connection_config[:adapter_name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.database_name
|
25
|
+
connection_config[:database_name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.adapter_host
|
29
|
+
connection_config[:adapter_host]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.adapter_port
|
33
|
+
connection_config[:adapter_port]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.connection_config(object_id = nil)
|
37
|
+
config = object_id.nil? ? default_connection_config : connection_config_by_id(object_id)
|
38
|
+
{
|
39
|
+
adapter_name: normalize_vendor(config[:adapter]),
|
40
|
+
adapter_host: config[:host],
|
41
|
+
adapter_port: config[:port],
|
42
|
+
database_name: config[:database]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Attempt to retrieve the connection from an object ID.
|
47
|
+
def self.connection_by_id(object_id)
|
48
|
+
return nil if object_id.nil?
|
49
|
+
ObjectSpace._id2ref(object_id)
|
50
|
+
rescue StandardError
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# Attempt to retrieve the connection config from an object ID.
|
55
|
+
# Typical of ActiveSupport::Notifications `sql.active_record`
|
56
|
+
def self.connection_config_by_id(object_id)
|
57
|
+
connection = connection_by_id(object_id)
|
58
|
+
return {} if connection.nil?
|
59
|
+
|
60
|
+
if connection.instance_variable_defined?(:@config)
|
61
|
+
connection.instance_variable_get(:@config)
|
62
|
+
else
|
63
|
+
{}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.default_connection_config
|
68
|
+
return @default_connection_config if instance_variable_defined?(:@default_connection_config)
|
69
|
+
current_connection_name = if ::ActiveRecord::Base.respond_to?(:connection_specification_name)
|
70
|
+
::ActiveRecord::Base.connection_specification_name
|
71
|
+
else
|
72
|
+
::ActiveRecord::Base
|
73
|
+
end
|
74
|
+
|
75
|
+
connection_pool = ::ActiveRecord::Base.connection_handler.retrieve_connection_pool(current_connection_name)
|
76
|
+
connection_pool.nil? ? {} : (@default_connection_config = connection_pool.spec.config)
|
77
|
+
rescue StandardError
|
78
|
+
{}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'ddtrace/contrib/active_support/notifications/subscription'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module Contrib
|
6
|
+
module ActiveSupport
|
7
|
+
module Notifications
|
8
|
+
# For classes that listen to ActiveSupport::Notification events.
|
9
|
+
# Creates subscriptions that are wrapped with tracing.
|
10
|
+
module Subscriber
|
11
|
+
def self.included(base)
|
12
|
+
base.send(:extend, ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Class methods that are implemented in the inheriting class.
|
16
|
+
module ClassMethods
|
17
|
+
# Returns a list of subscriptions created for this class.
|
18
|
+
def subscriptions
|
19
|
+
@subscriptions ||= Set.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns whether subscriptions have been activated, via #subscribe!
|
23
|
+
def subscribed?
|
24
|
+
subscribed == true
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
# Defines a callback for when subscribe! is called.
|
30
|
+
# Should contain subscription setup, defined by the inheriting class.
|
31
|
+
def on_subscribe(&block)
|
32
|
+
@on_subscribe_block = block
|
33
|
+
end
|
34
|
+
|
35
|
+
# Runs the on_subscribe callback once, to activate subscriptions.
|
36
|
+
# Should be triggered by the inheriting class.
|
37
|
+
def subscribe!
|
38
|
+
return subscribed? if subscribed? || on_subscribe_block.nil?
|
39
|
+
on_subscribe_block.call
|
40
|
+
@subscribed = true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Creates a subscription and immediately activates it.
|
44
|
+
def subscribe(pattern, span_name, options = {}, tracer = Datadog.tracer, &block)
|
45
|
+
subscription(span_name, options, tracer, &block).tap do |subscription|
|
46
|
+
subscription.subscribe(pattern)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates a subscription without activating it.
|
51
|
+
# Subscription is added to the inheriting class' list of subscriptions.
|
52
|
+
def subscription(span_name, options = {}, tracer = Datadog.tracer, &block)
|
53
|
+
Subscription.new(tracer, span_name, options, &block).tap do |subscription|
|
54
|
+
subscriptions << subscription
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
attr_reader :subscribed, :on_subscribe_block
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Datadog
|
2
|
+
module Contrib
|
3
|
+
module ActiveSupport
|
4
|
+
module Notifications
|
5
|
+
# An ActiveSupport::Notification subscription that wraps events with tracing.
|
6
|
+
class Subscription
|
7
|
+
attr_accessor \
|
8
|
+
:tracer,
|
9
|
+
:span_name,
|
10
|
+
:options
|
11
|
+
|
12
|
+
def initialize(tracer, span_name, options, &block)
|
13
|
+
raise ArgumentError, 'Must be given a block!' unless block_given?
|
14
|
+
@tracer = tracer
|
15
|
+
@span_name = span_name
|
16
|
+
@options = options
|
17
|
+
@handler = Handler.new(&block)
|
18
|
+
@callbacks = Callbacks.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# ActiveSupport 3.x calls this
|
22
|
+
def call(name, start, finish, id, payload)
|
23
|
+
start_span(name, id, payload, start)
|
24
|
+
finish_span(name, id, payload, finish)
|
25
|
+
end
|
26
|
+
|
27
|
+
# ActiveSupport 4+ calls this on start
|
28
|
+
def start(name, id, payload)
|
29
|
+
start_span(name, id, payload)
|
30
|
+
end
|
31
|
+
|
32
|
+
# ActiveSupport 4+ calls this on finish
|
33
|
+
def finish(name, id, payload)
|
34
|
+
finish_span(name, id, payload)
|
35
|
+
end
|
36
|
+
|
37
|
+
def before_trace(&block)
|
38
|
+
callbacks.add(:before_trace, &block) if block_given?
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_trace(&block)
|
42
|
+
callbacks.add(:after_trace, &block) if block_given?
|
43
|
+
end
|
44
|
+
|
45
|
+
def subscribe(pattern)
|
46
|
+
return false if subscribers.key?(pattern)
|
47
|
+
subscribers[pattern] = ::ActiveSupport::Notifications.subscribe(pattern, self)
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def unsubscribe(pattern)
|
52
|
+
return false unless subscribers.key?(pattern)
|
53
|
+
::ActiveSupport::Notifications.unsubscribe(subscribers[pattern])
|
54
|
+
subscribers.delete(pattern)
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def unsubscribe_all
|
59
|
+
return false if subscribers.empty?
|
60
|
+
subscribers.keys.each { |pattern| unsubscribe(pattern) }
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
attr_reader \
|
67
|
+
:handler,
|
68
|
+
:callbacks
|
69
|
+
|
70
|
+
def start_span(name, id, payload, start = nil)
|
71
|
+
# Run callbacks
|
72
|
+
callbacks.run(name, :before_trace, id, payload, start)
|
73
|
+
|
74
|
+
# Start a trace
|
75
|
+
tracer.trace(@span_name, @options).tap do |span|
|
76
|
+
# Assign start time if provided
|
77
|
+
span.start_time = start unless start.nil?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def finish_span(name, id, payload, finish = nil)
|
82
|
+
tracer.active_span.tap do |span|
|
83
|
+
# If no active span, return.
|
84
|
+
return nil if span.nil?
|
85
|
+
|
86
|
+
# Run handler for event
|
87
|
+
handler.run(span, name, id, payload)
|
88
|
+
|
89
|
+
# Finish the span
|
90
|
+
span.finish(finish)
|
91
|
+
|
92
|
+
# Run callbacks
|
93
|
+
callbacks.run(name, :after_trace, span, id, payload, finish)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Pattern => ActiveSupport:Notifications::Subscribers
|
98
|
+
def subscribers
|
99
|
+
@subscribers ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Wrapper for subscription handler
|
103
|
+
class Handler
|
104
|
+
attr_reader :block
|
105
|
+
|
106
|
+
def initialize(&block)
|
107
|
+
@block = block
|
108
|
+
end
|
109
|
+
|
110
|
+
def run(span, name, id, payload)
|
111
|
+
run!(span, name, id, payload)
|
112
|
+
rescue StandardError => e
|
113
|
+
Datadog::Tracer.log.debug("ActiveSupport::Notifications handler for '#{name}' failed: #{e.message}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def run!(*args)
|
117
|
+
@block.call(*args)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Wrapper for subscription callbacks
|
122
|
+
class Callbacks
|
123
|
+
attr_reader :blocks
|
124
|
+
|
125
|
+
def initialize
|
126
|
+
@blocks = {}
|
127
|
+
end
|
128
|
+
|
129
|
+
def add(key, &block)
|
130
|
+
blocks_for(key) << block if block_given?
|
131
|
+
end
|
132
|
+
|
133
|
+
def run(event, key, *args)
|
134
|
+
blocks_for(key).each do |callback|
|
135
|
+
begin
|
136
|
+
callback.call(event, key, *args)
|
137
|
+
rescue StandardError => e
|
138
|
+
Datadog::Tracer.log.debug(
|
139
|
+
"ActiveSupport::Notifications '#{key}' callback for '#{event}' failed: #{e.message}"
|
140
|
+
)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def blocks_for(key)
|
148
|
+
blocks[key] ||= []
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -15,6 +15,7 @@ module Datadog
|
|
15
15
|
include Base
|
16
16
|
register_as :elasticsearch, auto_patch: true
|
17
17
|
option :service_name, default: SERVICE
|
18
|
+
option :quantize, default: {}
|
18
19
|
|
19
20
|
@patched = false
|
20
21
|
|
@@ -89,7 +90,11 @@ module Datadog
|
|
89
90
|
span.set_tag(METHOD, method)
|
90
91
|
span.set_tag(URL, url)
|
91
92
|
span.set_tag(PARAMS, params) if params
|
92
|
-
|
93
|
+
if body
|
94
|
+
quantize_options = Datadog.configuration[:elasticsearch][:quantize]
|
95
|
+
quantized_body = Datadog::Contrib::Elasticsearch::Quantize.format_body(body, quantize_options)
|
96
|
+
span.set_tag(BODY, quantized_body)
|
97
|
+
end
|
93
98
|
span.set_tag('out.host', host) if host
|
94
99
|
span.set_tag('out.port', port) if port
|
95
100
|
|
@@ -3,6 +3,11 @@ module Datadog
|
|
3
3
|
module Elasticsearch
|
4
4
|
# Quantize contains ES-specific resource quantization tools.
|
5
5
|
module Quantize
|
6
|
+
PLACEHOLDER = '?'.freeze
|
7
|
+
EXCLUDE_KEYS = [].freeze
|
8
|
+
SHOW_KEYS = [:_index, :_type, :_id].freeze
|
9
|
+
DEFAULT_OPTIONS = { exclude: EXCLUDE_KEYS, show: SHOW_KEYS }.freeze
|
10
|
+
|
6
11
|
ID_REGEXP = %r{\/([0-9]+)([\/\?]|$)}
|
7
12
|
ID_PLACEHOLDER = '/?\2'.freeze
|
8
13
|
|
@@ -16,6 +21,90 @@ module Datadog
|
|
16
21
|
quantized_url = url.gsub(ID_REGEXP, ID_PLACEHOLDER)
|
17
22
|
quantized_url.gsub(INDEX_REGEXP, INDEX_PLACEHOLDER)
|
18
23
|
end
|
24
|
+
|
25
|
+
def format_body(body, options = {})
|
26
|
+
format_body!(body, options)
|
27
|
+
rescue StandardError
|
28
|
+
PLACEHOLDER
|
29
|
+
end
|
30
|
+
|
31
|
+
def format_body!(body, options = {})
|
32
|
+
options = merge_options(DEFAULT_OPTIONS, options)
|
33
|
+
|
34
|
+
# Determine if bulk query or not, based on content
|
35
|
+
statements = body.end_with?("\n") ? body.split("\n") : [body]
|
36
|
+
|
37
|
+
# Parse each statement and quantize them.
|
38
|
+
statements.collect do |string|
|
39
|
+
reserialize_json(string) do |obj|
|
40
|
+
format_statement(obj, options)
|
41
|
+
end
|
42
|
+
end.join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
def format_statement(statement, options = {})
|
46
|
+
return statement if options[:show] == :all
|
47
|
+
|
48
|
+
case statement
|
49
|
+
when Hash
|
50
|
+
statement.each_with_object({}) do |(key, value), quantized|
|
51
|
+
if options[:show].include?(key.to_sym)
|
52
|
+
quantized[key] = value
|
53
|
+
elsif !options[:exclude].include?(key.to_sym)
|
54
|
+
quantized[key] = format_value(value, options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
format_value(statement, options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def format_value(value, options = {})
|
63
|
+
return value if options[:show] == :all
|
64
|
+
|
65
|
+
case value
|
66
|
+
when Hash
|
67
|
+
format_statement(value, options)
|
68
|
+
when Array
|
69
|
+
# If any are objects, format them.
|
70
|
+
if value.any? { |v| v.class <= Hash || v.class <= Array }
|
71
|
+
value.collect { |i| format_value(i, options) }
|
72
|
+
# Otherwise short-circuit and return single placeholder
|
73
|
+
else
|
74
|
+
PLACEHOLDER
|
75
|
+
end
|
76
|
+
else
|
77
|
+
PLACEHOLDER
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def merge_options(original, additional)
|
82
|
+
{}.tap do |options|
|
83
|
+
# Show
|
84
|
+
# If either is :all, value becomes :all
|
85
|
+
options[:show] = if original[:show] == :all || additional[:show] == :all
|
86
|
+
:all
|
87
|
+
else
|
88
|
+
(original[:show] || []).dup.concat(additional[:show] || []).uniq
|
89
|
+
end
|
90
|
+
|
91
|
+
# Exclude
|
92
|
+
options[:exclude] = (original[:exclude] || []).dup.concat(additional[:exclude] || []).uniq
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Parses a JSON object from a string, passes its value
|
97
|
+
# to the block provided, and dumps its result back to JSON.
|
98
|
+
# If JSON parsing fails, it prints fail_value.
|
99
|
+
def reserialize_json(string, fail_value = PLACEHOLDER)
|
100
|
+
return string unless block_given?
|
101
|
+
begin
|
102
|
+
JSON.dump(yield(JSON.parse(string)))
|
103
|
+
rescue JSON::ParserError
|
104
|
+
# If it can't parse/dump, don't raise an error.
|
105
|
+
fail_value
|
106
|
+
end
|
107
|
+
end
|
19
108
|
end
|
20
109
|
end
|
21
110
|
end
|
@@ -71,7 +71,7 @@ module Datadog
|
|
71
71
|
span.resource = resource
|
72
72
|
|
73
73
|
# set the request span resource if it's a `rack.request` span
|
74
|
-
request_span = payload[:env][
|
74
|
+
request_span = payload[:env][Datadog::Contrib::Rack::TraceMiddleware::RACK_REQUEST_SPAN]
|
75
75
|
if !request_span.nil? && request_span.name == 'rack.request'
|
76
76
|
request_span.resource = resource
|
77
77
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ddtrace/ext/app_types'
|
2
|
+
require 'ddtrace/contrib/active_support/notifications/subscriber'
|
2
3
|
|
3
4
|
module Datadog
|
4
5
|
module Contrib
|
@@ -6,19 +7,50 @@ module Datadog
|
|
6
7
|
# Provides instrumentation for `racecar` through ActiveSupport instrumentation signals
|
7
8
|
module Patcher
|
8
9
|
include Base
|
10
|
+
include ActiveSupport::Notifications::Subscriber
|
11
|
+
|
9
12
|
NAME_MESSAGE = 'racecar.message'.freeze
|
10
13
|
NAME_BATCH = 'racecar.batch'.freeze
|
11
14
|
register_as :racecar
|
12
|
-
option :tracer, default: Datadog.tracer
|
13
15
|
option :service_name, default: 'racecar'
|
16
|
+
option :tracer, default: Datadog.tracer do |value|
|
17
|
+
(value || Datadog.tracer).tap do |v|
|
18
|
+
# Make sure to update tracers of all subscriptions
|
19
|
+
subscriptions.each do |subscription|
|
20
|
+
subscription.tracer = v
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
on_subscribe do
|
26
|
+
# Subscribe to single messages
|
27
|
+
subscription(
|
28
|
+
self::NAME_MESSAGE,
|
29
|
+
{ service: configuration[:service_name] },
|
30
|
+
configuration[:tracer],
|
31
|
+
&method(:process)
|
32
|
+
).tap do |subscription|
|
33
|
+
subscription.before_trace { ensure_clean_context! }
|
34
|
+
subscription.subscribe('process_message.racecar')
|
35
|
+
end
|
36
|
+
|
37
|
+
# Subscribe to batch messages
|
38
|
+
subscription(
|
39
|
+
self::NAME_BATCH,
|
40
|
+
{ service: configuration[:service_name] },
|
41
|
+
configuration[:tracer],
|
42
|
+
&method(:process)
|
43
|
+
).tap do |subscription|
|
44
|
+
subscription.before_trace { ensure_clean_context! }
|
45
|
+
subscription.subscribe('process_batch.racecar')
|
46
|
+
end
|
47
|
+
end
|
14
48
|
|
15
49
|
class << self
|
16
50
|
def patch
|
17
51
|
return patched? if patched? || !compatible?
|
18
52
|
|
19
|
-
|
20
|
-
::ActiveSupport::Notifications.subscribe('process_message.racecar', self)
|
21
|
-
|
53
|
+
subscribe!
|
22
54
|
configuration[:tracer].set_service_info(
|
23
55
|
configuration[:service_name],
|
24
56
|
'racecar',
|
@@ -33,28 +65,17 @@ module Datadog
|
|
33
65
|
@patched = false
|
34
66
|
end
|
35
67
|
|
36
|
-
def
|
37
|
-
ensure_clean_context!
|
38
|
-
|
39
|
-
name = event[/message/] ? NAME_MESSAGE : NAME_BATCH
|
40
|
-
span = configuration[:tracer].trace(name)
|
68
|
+
def process(span, event, _, payload)
|
41
69
|
span.service = configuration[:service_name]
|
42
70
|
span.resource = payload[:consumer_class]
|
71
|
+
|
43
72
|
span.set_tag('kafka.topic', payload[:topic])
|
44
73
|
span.set_tag('kafka.consumer', payload[:consumer_class])
|
45
74
|
span.set_tag('kafka.partition', payload[:partition])
|
46
75
|
span.set_tag('kafka.offset', payload[:offset]) if payload.key?(:offset)
|
47
76
|
span.set_tag('kafka.first_offset', payload[:first_offset]) if payload.key?(:first_offset)
|
48
77
|
span.set_tag('kafka.message_count', payload[:message_count]) if payload.key?(:message_count)
|
49
|
-
|
50
|
-
|
51
|
-
def finish(_, _, payload)
|
52
|
-
current_span = configuration[:tracer].call_context.current_span
|
53
|
-
|
54
|
-
return unless current_span
|
55
|
-
|
56
|
-
current_span.set_error(payload[:exception_object]) if payload[:exception_object]
|
57
|
-
current_span.finish
|
78
|
+
span.set_error(payload[:exception_object]) if payload[:exception_object]
|
58
79
|
end
|
59
80
|
|
60
81
|
private
|
@@ -67,9 +88,12 @@ module Datadog
|
|
67
88
|
defined?(::Racecar) && defined?(::ActiveSupport::Notifications)
|
68
89
|
end
|
69
90
|
|
91
|
+
# Context objects are thread-bound.
|
92
|
+
# If Racecar re-uses threads, context from a previous trace
|
93
|
+
# could leak into the new trace. This "cleans" current context,
|
94
|
+
# preventing such a leak.
|
70
95
|
def ensure_clean_context!
|
71
96
|
return unless configuration[:tracer].call_context.current_span
|
72
|
-
|
73
97
|
configuration[:tracer].provider.context = Context.new
|
74
98
|
end
|
75
99
|
end
|