instana 0.15.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Troubleshooting.md +32 -0
- data/lib/instana/agent.rb +1 -1
- data/lib/instana/instrumentation/excon.rb +3 -2
- data/lib/instana/instrumentation/net-http.rb +3 -2
- data/lib/instana/instrumentation/rack.rb +4 -4
- data/lib/instana/logger.rb +10 -4
- data/lib/instana/opentracing/carrier.rb +4 -0
- data/lib/instana/opentracing/tracer.rb +18 -0
- data/lib/instana/setup.rb +3 -0
- data/lib/instana/tracer.rb +107 -68
- data/lib/instana/tracing/processor.rb +5 -6
- data/lib/instana/tracing/span.rb +322 -2
- data/lib/instana/tracing/span_context.rb +31 -0
- data/lib/instana/tracing/trace.rb +51 -190
- data/lib/instana/util.rb +77 -0
- data/lib/instana/version.rb +1 -1
- data/lib/opentracing.rb +6 -0
- metadata +8 -3
@@ -147,21 +147,20 @@ module Instana
|
|
147
147
|
# are traces that have completed but may have outstanding
|
148
148
|
# asynchronous spans.
|
149
149
|
#
|
150
|
-
# @param
|
151
|
-
# :trace_id => 12345
|
152
|
-
# :span_id => 12345
|
150
|
+
# @param trace_id [Integer] the Trace ID to be searched for
|
153
151
|
#
|
154
|
-
def staged_trace(
|
152
|
+
def staged_trace(trace_id)
|
155
153
|
candidate = nil
|
156
154
|
@staging_lock.synchronize {
|
157
155
|
@staging_queue.each do |trace|
|
158
|
-
if trace.id ==
|
156
|
+
if trace.id == trace_id
|
159
157
|
candidate = trace
|
158
|
+
break
|
160
159
|
end
|
161
160
|
end
|
162
161
|
}
|
163
162
|
unless candidate
|
164
|
-
::Instana.logger.trace("Couldn't find staged trace with trace_id: #{
|
163
|
+
::Instana.logger.trace("Couldn't find staged trace with trace_id: #{trace_id}")
|
165
164
|
end
|
166
165
|
candidate
|
167
166
|
end
|
data/lib/instana/tracing/span.rb
CHANGED
@@ -1,19 +1,187 @@
|
|
1
1
|
module Instana
|
2
2
|
class Span
|
3
|
+
REGISTERED_SPANS = [ :rack, :'net-http', :excon ].freeze
|
4
|
+
ENTRY_SPANS = [ :rack ].freeze
|
5
|
+
EXIT_SPANS = [ :'net-http', :excon ].freeze
|
6
|
+
HTTP_SPANS = ENTRY_SPANS + EXIT_SPANS
|
7
|
+
|
3
8
|
attr_accessor :parent
|
9
|
+
attr_accessor :baggage
|
10
|
+
|
11
|
+
def initialize(name, trace_id, parent_id: nil, start_time: Time.now)
|
12
|
+
@data = {}
|
13
|
+
@data[:t] = trace_id # Trace ID
|
14
|
+
@data[:s] = ::Instana::Util.generate_id # Span ID
|
15
|
+
@data[:p] = parent_id if parent_id # Parent ID
|
16
|
+
@data[:ta] = :ruby # Agent
|
17
|
+
@data[:data] = {}
|
18
|
+
|
19
|
+
# Entity Source
|
20
|
+
@data[:f] = { :e => ::Instana.agent.report_pid,
|
21
|
+
:h => ::Instana.agent.agent_uuid }
|
22
|
+
# Start time
|
23
|
+
@data[:ts] = ::Instana::Util.time_to_ms(start_time)
|
24
|
+
|
25
|
+
@baggage = {}
|
26
|
+
|
27
|
+
# For entry spans, add a backtrace fingerprint
|
28
|
+
add_stack(limit: 2) if ENTRY_SPANS.include?(name)
|
29
|
+
|
30
|
+
# Attach a backtrace to all exit spans
|
31
|
+
add_stack if EXIT_SPANS.include?(name)
|
32
|
+
|
33
|
+
# Check for custom tracing
|
34
|
+
if REGISTERED_SPANS.include?(name.to_sym)
|
35
|
+
@data[:n] = name.to_sym
|
36
|
+
else
|
37
|
+
configure_custom(name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Adds a backtrace to this span
|
42
|
+
#
|
43
|
+
# @param limit [Integer] Limit the backtrace to the top <limit> frames
|
44
|
+
#
|
45
|
+
def add_stack(limit: nil, stack: Kernel.caller)
|
46
|
+
frame_count = 0
|
47
|
+
@data[:stack] = []
|
48
|
+
|
49
|
+
stack.each do |i|
|
50
|
+
# If the stack has the full instana gem version in it's path
|
51
|
+
# then don't include that frame. Also don't exclude the Rack module.
|
52
|
+
if !i.match(/instana\/instrumentation\/rack.rb/).nil? ||
|
53
|
+
(i.match(::Instana::VERSION_FULL).nil? && i.match('lib/instana/').nil?)
|
54
|
+
|
55
|
+
break if limit && frame_count >= limit
|
56
|
+
|
57
|
+
x = i.split(':')
|
58
|
+
|
59
|
+
@data[:stack] << {
|
60
|
+
:f => x[0],
|
61
|
+
:n => x[1],
|
62
|
+
:m => x[2]
|
63
|
+
}
|
64
|
+
frame_count = frame_count + 1 if limit
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Log an error into the span
|
70
|
+
#
|
71
|
+
# @param e [Exception] The exception to be logged
|
72
|
+
#
|
73
|
+
def add_error(e)
|
74
|
+
@data[:error] = true
|
75
|
+
|
76
|
+
if @data.key?(:ec)
|
77
|
+
@data[:ec] = @data[:ec] + 1
|
78
|
+
else
|
79
|
+
@data[:ec] = 1
|
80
|
+
end
|
81
|
+
|
82
|
+
# If a valid exception has been passed in, log the information about it
|
83
|
+
# In case of just logging an error for things such as HTTP client 5xx
|
84
|
+
# responses, an exception/backtrace may not exist.
|
85
|
+
if e
|
86
|
+
if e.backtrace.is_a?(Array)
|
87
|
+
add_stack(stack: e.backtrace)
|
88
|
+
end
|
89
|
+
|
90
|
+
if HTTP_SPANS.include?(@data[:n])
|
91
|
+
set_tags(:http => { :error => "#{e.class}: #{e.message}" })
|
92
|
+
else
|
93
|
+
set_tags(:log => { :message => e.message, :parameters => e.class })
|
94
|
+
end
|
95
|
+
e.instance_variable_set(:@instana_logged, true)
|
96
|
+
end
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Configure this span to be a custom span per the
|
102
|
+
# SDK generic span type.
|
103
|
+
#
|
104
|
+
# @param name [String] name of the span
|
105
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
106
|
+
#
|
107
|
+
def configure_custom(name)
|
108
|
+
@data[:n] = :sdk
|
109
|
+
@data[:data] = { :sdk => { :name => name.to_sym } }
|
4
110
|
|
5
|
-
|
6
|
-
@data =
|
111
|
+
#if kvs.is_a?(Hash)
|
112
|
+
# @data[:data][:sdk][:type] = kvs.key?(:type) ? kvs[:type] : :local
|
113
|
+
#
|
114
|
+
# if kvs.key?(:arguments)
|
115
|
+
# @data[:data][:sdk][:arguments] = kvs[:arguments]
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# if kvs.key?(:return)
|
119
|
+
# @data[:data][:sdk][:return] = kvs[:return]
|
120
|
+
# end
|
121
|
+
# @data[:data][:sdk][:custom] = kvs unless kvs.empty?
|
122
|
+
# end
|
123
|
+
self
|
7
124
|
end
|
8
125
|
|
126
|
+
# Closes out the span. This difference between this and
|
127
|
+
# the finish method tells us how the tracing is being
|
128
|
+
# performed (with OpenTracing or Instana default)
|
129
|
+
#
|
130
|
+
# @param end_time [Time] custom end time, if not now
|
131
|
+
# @return [Span]
|
132
|
+
#
|
133
|
+
def close(end_time = Time.now)
|
134
|
+
unless end_time.is_a?(Time)
|
135
|
+
::Instana.logger.debug "span.close: Passed #{end_time.class} instead of Time class"
|
136
|
+
end
|
137
|
+
|
138
|
+
@data[:d] = (::Instana::Util.time_to_ms(end_time) - @data[:ts])
|
139
|
+
self
|
140
|
+
end
|
141
|
+
|
142
|
+
#############################################################
|
143
|
+
# Accessors
|
144
|
+
#############################################################
|
145
|
+
|
146
|
+
# Retrieve the context of this span.
|
147
|
+
#
|
148
|
+
# @return [Instana::SpanContext]
|
149
|
+
#
|
150
|
+
def context
|
151
|
+
@context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @baggage)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Retrieve the ID for this span
|
155
|
+
#
|
156
|
+
# @return [Integer] the span ID
|
9
157
|
def id
|
10
158
|
@data[:s]
|
11
159
|
end
|
12
160
|
|
161
|
+
# Retrieve the Trace ID for this span
|
162
|
+
#
|
163
|
+
# @return [Integer] the Trace ID
|
164
|
+
def trace_id
|
165
|
+
@data[:t]
|
166
|
+
end
|
167
|
+
|
168
|
+
# Retrieve the parent ID of this span
|
169
|
+
#
|
170
|
+
# @return [Integer] parent span ID
|
13
171
|
def parent_id
|
14
172
|
@data[:p]
|
15
173
|
end
|
16
174
|
|
175
|
+
# Set the parent ID of this span
|
176
|
+
#
|
177
|
+
# @return [Integer] parent span ID
|
178
|
+
def parent_id=(id)
|
179
|
+
@data[:p] = id
|
180
|
+
end
|
181
|
+
|
182
|
+
# Get the name (operation) of this Span
|
183
|
+
#
|
184
|
+
# @return [String] or [Symbol] representing the span name
|
17
185
|
def name
|
18
186
|
if custom?
|
19
187
|
@data[:data][:sdk][:name]
|
@@ -22,32 +190,184 @@ module Instana
|
|
22
190
|
end
|
23
191
|
end
|
24
192
|
|
193
|
+
# Set the name (operation) for this Span
|
194
|
+
#
|
195
|
+
# @params name [String] or [Symbol]
|
196
|
+
#
|
197
|
+
def name=(n)
|
198
|
+
if custom?
|
199
|
+
@data[:data][:sdk][:name] = n
|
200
|
+
else
|
201
|
+
@data[:n] = n
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Get the duration value for this Span
|
206
|
+
#
|
207
|
+
# @return [Integer] the duration in milliseconds
|
25
208
|
def duration
|
26
209
|
@data[:d]
|
27
210
|
end
|
28
211
|
|
212
|
+
# Indicates whether this span in the root span
|
213
|
+
# in the Trace
|
214
|
+
#
|
215
|
+
# @return [Boolean]
|
216
|
+
#
|
29
217
|
def is_root?
|
30
218
|
@data[:s] == @data[:t]
|
31
219
|
end
|
32
220
|
|
221
|
+
# Hash accessor to the internal @data hash
|
222
|
+
#
|
33
223
|
def [](key)
|
34
224
|
@data[key.to_sym]
|
35
225
|
end
|
36
226
|
|
227
|
+
# Hash setter to the internal @data hash
|
228
|
+
#
|
37
229
|
def []=(key, value)
|
38
230
|
@data[key.to_sym] = value
|
39
231
|
end
|
40
232
|
|
233
|
+
# Hash key query to the internal @data hash
|
234
|
+
#
|
41
235
|
def key?(k)
|
42
236
|
@data.key?(k.to_sym)
|
43
237
|
end
|
44
238
|
|
239
|
+
# Get the raw @data hash that summarizes this span
|
240
|
+
#
|
45
241
|
def raw
|
46
242
|
@data
|
47
243
|
end
|
48
244
|
|
245
|
+
# Indicates whether this span is a custom or registered Span
|
49
246
|
def custom?
|
50
247
|
@data[:n] == :sdk
|
51
248
|
end
|
249
|
+
|
250
|
+
#############################################################
|
251
|
+
# OpenTracing Compatibility Methods
|
252
|
+
#############################################################
|
253
|
+
|
254
|
+
# Set the name of the operation
|
255
|
+
# Spec: OpenTracing API
|
256
|
+
#
|
257
|
+
# @params name [String] or [Symbol]
|
258
|
+
#
|
259
|
+
def operation_name=(name)
|
260
|
+
@data[:n] = name
|
261
|
+
end
|
262
|
+
|
263
|
+
# Set a tag value on this span
|
264
|
+
# Spec: OpenTracing API
|
265
|
+
#
|
266
|
+
# @param key [String] the key of the tag
|
267
|
+
# @param value [String, Numeric, Boolean] the value of the tag. If it's not
|
268
|
+
# a String, Numeric, or Boolean it will be encoded with to_s
|
269
|
+
#
|
270
|
+
def set_tag(key, value)
|
271
|
+
if custom?
|
272
|
+
@data[:data][:sdk][:custom] ||= {}
|
273
|
+
@data[:data][:sdk][:custom][key] = value
|
274
|
+
else
|
275
|
+
if !@data[:data].key?(key)
|
276
|
+
@data[:data][key] = value
|
277
|
+
elsif value.is_a?(Hash) && self[:data][key].is_a?(Hash)
|
278
|
+
@data[:data][key].merge!(value)
|
279
|
+
else
|
280
|
+
@data[:data][key] = value
|
281
|
+
end
|
282
|
+
end
|
283
|
+
self
|
284
|
+
end
|
285
|
+
|
286
|
+
# Helper method to add multiple tags to this span
|
287
|
+
#
|
288
|
+
# @params tags [Hash]
|
289
|
+
# @return [Span]
|
290
|
+
#
|
291
|
+
def set_tags(tags)
|
292
|
+
return unless tags.is_a?(Hash)
|
293
|
+
tags.each do |k,v|
|
294
|
+
set_tag(k, v)
|
295
|
+
end
|
296
|
+
self
|
297
|
+
end
|
298
|
+
|
299
|
+
# Set a baggage item on the span
|
300
|
+
# Spec: OpenTracing API
|
301
|
+
#
|
302
|
+
# @param key [String] the key of the baggage item
|
303
|
+
# @param value [String] the value of the baggage item
|
304
|
+
def set_baggage_item(key, value)
|
305
|
+
@baggage ||= {}
|
306
|
+
@baggage[key] = value
|
307
|
+
|
308
|
+
# Init/Update the SpanContext item
|
309
|
+
if @context
|
310
|
+
@context.baggage = @baggage
|
311
|
+
else
|
312
|
+
@context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @baggage)
|
313
|
+
end
|
314
|
+
self
|
315
|
+
end
|
316
|
+
|
317
|
+
# Get a baggage item
|
318
|
+
# Spec: OpenTracing API
|
319
|
+
#
|
320
|
+
# @param key [String] the key of the baggage item
|
321
|
+
# @return Value of the baggage item
|
322
|
+
#
|
323
|
+
def get_baggage_item(key)
|
324
|
+
@baggage[key]
|
325
|
+
end
|
326
|
+
|
327
|
+
# Retrieve the hash of tags for this span
|
328
|
+
#
|
329
|
+
def tags(key = nil)
|
330
|
+
if custom?
|
331
|
+
tags = @data[:data][:sdk][:custom]
|
332
|
+
else
|
333
|
+
tags = @data[:data][key]
|
334
|
+
end
|
335
|
+
key ? tags[key] : tags
|
336
|
+
end
|
337
|
+
|
338
|
+
# Add a log entry to this span
|
339
|
+
# Spec: OpenTracing API
|
340
|
+
#
|
341
|
+
# @param event [String] event name for the log
|
342
|
+
# @param timestamp [Time] time of the log
|
343
|
+
# @param fields [Hash] Additional information to log
|
344
|
+
#
|
345
|
+
def log(event = nil, _timestamp = Time.now, **fields)
|
346
|
+
set_tags(:log => { :message => event, :parameters => fields })
|
347
|
+
end
|
348
|
+
|
349
|
+
# Finish the {Span}
|
350
|
+
# Spec: OpenTracing API
|
351
|
+
#
|
352
|
+
# @param end_time [Time] custom end time, if not now
|
353
|
+
#
|
354
|
+
def finish(end_time = Time.now)
|
355
|
+
unless end_time.is_a?(Time)
|
356
|
+
::Instana.logger.debug "span.finish: Passed #{end_time.class} instead of Time class"
|
357
|
+
end
|
358
|
+
|
359
|
+
if ::Instana.tracer.current_span.id != id
|
360
|
+
::Instana.logger.tracing "Closing a span that isn't active. This will result in a broken trace: #{self.inspect}"
|
361
|
+
end
|
362
|
+
|
363
|
+
if is_root?
|
364
|
+
# This is the root span for the trace. Call log_end to close
|
365
|
+
# out and queue the trace
|
366
|
+
::Instana.tracer.log_end(name, {}, end_time)
|
367
|
+
else
|
368
|
+
::Instana.tracer.current_trace.end_span({}, end_time)
|
369
|
+
end
|
370
|
+
self
|
371
|
+
end
|
52
372
|
end
|
53
373
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Instana
|
2
|
+
class SpanContext
|
3
|
+
attr_accessor :trace_id
|
4
|
+
attr_accessor :span_id
|
5
|
+
attr_accessor :baggage
|
6
|
+
|
7
|
+
# Create a new SpanContext
|
8
|
+
#
|
9
|
+
# @param tid [Integer] the trace ID
|
10
|
+
# @param sid [Integer] the span ID
|
11
|
+
# @param baggage [Hash] baggage applied to this trace
|
12
|
+
#
|
13
|
+
def initialize(tid, sid, baggage = nil)
|
14
|
+
@trace_id = tid
|
15
|
+
@span_id = sid
|
16
|
+
@baggage = baggage
|
17
|
+
end
|
18
|
+
|
19
|
+
def trace_id_header
|
20
|
+
::Instana::Util.id_to_header(@trace_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def span_id_header
|
24
|
+
::Instana::Util.id_to_header(@span_id)
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hash
|
28
|
+
{ :trace_id => @trace_id, :span_id => @span_id }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,10 +1,5 @@
|
|
1
1
|
module Instana
|
2
2
|
class Trace
|
3
|
-
REGISTERED_SPANS = [ :rack, :'net-http', :excon ].freeze
|
4
|
-
ENTRY_SPANS = [ :rack ].freeze
|
5
|
-
EXIT_SPANS = [ :'net-http', :excon ].freeze
|
6
|
-
HTTP_SPANS = ENTRY_SPANS + EXIT_SPANS
|
7
|
-
|
8
3
|
# @return [Integer] the ID for this trace
|
9
4
|
attr_reader :id
|
10
5
|
|
@@ -22,13 +17,13 @@ module Instana
|
|
22
17
|
# :span_id the ID of the parent span (must be an unsigned hex-string)
|
23
18
|
# :level specifies data collection level (optional)
|
24
19
|
#
|
25
|
-
def initialize(name, kvs =
|
20
|
+
def initialize(name, kvs = nil, incoming_context = {}, start_time = Time.now)
|
26
21
|
# The collection of spans that make
|
27
22
|
# up this trace.
|
28
23
|
@spans = Set.new
|
29
24
|
|
30
25
|
# Generate a random 64bit ID for this trace
|
31
|
-
@id = generate_id
|
26
|
+
@id = ::Instana::Util.generate_id
|
32
27
|
|
33
28
|
# Indicates the time when this trace was started. Used to timeout
|
34
29
|
# traces that have asynchronous spans that never close out.
|
@@ -39,29 +34,14 @@ module Instana
|
|
39
34
|
|
40
35
|
# This is a new trace so open the first span with the proper
|
41
36
|
# root span IDs.
|
42
|
-
@current_span = Span.new(
|
43
|
-
|
44
|
-
:ts => ts_now, # Timestamp
|
45
|
-
:ta => :ruby, # Agent
|
46
|
-
:f => { :e => ::Instana.agent.report_pid, :h => ::Instana.agent.agent_uuid } # Entity Source
|
47
|
-
})
|
48
|
-
|
49
|
-
# For entry spans, add a backtrace fingerprint
|
50
|
-
add_stack(2) if ENTRY_SPANS.include?(name)
|
51
|
-
|
52
|
-
# Check for custom tracing
|
53
|
-
if !REGISTERED_SPANS.include?(name.to_sym)
|
54
|
-
configure_custom_span(nil, name, kvs)
|
55
|
-
else
|
56
|
-
@current_span[:n] = name.to_sym
|
57
|
-
@current_span[:data] = kvs
|
58
|
-
end
|
37
|
+
@current_span = Span.new(name, @id, start_time: start_time)
|
38
|
+
@current_span.set_tags(kvs) if kvs
|
59
39
|
|
60
40
|
# Handle potential incoming context
|
61
|
-
if incoming_context.empty?
|
41
|
+
if !incoming_context || incoming_context.empty?
|
62
42
|
# No incoming context. Set trace ID the same
|
63
43
|
# as this first span.
|
64
|
-
@current_span[:
|
44
|
+
@current_span[:s] = @id
|
65
45
|
else
|
66
46
|
@id = incoming_context[:trace_id]
|
67
47
|
@current_span[:t] = incoming_context[:trace_id]
|
@@ -76,32 +56,22 @@ module Instana
|
|
76
56
|
# @param name [String] the name of the span to start
|
77
57
|
# @param kvs [Hash] list of key values to be reported in the span
|
78
58
|
#
|
79
|
-
def new_span(name, kvs =
|
59
|
+
def new_span(name, kvs = nil, start_time = Time.now, child_of = nil)
|
80
60
|
return unless @current_span
|
81
61
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
:ts => ts_now, # Timestamp
|
87
|
-
:ta => :ruby, # Agent
|
88
|
-
:f => { :e => Process.pid, :h => :agent_id } # Entity Source
|
89
|
-
})
|
90
|
-
|
91
|
-
new_span.parent = @current_span
|
92
|
-
@spans.add(new_span)
|
93
|
-
@current_span = new_span
|
94
|
-
|
95
|
-
# Check for custom tracing
|
96
|
-
if !REGISTERED_SPANS.include?(name.to_sym)
|
97
|
-
configure_custom_span(nil, name, kvs)
|
62
|
+
if child_of && child_of.is_a?(::Instana::Span)
|
63
|
+
new_span = Span.new(name, @id, parent_id: child_of.id, start_time: start_time)
|
64
|
+
new_span.parent = child_of
|
65
|
+
new_span.baggage = child_of.baggage.dup
|
98
66
|
else
|
99
|
-
@current_span
|
100
|
-
|
67
|
+
new_span = Span.new(name, @id, parent_id: @current_span.id, start_time: start_time)
|
68
|
+
new_span.parent = @current_span
|
69
|
+
new_span.baggage = @current_span.baggage.dup
|
101
70
|
end
|
71
|
+
new_span.set_tags(kvs) if kvs
|
102
72
|
|
103
|
-
|
104
|
-
|
73
|
+
@spans.add(new_span)
|
74
|
+
@current_span = new_span
|
105
75
|
end
|
106
76
|
|
107
77
|
# Add KVs to the current span
|
@@ -139,33 +109,8 @@ module Instana
|
|
139
109
|
# Return if we've already logged this exception and it
|
140
110
|
# is just propogating up the spans.
|
141
111
|
return if e && e.instance_variable_get(:@instana_logged)
|
142
|
-
|
143
112
|
span ||= @current_span
|
144
|
-
|
145
|
-
span[:error] = true
|
146
|
-
|
147
|
-
if span.key?(:ec)
|
148
|
-
span[:ec] = span[:ec] + 1
|
149
|
-
else
|
150
|
-
span[:ec] = 1
|
151
|
-
end
|
152
|
-
|
153
|
-
# If a valid exception has been passed in, log the information about it
|
154
|
-
# In case of just logging an error for things such as HTTP client 5xx
|
155
|
-
# responses, an exception/backtrace may not exist.
|
156
|
-
if e
|
157
|
-
if e.backtrace.is_a?(Array)
|
158
|
-
add_backtrace_to_span(e.backtrace, nil, span)
|
159
|
-
end
|
160
|
-
|
161
|
-
if HTTP_SPANS.include?(span.name)
|
162
|
-
add_info(:http => { :error => "#{e.class}: #{e.message}" })
|
163
|
-
else
|
164
|
-
add_info(:log => { :message => e.message, :parameters => e.class })
|
165
|
-
end
|
166
|
-
e.instance_variable_set(:@instana_logged, true)
|
167
|
-
end
|
168
|
-
|
113
|
+
span.add_error(e)
|
169
114
|
end
|
170
115
|
|
171
116
|
# Close out the current span and set the parent as
|
@@ -173,20 +118,20 @@ module Instana
|
|
173
118
|
#
|
174
119
|
# @param kvs [Hash] list of key values to be reported in the span
|
175
120
|
#
|
176
|
-
def end_span(kvs = {})
|
177
|
-
@current_span
|
121
|
+
def end_span(kvs = {}, end_time = Time.now)
|
122
|
+
@current_span.close(end_time)
|
178
123
|
add_info(kvs) if kvs && !kvs.empty?
|
179
124
|
@current_span = @current_span.parent unless @current_span.is_root?
|
180
125
|
end
|
181
126
|
|
182
127
|
# Closes out the final span in this trace and runs any finalizer
|
183
128
|
# steps required.
|
184
|
-
# This should be called only on the root span to end the trace.
|
129
|
+
# This should be called only when on the root span to end the trace.
|
185
130
|
#
|
186
131
|
# @param kvs [Hash] list of key values to be reported in the span
|
187
132
|
#
|
188
|
-
def finish(kvs = {})
|
189
|
-
end_span(kvs)
|
133
|
+
def finish(kvs = {}, end_time = Time.now)
|
134
|
+
end_span(kvs, end_time)
|
190
135
|
end
|
191
136
|
|
192
137
|
###########################################################################
|
@@ -202,77 +147,47 @@ module Instana
|
|
202
147
|
# @param name [String] the name of the span to start
|
203
148
|
# @param kvs [Hash] list of key values to be reported in the span
|
204
149
|
#
|
205
|
-
def new_async_span(name, kvs)
|
206
|
-
|
207
|
-
new_span
|
208
|
-
:s => generate_id, # Span ID
|
209
|
-
:t => @id, # Trace ID (same as :s for root span)
|
210
|
-
:p => @current_span.id, # Parent ID
|
211
|
-
:ts => ts_now, # Timestamp
|
212
|
-
:ta => :ruby, # Agent
|
213
|
-
:async => true, # Asynchonous
|
214
|
-
:f => { :e => Process.pid, :h => :agent_id } # Entity Source
|
215
|
-
})
|
216
|
-
|
150
|
+
def new_async_span(name, kvs = {})
|
151
|
+
new_span = Span.new(name, @id, parent_id: @current_span.id)
|
152
|
+
new_span.set_tags(kvs) unless kvs.empty?
|
217
153
|
new_span.parent = @current_span
|
218
|
-
@has_async = true
|
219
|
-
|
220
|
-
# Check for custom tracing
|
221
|
-
if !REGISTERED_SPANS.include?(name.to_sym)
|
222
|
-
configure_custom_span(new_span, name, kvs)
|
223
|
-
else
|
224
|
-
new_span[:n] = name.to_sym
|
225
|
-
new_span[:data] = kvs
|
226
|
-
end
|
227
|
-
|
228
|
-
# Attach a backtrace to all exit spans
|
229
|
-
add_stack(nil, new_span) if EXIT_SPANS.include?(name)
|
154
|
+
new_span[:async] = @has_async = true
|
230
155
|
|
231
156
|
# Add the new span to the span collection
|
232
157
|
@spans.add(new_span)
|
233
|
-
|
234
|
-
{ :trace_id => new_span[:t], :span_id => new_span.id }
|
158
|
+
new_span
|
235
159
|
end
|
236
160
|
|
237
161
|
# Log info into an asynchronous span
|
238
162
|
#
|
239
163
|
# @param kvs [Hash] list of key values to be reported in the span
|
240
|
-
# @param span [Span] the span
|
164
|
+
# @param span [Span] the span of this Async op (previously returned
|
165
|
+
# from `log_async_entry`)
|
241
166
|
#
|
242
|
-
def add_async_info(kvs,
|
243
|
-
|
244
|
-
if span.id == ids[:span_id]
|
245
|
-
add_info(kvs, span)
|
246
|
-
end
|
247
|
-
end
|
167
|
+
def add_async_info(kvs, span)
|
168
|
+
span.set_tags(kvs)
|
248
169
|
end
|
249
170
|
|
250
171
|
# Log an error into an asynchronous span
|
251
172
|
#
|
252
|
-
# @param span [Span] the span to configure
|
253
173
|
# @param e [Exception] Add exception to the current span
|
174
|
+
# @param span [Span] the span of this Async op (previously returned
|
175
|
+
# from `log_async_entry`)
|
254
176
|
#
|
255
|
-
def add_async_error(e,
|
256
|
-
|
257
|
-
add_error(e, span) if span.id == ids[:span_id]
|
258
|
-
end
|
177
|
+
def add_async_error(e, span)
|
178
|
+
span.add_error(e)
|
259
179
|
end
|
260
180
|
|
261
181
|
# End an asynchronous span
|
262
182
|
#
|
263
183
|
# @param name [Symbol] the name of the span
|
264
184
|
# @param kvs [Hash] list of key values to be reported in the span
|
265
|
-
# @param
|
266
|
-
#
|
267
|
-
# :span_id => 12345
|
185
|
+
# @param span [Span] the span of this Async op (previously returned
|
186
|
+
# from `log_async_entry`)
|
268
187
|
#
|
269
|
-
def end_async_span(kvs = {},
|
270
|
-
|
271
|
-
|
272
|
-
span[:d] = ts_now - span[:ts]
|
273
|
-
add_info(kvs, span) unless kvs.empty?
|
274
|
-
end
|
275
|
-
end
|
188
|
+
def end_async_span(kvs = {}, span)
|
189
|
+
span.set_tags(kvs) unless kvs.empty?
|
190
|
+
span.close
|
276
191
|
end
|
277
192
|
|
278
193
|
###########################################################################
|
@@ -290,6 +205,7 @@ module Instana
|
|
290
205
|
return false
|
291
206
|
end
|
292
207
|
end
|
208
|
+
true
|
293
209
|
end
|
294
210
|
|
295
211
|
# Indicates if every span of this trace has completed. Useful when
|
@@ -327,6 +243,14 @@ module Instana
|
|
327
243
|
false
|
328
244
|
end
|
329
245
|
|
246
|
+
# Get the current span.
|
247
|
+
#
|
248
|
+
# @return [Span]
|
249
|
+
#
|
250
|
+
def current_span
|
251
|
+
@current_span
|
252
|
+
end
|
253
|
+
|
330
254
|
# Get the ID of the current span for this trace.
|
331
255
|
# Used often to place in HTTP response headers.
|
332
256
|
#
|
@@ -379,53 +303,7 @@ module Instana
|
|
379
303
|
#
|
380
304
|
def configure_custom_span(span, name, kvs = {})
|
381
305
|
span ||= @current_span
|
382
|
-
|
383
|
-
span[:n] = :sdk
|
384
|
-
span[:data] = { :sdk => { :name => name.to_sym } }
|
385
|
-
span[:data][:sdk][:type] = kvs.key?(:type) ? kvs[:type] : :local
|
386
|
-
|
387
|
-
if kvs.key?(:arguments)
|
388
|
-
span[:data][:sdk][:arguments] = kvs[:arguments]
|
389
|
-
end
|
390
|
-
|
391
|
-
if kvs.key?(:return)
|
392
|
-
span[:data][:sdk][:return] = kvs[:return]
|
393
|
-
end
|
394
|
-
span[:data][:sdk][:custom] = kvs unless kvs.empty?
|
395
|
-
#span[:data][:sdk][:custom][:tags] = {}
|
396
|
-
#span[:data][:sdk][:custom][:logs] = {}
|
397
|
-
end
|
398
|
-
|
399
|
-
# Locates the span in the current_trace or
|
400
|
-
# in the staging queue. This is generally used by async
|
401
|
-
# operations.
|
402
|
-
#
|
403
|
-
# @param ids [Hash] the Trace ID and Span ID in the form of
|
404
|
-
# :trace_id => 12345
|
405
|
-
# :span_id => 12345
|
406
|
-
#
|
407
|
-
# @return [Span]
|
408
|
-
#
|
409
|
-
def find_span(ids)
|
410
|
-
if ids[:trace_id] == @id
|
411
|
-
@spans.each do |s|
|
412
|
-
return s if s[:s] == ids[:span_id]
|
413
|
-
end
|
414
|
-
else
|
415
|
-
#::Instana.processor.staged_trace(
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
# Adds a backtrace to the passed in span or on @current_span if not.
|
420
|
-
#
|
421
|
-
# @param limit [Integer] Limit the backtrace to the top <limit> frames
|
422
|
-
# @param span [Span] the span to add the backtrace to or if unspecified
|
423
|
-
# the current span
|
424
|
-
#
|
425
|
-
def add_stack(limit = nil, span = nil)
|
426
|
-
span ||= @current_span
|
427
|
-
|
428
|
-
add_backtrace_to_span(Kernel.caller, limit, span)
|
306
|
+
span.configure_custom(name, kvs)
|
429
307
|
end
|
430
308
|
|
431
309
|
# Adds the passed in backtrace to the specified span. Backtrace can be one
|
@@ -459,22 +337,5 @@ module Instana
|
|
459
337
|
end
|
460
338
|
end
|
461
339
|
end
|
462
|
-
|
463
|
-
# Get the current time in milliseconds
|
464
|
-
#
|
465
|
-
# @return [Integer] the current time in milliseconds
|
466
|
-
#
|
467
|
-
def ts_now
|
468
|
-
(Time.now.to_f * 1000).floor
|
469
|
-
end
|
470
|
-
|
471
|
-
# Generate a random 64bit ID
|
472
|
-
#
|
473
|
-
# @return [Integer] a random 64bit integer
|
474
|
-
#
|
475
|
-
def generate_id
|
476
|
-
# Max value is 9223372036854775807 (signed long in Java)
|
477
|
-
rand(-2**63..2**63-1)
|
478
|
-
end
|
479
340
|
end
|
480
341
|
end
|