instana 1.9.7 → 1.10.0.slimfast

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 (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