instana 1.9.7 → 1.10.0.slimfast
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/instana/agent.rb +19 -19
- data/lib/instana/agent/helpers.rb +2 -2
- data/lib/instana/agent/tasks.rb +2 -2
- data/lib/instana/collectors/gc.rb +1 -1
- data/lib/instana/collectors/memory.rb +1 -1
- data/lib/instana/collectors/thread.rb +1 -1
- data/lib/instana/frameworks/instrumentation/mysql2_adapter.rb +1 -1
- data/lib/instana/frameworks/instrumentation/mysql_adapter.rb +1 -1
- data/lib/instana/helpers.rb +2 -2
- data/lib/instana/instrumentation.rb +1 -1
- data/lib/instana/instrumentation/excon.rb +8 -5
- data/lib/instana/instrumentation/rack.rb +2 -2
- data/lib/instana/instrumentation/resque.rb +3 -3
- data/lib/instana/tracer.rb +92 -117
- data/lib/instana/tracing/processor.rb +18 -133
- data/lib/instana/tracing/span.rb +40 -35
- data/lib/instana/tracing/span_context.rb +3 -1
- data/lib/instana/util.rb +5 -5
- data/lib/instana/version.rb +1 -1
- data/lib/opentracing.rb +1 -1
- data/test/frameworks/rack_test.rb +6 -11
- data/test/frameworks/rails/actioncontroller_test.rb +32 -62
- data/test/frameworks/rails/actionview5_test.rb +91 -132
- data/test/frameworks/rails/activerecord5_test.rb +14 -17
- data/test/instrumentation/dalli_test.rb +51 -72
- data/test/instrumentation/excon_test.rb +70 -94
- data/test/instrumentation/grpc_test.rb +164 -126
- data/test/instrumentation/net-http_test.rb +48 -57
- data/test/instrumentation/redis_test.rb +4 -6
- data/test/instrumentation/resque_test.rb +41 -41
- data/test/instrumentation/rest-client_test.rb +25 -31
- data/test/instrumentation/sidekiq-client_test.rb +12 -20
- data/test/instrumentation/sidekiq-worker_test.rb +48 -63
- data/test/jobs/resque_error_job.rb +7 -1
- data/test/jobs/resque_fast_job.rb +7 -1
- data/test/servers/sidekiq/worker.rb +1 -3
- data/test/test_helper.rb +58 -0
- data/test/tracing/custom_test.rb +11 -19
- data/test/tracing/opentracing_test.rb +48 -156
- data/test/tracing/trace_test.rb +67 -67
- data/test/tracing/tracer_async_test.rb +75 -175
- data/test/tracing/tracer_test.rb +75 -75
- metadata +4 -5
- data/lib/instana/tracing/trace.rb +0 -316
@@ -2,78 +2,43 @@ require 'thread'
|
|
2
2
|
|
3
3
|
module Instana
|
4
4
|
class Processor
|
5
|
-
|
6
5
|
def initialize
|
7
6
|
# The main queue before being reported to the
|
8
|
-
# host agent.
|
7
|
+
# host agent. Spans in this queue are complete
|
9
8
|
# and ready to be sent.
|
10
9
|
@queue = Queue.new
|
11
10
|
|
12
|
-
# The staging queue that holds traces that have completed
|
13
|
-
# but still have outstanding async spans.
|
14
|
-
# Traces that have been in this queue for more than
|
15
|
-
# 5 minutes are discarded.
|
16
|
-
@staging_queue = Set.new
|
17
|
-
|
18
|
-
# No access to the @staging_queue until this lock
|
19
|
-
# is taken.
|
20
|
-
@staging_lock = Mutex.new
|
21
|
-
|
22
11
|
# This is the maximum number of spans we send to the host
|
23
12
|
# agent at once.
|
24
13
|
@batch_size = 3000
|
25
14
|
end
|
26
15
|
|
27
|
-
# Adds a
|
28
|
-
# sent to the host agent
|
16
|
+
# Adds a Set of spans to the queue
|
29
17
|
#
|
30
|
-
# @param [
|
31
|
-
def
|
18
|
+
# @param [spans] - the trace to be added to the queue
|
19
|
+
def add_spans(spans)
|
32
20
|
# Do a quick checkup on our background thread.
|
33
21
|
if ::Instana.agent.collect_thread.nil? || !::Instana.agent.collect_thread.alive?
|
34
22
|
::Instana.agent.spawn_background_thread
|
35
23
|
end
|
36
|
-
|
37
|
-
# ::Instana.logger.debug("Queuing completed trace id: #{trace.id}")
|
38
|
-
@queue.push(trace)
|
24
|
+
spans.each { |span| @queue.push(span)}
|
39
25
|
end
|
40
26
|
|
41
|
-
# Adds a
|
27
|
+
# Adds a span to the span queue
|
42
28
|
#
|
43
|
-
# @param [Trace] the trace to be added to the queue
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
# completed or timed out incompleted traces. Completed traces will
|
51
|
-
# be added to the main @queue. Timed out traces will be discarded
|
52
|
-
#
|
53
|
-
def process_staged
|
54
|
-
@staging_lock.synchronize {
|
55
|
-
if @staging_queue.size > 0
|
56
|
-
@staging_queue.delete_if do |t|
|
57
|
-
if t.complete?
|
58
|
-
::Instana.logger.debug("Moving staged complete trace to main queue: #{t.id}")
|
59
|
-
add(t)
|
60
|
-
true
|
61
|
-
elsif t.discard?
|
62
|
-
::Instana.logger.debug("Discarding trace with uncompleted async spans over 5 mins old. id: #{t.id}")
|
63
|
-
true
|
64
|
-
else
|
65
|
-
false
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
}
|
29
|
+
# @param [Trace] - the trace to be added to the queue
|
30
|
+
def add_span(span)
|
31
|
+
# Do a quick checkup on our background thread.
|
32
|
+
if ::Instana.agent.collect_thread.nil? || !::Instana.agent.collect_thread.alive?
|
33
|
+
::Instana.agent.spawn_background_thread
|
34
|
+
end
|
35
|
+
@queue.push(span)
|
70
36
|
end
|
71
37
|
|
72
38
|
##
|
73
39
|
# send
|
74
40
|
#
|
75
|
-
# Sends all traces in @queue to the host
|
76
|
-
# agent
|
41
|
+
# Sends all traces in @queue to the host agent
|
77
42
|
#
|
78
43
|
# FIXME: Add limits checking here in regards to:
|
79
44
|
# - Max HTTP Post size
|
@@ -83,15 +48,6 @@ module Instana
|
|
83
48
|
def send
|
84
49
|
return if @queue.empty? || ENV.key?('INSTANA_TEST')
|
85
50
|
|
86
|
-
size = @queue.size
|
87
|
-
if size > 200
|
88
|
-
Instana.logger.debug "Trace queue is #{size}"
|
89
|
-
end
|
90
|
-
|
91
|
-
# Scan for any staged but incomplete traces that have now
|
92
|
-
# completed.
|
93
|
-
process_staged
|
94
|
-
|
95
51
|
# Retrieve all spans for queued traces
|
96
52
|
spans = queued_spans
|
97
53
|
|
@@ -117,85 +73,15 @@ module Instana
|
|
117
73
|
spans = []
|
118
74
|
until @queue.empty? do
|
119
75
|
# Non-blocking pop; ignore exception
|
120
|
-
|
121
|
-
|
122
|
-
spans <<
|
76
|
+
span = @queue.pop(true) rescue nil
|
77
|
+
if span
|
78
|
+
spans << span.raw
|
123
79
|
end
|
124
80
|
end
|
125
81
|
spans
|
126
82
|
end
|
127
83
|
|
128
|
-
#
|
129
|
-
# Note that traces retrieved with this method are removed
|
130
|
-
# entirely from the queue.
|
131
|
-
#
|
132
|
-
# @return [Array] An array of [Trace] or empty
|
133
|
-
#
|
134
|
-
def queued_traces
|
135
|
-
return [] if @queue.empty?
|
136
|
-
|
137
|
-
traces = []
|
138
|
-
until @queue.empty? do
|
139
|
-
# Non-blocking pop; ignore exception
|
140
|
-
traces << @queue.pop(true) rescue nil
|
141
|
-
end
|
142
|
-
traces
|
143
|
-
end
|
144
|
-
|
145
|
-
# Retrieves a all staged traces from the staging queue. Staged traces
|
146
|
-
# are traces that have completed but may have outstanding
|
147
|
-
# asynchronous spans.
|
148
|
-
#
|
149
|
-
# @return [Array]
|
150
|
-
#
|
151
|
-
def staged_traces
|
152
|
-
traces = nil
|
153
|
-
@staging_lock.synchronize {
|
154
|
-
traces = @staging_queue.to_a
|
155
|
-
@staging_queue.clear
|
156
|
-
}
|
157
|
-
traces
|
158
|
-
end
|
159
|
-
|
160
|
-
# Retrieves a single staged trace from the staging queue. Staged traces
|
161
|
-
# are traces that have completed but may have outstanding
|
162
|
-
# asynchronous spans.
|
163
|
-
#
|
164
|
-
# @param trace_id [Integer] the Trace ID to be searched for
|
165
|
-
#
|
166
|
-
def staged_trace(trace_id)
|
167
|
-
candidate = nil
|
168
|
-
@staging_lock.synchronize {
|
169
|
-
@staging_queue.each do |trace|
|
170
|
-
if trace.id == trace_id
|
171
|
-
candidate = trace
|
172
|
-
break
|
173
|
-
end
|
174
|
-
end
|
175
|
-
}
|
176
|
-
unless candidate
|
177
|
-
::Instana.logger.debug("Couldn't find staged trace with trace_id: #{trace_id}")
|
178
|
-
end
|
179
|
-
candidate
|
180
|
-
end
|
181
|
-
|
182
|
-
# Get the number traces currently in the queue
|
183
|
-
#
|
184
|
-
# @return [Integer] the queue size
|
185
|
-
#
|
186
|
-
def queue_count
|
187
|
-
@queue.size
|
188
|
-
end
|
189
|
-
|
190
|
-
# Get the number traces currently in the staging queue
|
191
|
-
#
|
192
|
-
# @return [Integer] the queue size
|
193
|
-
#
|
194
|
-
def staged_count
|
195
|
-
@staging_queue.size
|
196
|
-
end
|
197
|
-
|
198
|
-
# Removes all traces from the @queue and @staging_queue. Used in the
|
84
|
+
# Removes all traces from the @queue. Used in the
|
199
85
|
# test suite to reset state.
|
200
86
|
#
|
201
87
|
def clear!
|
@@ -203,7 +89,6 @@ module Instana
|
|
203
89
|
# Non-blocking pop; ignore exception
|
204
90
|
@queue.pop(true) rescue nil
|
205
91
|
end
|
206
|
-
@staging_queue.clear
|
207
92
|
end
|
208
93
|
end
|
209
94
|
end
|
data/lib/instana/tracing/span.rb
CHANGED
@@ -11,13 +11,33 @@ module Instana
|
|
11
11
|
|
12
12
|
attr_accessor :parent
|
13
13
|
attr_accessor :baggage
|
14
|
+
attr_accessor :is_root
|
15
|
+
attr_accessor :context
|
14
16
|
|
15
|
-
def initialize(name,
|
17
|
+
def initialize(name, parent_ctx: nil, start_time: ::Instana::Util.now_in_ms)
|
16
18
|
@data = {}
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
|
20
|
+
if parent_ctx == nil
|
21
|
+
# No parent specified so we're starting a new Trace - this will be the root span
|
22
|
+
id = ::Instana::Util.generate_id
|
23
|
+
@data[:t] = id # Trace ID
|
24
|
+
@data[:s] = id # Span ID
|
25
|
+
is_root = true
|
26
|
+
else
|
27
|
+
if parent_ctx.is_a?(::Instana::Span)
|
28
|
+
@parent = parent_ctx
|
29
|
+
parent_context = parent_ctx.context
|
30
|
+
elsif parent_ctx.is_a?(::Instana::SpanContext)
|
31
|
+
parent_context = parent_ctx
|
32
|
+
end
|
33
|
+
|
34
|
+
@data[:t] = parent_context.trace_id # Trace ID
|
35
|
+
@data[:s] = ::Instana::Util.generate_id # Span ID
|
36
|
+
@data[:p] = parent_context.span_id # Parent ID
|
37
|
+
@baggage = parent_ctx.baggage.dup
|
38
|
+
is_root = false
|
39
|
+
end
|
40
|
+
|
21
41
|
@data[:data] = {}
|
22
42
|
|
23
43
|
# Entity Source
|
@@ -30,8 +50,6 @@ module Instana
|
|
30
50
|
@data[:ts] = start_time
|
31
51
|
end
|
32
52
|
|
33
|
-
@baggage = {}
|
34
|
-
|
35
53
|
if ::Instana.config[:collect_backtraces]
|
36
54
|
# For entry spans, add a backtrace fingerprint
|
37
55
|
add_stack(limit: 2) if ENTRY_SPANS.include?(name)
|
@@ -119,7 +137,7 @@ module Instana
|
|
119
137
|
#
|
120
138
|
def configure_custom(name)
|
121
139
|
@data[:n] = :sdk
|
122
|
-
@data[:k] =
|
140
|
+
@data[:k] = 3
|
123
141
|
@data[:data] = { :sdk => { :name => name.to_sym, :type => :intermediate } }
|
124
142
|
@data[:data][:sdk][:custom] = { :tags => {}, :logs => {} }
|
125
143
|
self
|
@@ -133,12 +151,15 @@ module Instana
|
|
133
151
|
# @return [Span]
|
134
152
|
#
|
135
153
|
def close(end_time = ::Instana::Util.now_in_ms)
|
136
|
-
|
137
154
|
if end_time.is_a?(Time)
|
138
155
|
end_time = ::Instana::Util.time_to_ms(end_time)
|
139
156
|
end
|
140
157
|
|
141
158
|
@data[:d] = end_time - @data[:ts]
|
159
|
+
|
160
|
+
# Add this span to the queue for reporting
|
161
|
+
::Instana.processor.add_span(self)
|
162
|
+
|
142
163
|
self
|
143
164
|
end
|
144
165
|
|
@@ -151,7 +172,7 @@ module Instana
|
|
151
172
|
# @return [Instana::SpanContext]
|
152
173
|
#
|
153
174
|
def context
|
154
|
-
@context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @baggage)
|
175
|
+
@context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], 1, @baggage)
|
155
176
|
end
|
156
177
|
|
157
178
|
# Retrieve the ID for this span
|
@@ -212,15 +233,6 @@ module Instana
|
|
212
233
|
@data[:d]
|
213
234
|
end
|
214
235
|
|
215
|
-
# Indicates whether this span in the root span
|
216
|
-
# in the Trace
|
217
|
-
#
|
218
|
-
# @return [Boolean]
|
219
|
-
#
|
220
|
-
def is_root?
|
221
|
-
@data[:s] == @data[:t]
|
222
|
-
end
|
223
|
-
|
224
236
|
# Hash accessor to the internal @data hash
|
225
237
|
#
|
226
238
|
def [](key)
|
@@ -283,11 +295,14 @@ module Instana
|
|
283
295
|
if key.to_sym == :'span.kind'
|
284
296
|
case value.to_sym
|
285
297
|
when :server, :consumer
|
286
|
-
@data[:data][:sdk][:type] =
|
298
|
+
@data[:data][:sdk][:type] = :entry
|
299
|
+
@data[:k] = 1
|
287
300
|
when :client, :producer
|
288
|
-
@data[:data][:sdk][:type] =
|
301
|
+
@data[:data][:sdk][:type] = :exit
|
302
|
+
@data[:k] = 2
|
289
303
|
else
|
290
|
-
@data[:data][:sdk][:type] =
|
304
|
+
@data[:data][:sdk][:type] = :intermediate
|
305
|
+
@data[:k] = 3
|
291
306
|
end
|
292
307
|
end
|
293
308
|
else
|
@@ -328,7 +343,7 @@ module Instana
|
|
328
343
|
if @context
|
329
344
|
@context.baggage = @baggage
|
330
345
|
else
|
331
|
-
@context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @baggage)
|
346
|
+
@context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], 1, @baggage)
|
332
347
|
end
|
333
348
|
self
|
334
349
|
end
|
@@ -370,7 +385,7 @@ module Instana
|
|
370
385
|
set_tags(:log => fields)
|
371
386
|
end
|
372
387
|
rescue StandardError => e
|
373
|
-
Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
388
|
+
Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
|
374
389
|
end
|
375
390
|
|
376
391
|
# Finish the {Span}
|
@@ -379,17 +394,7 @@ module Instana
|
|
379
394
|
# @param end_time [Time] custom end time, if not now
|
380
395
|
#
|
381
396
|
def finish(end_time = ::Instana::Util.now_in_ms)
|
382
|
-
|
383
|
-
::Instana.logger.debug "Closing a span that isn't active. This will result in a broken trace: #{self.inspect}"
|
384
|
-
end
|
385
|
-
|
386
|
-
if is_root?
|
387
|
-
# This is the root span for the trace. Call log_end to close
|
388
|
-
# out and queue the trace
|
389
|
-
::Instana.tracer.log_end(name, {}, end_time)
|
390
|
-
else
|
391
|
-
::Instana.tracer.current_trace.end_span({}, end_time)
|
392
|
-
end
|
397
|
+
close(end_time)
|
393
398
|
self
|
394
399
|
end
|
395
400
|
end
|
@@ -8,11 +8,13 @@ module Instana
|
|
8
8
|
#
|
9
9
|
# @param tid [Integer] the trace ID
|
10
10
|
# @param sid [Integer] the span ID
|
11
|
+
# @param level [Integer] default 1
|
11
12
|
# @param baggage [Hash] baggage applied to this trace
|
12
13
|
#
|
13
|
-
def initialize(tid, sid, baggage = nil)
|
14
|
+
def initialize(tid, sid, level = 1, baggage = nil)
|
14
15
|
@trace_id = tid
|
15
16
|
@span_id = sid
|
17
|
+
@level = level
|
16
18
|
@baggage = baggage
|
17
19
|
end
|
18
20
|
|
data/lib/instana/util.rb
CHANGED
@@ -119,8 +119,8 @@ module Instana
|
|
119
119
|
|
120
120
|
data
|
121
121
|
rescue => e
|
122
|
-
::Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
123
|
-
::Instana.logger.debug e.backtrace.join("\r\n")
|
122
|
+
::Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
|
123
|
+
::Instana.logger.debug { e.backtrace.join("\r\n") }
|
124
124
|
return data
|
125
125
|
end
|
126
126
|
|
@@ -187,7 +187,7 @@ module Instana
|
|
187
187
|
return File.basename($0)
|
188
188
|
rescue Exception => e
|
189
189
|
Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
190
|
-
Instana.logger.debug e.backtrace.join("\r\n")
|
190
|
+
Instana.logger.debug { e.backtrace.join("\r\n") }
|
191
191
|
end
|
192
192
|
|
193
193
|
# Get the current time in milliseconds from the epoch
|
@@ -231,7 +231,7 @@ module Instana
|
|
231
231
|
[id.to_i].pack('q>').unpack('H*')[0].gsub(/^0+/, '')
|
232
232
|
rescue => e
|
233
233
|
Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
234
|
-
Instana.logger.debug e.backtrace.join("\r\n")
|
234
|
+
Instana.logger.debug { e.backtrace.join("\r\n") }
|
235
235
|
end
|
236
236
|
|
237
237
|
# Convert a received header value into a valid ID
|
@@ -254,7 +254,7 @@ module Instana
|
|
254
254
|
[header_id].pack("H*").unpack("q>")[0]
|
255
255
|
rescue => e
|
256
256
|
Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
257
|
-
Instana.logger.debug e.backtrace.join("\r\n")
|
257
|
+
Instana.logger.debug { e.backtrace.join("\r\n") }
|
258
258
|
end
|
259
259
|
end
|
260
260
|
end
|
data/lib/instana/version.rb
CHANGED
data/lib/opentracing.rb
CHANGED
@@ -31,7 +31,6 @@ class RackTest < Minitest::Test
|
|
31
31
|
|
32
32
|
first_span = spans.first
|
33
33
|
assert_equal :rack, first_span[:n]
|
34
|
-
assert_equal :ruby, first_span[:ta]
|
35
34
|
assert first_span.key?(:data)
|
36
35
|
assert first_span[:data].key?(:http)
|
37
36
|
assert_equal "GET", first_span[:data][:http][:method]
|
@@ -78,7 +77,6 @@ class RackTest < Minitest::Test
|
|
78
77
|
assert_equal 1, spans.count
|
79
78
|
first_span = spans.first
|
80
79
|
assert_equal :rack, first_span[:n]
|
81
|
-
assert_equal :ruby, first_span[:ta]
|
82
80
|
assert first_span.key?(:data)
|
83
81
|
assert first_span[:data].key?(:http)
|
84
82
|
assert_equal "POST", first_span[:data][:http][:method]
|
@@ -101,7 +99,6 @@ class RackTest < Minitest::Test
|
|
101
99
|
assert_equal 1, spans.count
|
102
100
|
first_span = spans.first
|
103
101
|
assert_equal :rack, first_span[:n]
|
104
|
-
assert_equal :ruby, first_span[:ta]
|
105
102
|
assert first_span.key?(:data)
|
106
103
|
assert first_span[:data].key?(:http)
|
107
104
|
assert_equal "PUT", first_span[:data][:http][:method]
|
@@ -127,7 +124,6 @@ class RackTest < Minitest::Test
|
|
127
124
|
assert_equal 1, spans.count
|
128
125
|
first_span = spans.first
|
129
126
|
assert_equal :rack, first_span[:n]
|
130
|
-
assert_equal :ruby, first_span[:ta]
|
131
127
|
assert first_span.key?(:data)
|
132
128
|
assert first_span[:data].key?(:http)
|
133
129
|
assert_equal "GET", first_span[:data][:http][:method]
|
@@ -158,14 +154,13 @@ class RackTest < Minitest::Test
|
|
158
154
|
clear_all!
|
159
155
|
get '/mrlobster?blah=2&wilma=1&betty=2;fred=3'
|
160
156
|
|
161
|
-
|
162
|
-
assert_equal 1,
|
157
|
+
spans = ::Instana.processor.queued_spans
|
158
|
+
assert_equal 1, spans.length
|
163
159
|
|
164
|
-
|
165
|
-
refute_nil
|
166
|
-
refute_nil
|
167
|
-
|
168
|
-
assert_equal '/mrlobster', trace.spans.first[:data][:http][:url]
|
160
|
+
refute_nil spans.first.key?(:data)
|
161
|
+
refute_nil spans.first[:data].key?(:http)
|
162
|
+
refute_nil spans.first[:data][:http].key?(:url)
|
163
|
+
assert_equal '/mrlobster', spans.first[:data][:http][:url]
|
169
164
|
|
170
165
|
assert last_response.ok?
|
171
166
|
end
|