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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/instana/agent.rb +19 -19
  3. data/lib/instana/agent/helpers.rb +2 -2
  4. data/lib/instana/agent/tasks.rb +2 -2
  5. data/lib/instana/collectors/gc.rb +1 -1
  6. data/lib/instana/collectors/memory.rb +1 -1
  7. data/lib/instana/collectors/thread.rb +1 -1
  8. data/lib/instana/frameworks/instrumentation/mysql2_adapter.rb +1 -1
  9. data/lib/instana/frameworks/instrumentation/mysql_adapter.rb +1 -1
  10. data/lib/instana/helpers.rb +2 -2
  11. data/lib/instana/instrumentation.rb +1 -1
  12. data/lib/instana/instrumentation/excon.rb +8 -5
  13. data/lib/instana/instrumentation/rack.rb +2 -2
  14. data/lib/instana/instrumentation/resque.rb +3 -3
  15. data/lib/instana/tracer.rb +92 -117
  16. data/lib/instana/tracing/processor.rb +18 -133
  17. data/lib/instana/tracing/span.rb +40 -35
  18. data/lib/instana/tracing/span_context.rb +3 -1
  19. data/lib/instana/util.rb +5 -5
  20. data/lib/instana/version.rb +1 -1
  21. data/lib/opentracing.rb +1 -1
  22. data/test/frameworks/rack_test.rb +6 -11
  23. data/test/frameworks/rails/actioncontroller_test.rb +32 -62
  24. data/test/frameworks/rails/actionview5_test.rb +91 -132
  25. data/test/frameworks/rails/activerecord5_test.rb +14 -17
  26. data/test/instrumentation/dalli_test.rb +51 -72
  27. data/test/instrumentation/excon_test.rb +70 -94
  28. data/test/instrumentation/grpc_test.rb +164 -126
  29. data/test/instrumentation/net-http_test.rb +48 -57
  30. data/test/instrumentation/redis_test.rb +4 -6
  31. data/test/instrumentation/resque_test.rb +41 -41
  32. data/test/instrumentation/rest-client_test.rb +25 -31
  33. data/test/instrumentation/sidekiq-client_test.rb +12 -20
  34. data/test/instrumentation/sidekiq-worker_test.rb +48 -63
  35. data/test/jobs/resque_error_job.rb +7 -1
  36. data/test/jobs/resque_fast_job.rb +7 -1
  37. data/test/servers/sidekiq/worker.rb +1 -3
  38. data/test/test_helper.rb +58 -0
  39. data/test/tracing/custom_test.rb +11 -19
  40. data/test/tracing/opentracing_test.rb +48 -156
  41. data/test/tracing/trace_test.rb +67 -67
  42. data/test/tracing/tracer_async_test.rb +75 -175
  43. data/test/tracing/tracer_test.rb +75 -75
  44. metadata +4 -5
  45. 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. Traces in this queue are complete
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 trace to the queue to be processed and
28
- # sent to the host agent
16
+ # Adds a Set of spans to the queue
29
17
  #
30
- # @param [Trace] the trace to be added to the queue
31
- def add(trace)
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 trace to the staging queue.
27
+ # Adds a span to the span queue
42
28
  #
43
- # @param [Trace] the trace to be added to the queue
44
- def stage(trace)
45
- ::Instana.logger.debug("Staging incomplete trace id: #{trace.id}")
46
- @staging_queue.add(trace)
47
- end
48
-
49
- # This will run through the staged traces (if any) to find
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
- trace = @queue.pop(true) rescue nil
121
- trace.spans.each do |s|
122
- spans << s.raw
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
- # Retrieves all of the traces that are in @queue.
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
@@ -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, trace_id, parent_id: nil, start_time: ::Instana::Util.now_in_ms)
17
+ def initialize(name, parent_ctx: nil, start_time: ::Instana::Util.now_in_ms)
16
18
  @data = {}
17
- @data[:t] = trace_id # Trace ID
18
- @data[:s] = ::Instana::Util.generate_id # Span ID
19
- @data[:p] = parent_id if parent_id # Parent ID
20
- @data[:ta] = :ruby # Agent
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] = :intermediate
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] = @data[:k] = :entry
298
+ @data[:data][:sdk][:type] = :entry
299
+ @data[:k] = 1
287
300
  when :client, :producer
288
- @data[:data][:sdk][:type] = @data[:k] = :exit
301
+ @data[:data][:sdk][:type] = :exit
302
+ @data[:k] = 2
289
303
  else
290
- @data[:data][:sdk][:type] = @data[:k] = :intermediate
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
- if ::Instana.tracer.current_span.id != id
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
 
@@ -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
@@ -1,4 +1,4 @@
1
1
  module Instana
2
- VERSION = "1.9.7"
2
+ VERSION = "1.10.0.slimfast"
3
3
  VERSION_FULL = "instana-#{VERSION}"
4
4
  end
@@ -2,5 +2,5 @@ require "instana/opentracing/tracer"
2
2
  require "instana/opentracing/carrier"
3
3
 
4
4
  # Set the global tracer to our OT tracer
5
- # which supports the OT specificiation
5
+ # which supports the OT specification
6
6
  OpenTracing.global_tracer = ::Instana.tracer
@@ -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
- traces = ::Instana.processor.queued_traces
162
- assert_equal 1, traces.length
157
+ spans = ::Instana.processor.queued_spans
158
+ assert_equal 1, spans.length
163
159
 
164
- trace = traces[0]
165
- refute_nil trace.spans.first.key?(:data)
166
- refute_nil trace.spans.first[:data].key?(:http)
167
- refute_nil trace.spans.first[:data][:http].key?(:url)
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