ddtrace 0.12.0.beta2 → 0.12.0.rc1

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +8 -8
  3. data/CHANGELOG.md +293 -0
  4. data/README.md +11 -114
  5. data/Rakefile +26 -18
  6. data/docs/GettingStarted.md +704 -453
  7. data/gemfiles/contrib.gemfile +2 -2
  8. data/gemfiles/rails4_mysql2.gemfile +1 -1
  9. data/gemfiles/rails5_mysql2.gemfile +2 -2
  10. data/gemfiles/rails5_postgres.gemfile +1 -1
  11. data/gemfiles/rails5_postgres_redis.gemfile +1 -1
  12. data/gemfiles/rails5_postgres_sidekiq.gemfile +1 -1
  13. data/lib/ddtrace.rb +1 -0
  14. data/lib/ddtrace/context.rb +96 -34
  15. data/lib/ddtrace/context_flush.rb +132 -0
  16. data/lib/ddtrace/contrib/active_record/patcher.rb +55 -70
  17. data/lib/ddtrace/contrib/active_record/utils.rb +83 -0
  18. data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +66 -0
  19. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +155 -0
  20. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +6 -1
  21. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +89 -0
  22. data/lib/ddtrace/contrib/grape/endpoint.rb +1 -1
  23. data/lib/ddtrace/contrib/racecar/patcher.rb +43 -19
  24. data/lib/ddtrace/contrib/rack/middlewares.rb +58 -11
  25. data/lib/ddtrace/contrib/rack/patcher.rb +18 -11
  26. data/lib/ddtrace/contrib/rails/action_controller.rb +9 -11
  27. data/lib/ddtrace/contrib/rails/action_view.rb +5 -1
  28. data/lib/ddtrace/contrib/rails/active_support.rb +6 -2
  29. data/lib/ddtrace/contrib/rails/core_extensions.rb +280 -215
  30. data/lib/ddtrace/contrib/rails/framework.rb +38 -23
  31. data/lib/ddtrace/contrib/rails/middlewares.rb +7 -2
  32. data/lib/ddtrace/contrib/rails/patcher.rb +9 -6
  33. data/lib/ddtrace/contrib/rails/railtie.rb +4 -2
  34. data/lib/ddtrace/contrib/rails/utils.rb +9 -40
  35. data/lib/ddtrace/patcher.rb +32 -10
  36. data/lib/ddtrace/quantization/http.rb +86 -0
  37. data/lib/ddtrace/tracer.rb +29 -2
  38. data/lib/ddtrace/transport.rb +33 -20
  39. data/lib/ddtrace/version.rb +1 -1
  40. data/lib/ddtrace/writer.rb +11 -5
  41. metadata +8 -3
  42. data/lib/ddtrace/contrib/rails/active_record.rb +0 -80
@@ -13,13 +13,13 @@ gem "redis", "< 4.0"
13
13
  gem "hiredis"
14
14
  gem "sinatra"
15
15
  gem "sqlite3"
16
- gem "activerecord"
16
+ gem "activerecord", "< 5.1.5"
17
17
  gem "sidekiq"
18
18
  gem "aws-sdk"
19
19
  gem "sucker_punch"
20
20
  gem "dalli"
21
21
  gem "resque", "< 2.0"
22
22
  gem "racecar", ">= 0.3.5"
23
- gem "mysql2", platform: :ruby
23
+ gem "mysql2", "< 0.5", platform: :ruby
24
24
 
25
25
  gemspec path: "../"
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
6
  gem "rails", "4.2.7.1"
7
- gem "mysql2", platform: :ruby
7
+ gem "mysql2", "< 0.5", platform: :ruby
8
8
  gem "activerecord-jdbcmysql-adapter", platform: :jruby
9
9
 
10
10
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.0.1"
7
- gem "mysql2", platform: :ruby
6
+ gem "rails", "5.1.5"
7
+ gem "mysql2", "< 0.5", platform: :ruby
8
8
 
9
9
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.0.1"
6
+ gem "rails", "5.1.5"
7
7
  gem "pg", "< 1.0", platform: :ruby
8
8
 
9
9
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.0.1"
6
+ gem "rails", "5.1.5"
7
7
  gem "pg", "< 1.0", platform: :ruby
8
8
  gem "redis-rails"
9
9
  gem "redis"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "pry-nav", git: "https://github.com/nixme/pry-nav.git", branch: "master"
6
- gem "rails", "5.0.1"
6
+ gem "rails", "5.1.5"
7
7
  gem "pg", "< 1.0", platform: :ruby
8
8
  gem "sidekiq"
9
9
  gem "activejob"
@@ -4,6 +4,7 @@ require 'ddtrace/registry'
4
4
  require 'ddtrace/pin'
5
5
  require 'ddtrace/tracer'
6
6
  require 'ddtrace/error'
7
+ require 'ddtrace/quantization/http'
7
8
  require 'ddtrace/pipeline'
8
9
  require 'ddtrace/configuration'
9
10
  require 'ddtrace/patcher'
@@ -13,23 +13,22 @@ module Datadog
13
13
  # \Context, it will be related to the original trace.
14
14
  #
15
15
  # This data structure is thread-safe.
16
+ # rubocop:disable Metrics/ClassLength
16
17
  class Context
18
+ # 100k spans is about a 100Mb footprint
19
+ DEFAULT_MAX_LENGTH = 100_000
20
+
21
+ attr_reader :max_length
22
+
17
23
  # Initialize a new thread-safe \Context.
18
24
  def initialize(options = {})
19
25
  @mutex = Mutex.new
26
+ # max_length is the amount of spans above which, for a given trace,
27
+ # the context will simply drop and ignore spans, avoiding high memory usage.
28
+ @max_length = options.fetch(:max_length, DEFAULT_MAX_LENGTH)
20
29
  reset(options)
21
30
  end
22
31
 
23
- def reset(options = {})
24
- @trace = []
25
- @parent_trace_id = options.fetch(:trace_id, nil)
26
- @parent_span_id = options.fetch(:span_id, nil)
27
- @sampled = options.fetch(:sampled, false)
28
- @sampling_priority = options.fetch(:sampling_priority, nil)
29
- @finished_spans = 0
30
- @current_span = nil
31
- end
32
-
33
32
  def trace_id
34
33
  @mutex.synchronize do
35
34
  @parent_trace_id
@@ -64,20 +63,19 @@ module Datadog
64
63
  end
65
64
  end
66
65
 
67
- def set_current_span(span)
68
- @current_span = span
69
- if span
70
- @parent_trace_id = span.trace_id
71
- @parent_span_id = span.span_id
72
- @sampled = span.sampled
73
- else
74
- @parent_span_id = nil
75
- end
76
- end
77
-
78
66
  # Add a span to the context trace list, keeping it as the last active span.
79
67
  def add_span(span)
80
68
  @mutex.synchronize do
69
+ # If hitting the hard limit, just drop spans. This is really a rare case
70
+ # as it means despite the soft limit, the hard limit is reached, so the trace
71
+ # by default has 10000 spans, all of which belong to unfinished parts of a
72
+ # larger trace. This is a catch-all to reduce global memory usage.
73
+ if @max_length > 0 && @trace.length >= @max_length
74
+ Datadog::Tracer.log.debug("context full, ignoring span #{span.name}")
75
+ # Detach the span from any context, it's being dropped and ignored.
76
+ span.context = nil
77
+ return
78
+ end
81
79
  set_current_span(span)
82
80
  @trace << span
83
81
  span.context = self
@@ -105,12 +103,6 @@ module Datadog
105
103
  end
106
104
  end
107
105
 
108
- # Returns if the trace for the current Context is finished or not.
109
- # Low-level internal function, not thread-safe.
110
- def check_finished_spans
111
- @finished_spans > 0 && @trace.length == @finished_spans
112
- end
113
-
114
106
  # Returns if the trace for the current Context is finished or not. A \Context
115
107
  # is considered finished if all spans in this context are finished.
116
108
  def finished?
@@ -135,14 +127,16 @@ module Datadog
135
127
  # This operation is thread-safe.
136
128
  def get
137
129
  @mutex.synchronize do
138
- return nil, nil unless check_finished_spans
139
-
140
130
  trace = @trace
141
131
  sampled = @sampled
132
+
142
133
  attach_sampling_priority if sampled && @sampling_priority
143
134
 
135
+ # still return sampled attribute, even if context is not finished
136
+ return nil, sampled unless check_finished_spans()
137
+
144
138
  reset
145
- return trace, sampled
139
+ [trace, sampled]
146
140
  end
147
141
  end
148
142
 
@@ -154,6 +148,35 @@ module Datadog
154
148
  end
155
149
  end
156
150
 
151
+ private
152
+
153
+ def reset(options = {})
154
+ @trace = []
155
+ @parent_trace_id = options.fetch(:trace_id, nil)
156
+ @parent_span_id = options.fetch(:span_id, nil)
157
+ @sampled = options.fetch(:sampled, false)
158
+ @sampling_priority = options.fetch(:sampling_priority, nil)
159
+ @finished_spans = 0
160
+ @current_span = nil
161
+ end
162
+
163
+ def set_current_span(span)
164
+ @current_span = span
165
+ if span
166
+ @parent_trace_id = span.trace_id
167
+ @parent_span_id = span.span_id
168
+ @sampled = span.sampled
169
+ else
170
+ @parent_span_id = nil
171
+ end
172
+ end
173
+
174
+ # Returns if the trace for the current Context is finished or not.
175
+ # Low-level internal function, not thread-safe.
176
+ def check_finished_spans
177
+ @finished_spans > 0 && @trace.length == @finished_spans
178
+ end
179
+
157
180
  def attach_sampling_priority
158
181
  @trace.first.set_metric(
159
182
  Ext::DistributedTracing::SAMPLING_PRIORITY_KEY,
@@ -161,10 +184,49 @@ module Datadog
161
184
  )
162
185
  end
163
186
 
164
- private :reset
165
- private :check_finished_spans
166
- private :set_current_span
167
- private :attach_sampling_priority
187
+ # Return the start time of the root span, or nil if there are no spans or this is undefined.
188
+ def start_time
189
+ @mutex.synchronize do
190
+ return nil if @trace.empty?
191
+ @trace[0].start_time
192
+ end
193
+ end
194
+
195
+ # Return the length of the current trace held by this context.
196
+ def length
197
+ @mutex.synchronize do
198
+ @trace.length
199
+ end
200
+ end
201
+
202
+ # Iterate on each span within the trace. This is thread safe.
203
+ def each_span
204
+ @mutex.synchronize do
205
+ @trace.each do |span|
206
+ yield span
207
+ end
208
+ end
209
+ end
210
+
211
+ # Delete any span matching the condition. This is thread safe.
212
+ def delete_span_if
213
+ @mutex.synchronize do
214
+ @trace.delete_if do |span|
215
+ finished = span.finished?
216
+ delete_span = yield span
217
+ if delete_span
218
+ # We need to detach the span from the context, else, some code
219
+ # finishing it afterwards would mess up with the number of
220
+ # finished_spans and possibly cause other side effects.
221
+ span.context = nil
222
+ # Acknowledge there's one span less to finish, if needed.
223
+ # It's very important to keep this balanced.
224
+ @finished_spans -= 1 if finished
225
+ end
226
+ delete_span
227
+ end
228
+ end
229
+ end
168
230
  end
169
231
 
170
232
  # ThreadLocalContext can be used as a tracer global reference to create
@@ -0,0 +1,132 @@
1
+ require 'set'
2
+
3
+ require 'ddtrace/context'
4
+
5
+ module Datadog
6
+ # \ContextFlush is used to cap context size and avoid it using too much memory.
7
+ # It performs memory flushes when required.
8
+ class ContextFlush
9
+ # by default, soft and hard limits are the same
10
+ DEFAULT_MAX_SPANS_BEFORE_PARTIAL_FLUSH = Datadog::Context::DEFAULT_MAX_LENGTH
11
+ # by default, never do a partial flush
12
+ DEFAULT_MIN_SPANS_BEFORE_PARTIAL_FLUSH = Datadog::Context::DEFAULT_MAX_LENGTH
13
+ # timeout should be lower than the trace agent window
14
+ DEFAULT_PARTIAL_FLUSH_TIMEOUT = 10
15
+
16
+ private_constant :DEFAULT_MAX_SPANS_BEFORE_PARTIAL_FLUSH
17
+ private_constant :DEFAULT_MIN_SPANS_BEFORE_PARTIAL_FLUSH
18
+ private_constant :DEFAULT_PARTIAL_FLUSH_TIMEOUT
19
+
20
+ def initialize(options = {})
21
+ # max_spans_before_partial_flush is the amount of spans collected before
22
+ # the context starts to partially flush parts of traces. With a setting of 10k,
23
+ # the memory overhead is about 10Mb per thread/context (depends on spans metadata,
24
+ # this is just an order of magnitude).
25
+ @max_spans_before_partial_flush = options.fetch(:max_spans_before_partial_flush,
26
+ DEFAULT_MAX_SPANS_BEFORE_PARTIAL_FLUSH)
27
+ # min_spans_before_partial_flush is the minimum number of spans required
28
+ # for a partial flush to happen on a timeout. This is to prevent partial flush
29
+ # of traces which last a very long time but yet have few spans.
30
+ @min_spans_before_partial_flush = options.fetch(:min_spans_before_partial_flush,
31
+ DEFAULT_MIN_SPANS_BEFORE_PARTIAL_FLUSH)
32
+ # partial_flush_timeout is the limit (in seconds) above which the context
33
+ # considers flushing parts of the trace. Partial flushes should not be done too
34
+ # late else the agent rejects them with a "too far in the past" error.
35
+ @partial_flush_timeout = options.fetch(:partial_flush_timeout,
36
+ DEFAULT_PARTIAL_FLUSH_TIMEOUT)
37
+ @partial_traces = []
38
+ end
39
+
40
+ def add_children(m, spans, ids, leaf)
41
+ spans << leaf
42
+ ids.add(leaf.span_id)
43
+
44
+ if m[leaf.span_id]
45
+ m[leaf.span_id].each do |sub|
46
+ add_children(m, spans, ids, sub)
47
+ end
48
+ end
49
+ end
50
+
51
+ def partial_traces(context)
52
+ # 1st step, taint all parents of an unfinished span as unflushable
53
+ unflushable_ids = Set.new
54
+
55
+ context.send(:each_span) do |span|
56
+ next if span.finished? || unflushable_ids.include?(span.span_id)
57
+ unflushable_ids.add span.span_id
58
+ while span.parent
59
+ span = span.parent
60
+ unflushable_ids.add span.span_id
61
+ end
62
+ end
63
+
64
+ # 2nd step, find all spans which are at the border between flushable and unflushable
65
+ # Along the road, collect a reverse-tree which allows direct walking from parents to
66
+ # children but only for the ones we're interested it.
67
+ roots = []
68
+ children_map = {}
69
+ context.send(:each_span) do |span|
70
+ # There's no point in trying to put the real root in those partial roots, if
71
+ # it's flushable, the default algorithm would figure way more quickly.
72
+ if span.parent && !unflushable_ids.include?(span.span_id)
73
+ if unflushable_ids.include?(span.parent.span_id)
74
+ # span is flushable but is parent is not
75
+ roots << span
76
+ else
77
+ # span is flushable and its parent is too, build the reverse
78
+ # parent to child map for this one, it will be useful
79
+ children_map[span.parent.span_id] ||= []
80
+ children_map[span.parent.span_id] << span
81
+ end
82
+ end
83
+ end
84
+
85
+ # 3rd step, find all children, as this can be costly, only perform it for partial roots
86
+ partial_traces = []
87
+ all_ids = Set.new
88
+ roots.each do |root|
89
+ spans = []
90
+ add_children(children_map, spans, all_ids, root)
91
+ partial_traces << spans
92
+ end
93
+
94
+ return [nil, nil] if partial_traces.empty?
95
+ [partial_traces, all_ids]
96
+ end
97
+
98
+ def partial_flush(context)
99
+ traces, flushed_ids = partial_traces(context)
100
+ return nil unless traces && flushed_ids
101
+
102
+ # We need to reject by span ID and not by value, because a span
103
+ # value may be altered (typical example: it's finished by some other thread)
104
+ # since we lock only the context, not all the spans which belong to it.
105
+ context.send(:delete_span_if) { |span| flushed_ids.include? span.span_id }
106
+ traces
107
+ end
108
+
109
+ # Performs an operation which each partial trace it can get from the context.
110
+ def each_partial_trace(context)
111
+ start_time = context.send(:start_time)
112
+ length = context.send(:length)
113
+ # Stop and do not flush anything if there are not enough spans.
114
+ return if length <= @min_spans_before_partial_flush
115
+ # If there are enough spans, but not too many, check for start time.
116
+ # If timeout is not given or 0, then wait
117
+ return if length <= @max_spans_before_partial_flush &&
118
+ (@partial_flush_timeout.nil? || @partial_flush_timeout <= 0 ||
119
+ (start_time && start_time > Time.now.utc - @partial_flush_timeout))
120
+ # Here, either the trace is old or we have too many spans, flush it.
121
+ traces = partial_flush(context)
122
+ return unless traces
123
+ traces.each do |trace|
124
+ yield trace
125
+ end
126
+ end
127
+
128
+ private :add_children
129
+ private :partial_traces
130
+ private :partial_flush
131
+ end
132
+ end
@@ -1,5 +1,7 @@
1
1
  require 'ddtrace/ext/sql'
2
2
  require 'ddtrace/ext/app_types'
3
+ require 'ddtrace/contrib/active_record/utils'
4
+ require 'ddtrace/contrib/active_support/notifications/subscriber'
3
5
 
4
6
  module Datadog
5
7
  module Contrib
@@ -7,15 +9,51 @@ module Datadog
7
9
  # Patcher enables patching of 'active_record' module.
8
10
  module Patcher
9
11
  include Base
12
+ include ActiveSupport::Notifications::Subscriber
13
+
14
+ NAME_SQL = 'sql.active_record'.freeze
15
+ NAME_INSTANTIATION = 'instantiation.active_record'.freeze
16
+
10
17
  register_as :active_record, auto_patch: false
11
- option :service_name do |value|
12
- value.tap { @database_service_name = nil }
18
+ option :service_name, depends_on: [:tracer] do |value|
19
+ (value || Utils.adapter_name).tap do |v|
20
+ get_option(:tracer).set_service_info(v, 'active_record', Ext::AppTypes::DB)
21
+ end
13
22
  end
14
23
  option :orm_service_name
15
- option :tracer, default: Datadog.tracer
24
+ option :tracer, default: Datadog.tracer do |value|
25
+ (value || Datadog.tracer).tap do |v|
26
+ # Make sure to update tracers of all subscriptions
27
+ subscriptions.each do |subscription|
28
+ subscription.tracer = v
29
+ end
30
+ end
31
+ end
16
32
 
17
33
  @patched = false
18
34
 
35
+ on_subscribe do
36
+ # sql.active_record
37
+ subscribe(
38
+ self::NAME_SQL, # Event name
39
+ 'active_record.sql', # Span name
40
+ { service: get_option(:service_name) }, # Span options
41
+ get_option(:tracer), # Tracer
42
+ &method(:sql) # Handler
43
+ )
44
+
45
+ # instantiation.active_record
46
+ if instantiation_tracing_supported?
47
+ subscribe(
48
+ self::NAME_INSTANTIATION, # Event name
49
+ 'active_record.instantiation', # Span name
50
+ { service: get_option(:service_name) }, # Span options
51
+ get_option(:tracer), # Tracer
52
+ &method(:instantiation) # Handler
53
+ )
54
+ end
55
+ end
56
+
19
57
  module_function
20
58
 
21
59
  # patched? tells whether patch has been successfully applied
@@ -26,9 +64,7 @@ module Datadog
26
64
  def patch
27
65
  if !@patched && defined?(::ActiveRecord)
28
66
  begin
29
- require 'ddtrace/contrib/rails/utils'
30
-
31
- patch_active_record
67
+ subscribe!
32
68
  @patched = true
33
69
  rescue StandardError => e
34
70
  Datadog::Tracer.log.error("Unable to apply Active Record integration: #{e}")
@@ -38,84 +74,33 @@ module Datadog
38
74
  @patched
39
75
  end
40
76
 
41
- def patch_active_record
42
- # subscribe when the active record query has been processed
43
- ::ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
44
- sql(*args)
45
- end
46
-
47
- if instantiation_tracing_supported?
48
- # subscribe when the active record instantiates objects
49
- ::ActiveSupport::Notifications.subscribe('instantiation.active_record') do |*args|
50
- instantiation(*args)
51
- end
52
- end
53
- end
54
-
55
77
  def instantiation_tracing_supported?
56
78
  Gem.loaded_specs['activerecord'] \
57
79
  && Gem.loaded_specs['activerecord'].version >= Gem::Version.new('4.2')
58
80
  end
59
81
 
60
- # NOTE: Resolve this here instead of in the option defaults,
61
- # because resolving adapter name as a default causes ActiveRecord to connect,
62
- # which isn't a good idea at initialization time.
63
- def self.database_service_name
64
- @database_service_name ||= (get_option(:service_name) || adapter_name).tap do |name|
65
- get_option(:tracer).set_service_info(name, 'active_record', Ext::AppTypes::DB)
66
- end
67
- end
68
-
69
- def self.adapter_name
70
- @adapter_name ||= Datadog::Contrib::Rails::Utils.adapter_name
71
- end
72
-
73
- def self.database_name
74
- @database_name ||= Datadog::Contrib::Rails::Utils.database_name
75
- end
76
-
77
- def self.adapter_host
78
- @adapter_host ||= Datadog::Contrib::Rails::Utils.adapter_host
79
- end
80
-
81
- def self.adapter_port
82
- @adapter_port ||= Datadog::Contrib::Rails::Utils.adapter_port
83
- end
84
-
85
- def self.sql(_name, start, finish, _id, payload)
86
- span = get_option(:tracer).trace(
87
- "#{adapter_name}.query",
88
- resource: payload.fetch(:sql),
89
- service: database_service_name,
90
- span_type: Datadog::Ext::SQL::TYPE
91
- )
82
+ def sql(span, event, _id, payload)
83
+ connection_config = Utils.connection_config(payload[:connection_id])
84
+ span.name = "#{connection_config[:adapter_name]}.query"
85
+ span.service = get_option(:service_name)
86
+ span.resource = payload.fetch(:sql)
87
+ span.span_type = Datadog::Ext::SQL::TYPE
92
88
 
93
89
  # Find out if the SQL query has been cached in this request. This meta is really
94
90
  # helpful to users because some spans may have 0ns of duration because the query
95
91
  # is simply cached from memory, so the notification is fired with start == finish.
96
92
  cached = payload[:cached] || (payload[:name] == 'CACHE')
97
93
 
98
- # the span should have the query ONLY in the Resource attribute,
99
- # so that the ``sql.query`` tag will be set in the agent with an
100
- # obfuscated version
101
- span.set_tag('active_record.db.vendor', adapter_name)
102
- span.set_tag('active_record.db.name', database_name)
94
+ span.set_tag('active_record.db.vendor', connection_config[:adapter_name])
95
+ span.set_tag('active_record.db.name', connection_config[:database_name])
103
96
  span.set_tag('active_record.db.cached', cached) if cached
104
- span.set_tag('out.host', adapter_host)
105
- span.set_tag('out.port', adapter_port)
106
- span.start_time = start
107
- span.finish(finish)
97
+ span.set_tag('out.host', connection_config[:adapter_host])
98
+ span.set_tag('out.port', connection_config[:adapter_port])
108
99
  rescue StandardError => e
109
100
  Datadog::Tracer.log.debug(e.message)
110
101
  end
111
102
 
112
- def self.instantiation(_name, start, finish, _id, payload)
113
- span = get_option(:tracer).trace(
114
- 'active_record.instantiation',
115
- resource: payload.fetch(:class_name),
116
- span_type: 'custom'
117
- )
118
-
103
+ def instantiation(span, event, _id, payload)
119
104
  # Inherit service name from parent, if available.
120
105
  span.service = if get_option(:orm_service_name)
121
106
  get_option(:orm_service_name)
@@ -125,10 +110,10 @@ module Datadog
125
110
  'active_record'
126
111
  end
127
112
 
113
+ span.resource = payload.fetch(:class_name)
114
+ span.span_type = 'custom'
128
115
  span.set_tag('active_record.instantiation.class_name', payload.fetch(:class_name))
129
116
  span.set_tag('active_record.instantiation.record_count', payload.fetch(:record_count))
130
- span.start_time = start
131
- span.finish(finish)
132
117
  rescue StandardError => e
133
118
  Datadog::Tracer.log.debug(e.message)
134
119
  end