instana 1.195.4 → 1.197.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -2
  3. data/Rakefile +1 -1
  4. data/instana.gemspec +3 -7
  5. data/lib/instana.rb +3 -0
  6. data/lib/instana/activator.rb +2 -0
  7. data/lib/instana/backend/agent.rb +60 -0
  8. data/lib/instana/backend/gc_snapshot.rb +41 -0
  9. data/lib/instana/backend/host_agent.rb +57 -0
  10. data/lib/instana/backend/host_agent_activation_observer.rb +87 -0
  11. data/lib/instana/backend/host_agent_lookup.rb +57 -0
  12. data/lib/instana/backend/host_agent_reporting_observer.rb +106 -0
  13. data/lib/instana/backend/process_info.rb +64 -0
  14. data/lib/instana/backend/request_client.rb +84 -0
  15. data/lib/instana/backend/serverless_agent.rb +118 -0
  16. data/lib/instana/base.rb +8 -27
  17. data/lib/instana/config.rb +7 -21
  18. data/lib/instana/logger_delegator.rb +31 -0
  19. data/lib/instana/{opentracing → open_tracing}/carrier.rb +0 -0
  20. data/lib/instana/open_tracing/instana_tracer.rb +99 -0
  21. data/lib/instana/secrets.rb +6 -2
  22. data/lib/instana/setup.rb +20 -11
  23. data/lib/instana/snapshot/deltable.rb +25 -0
  24. data/lib/instana/snapshot/docker_container.rb +151 -0
  25. data/lib/instana/snapshot/fargate_container.rb +88 -0
  26. data/lib/instana/snapshot/fargate_process.rb +67 -0
  27. data/lib/instana/snapshot/fargate_task.rb +72 -0
  28. data/lib/instana/snapshot/ruby_process.rb +48 -0
  29. data/lib/instana/tracer.rb +25 -143
  30. data/lib/instana/tracing/processor.rb +4 -22
  31. data/lib/instana/tracing/span.rb +26 -35
  32. data/lib/instana/tracing/span_context.rb +1 -1
  33. data/lib/instana/util.rb +4 -67
  34. data/lib/instana/version.rb +1 -1
  35. data/lib/opentracing.rb +26 -3
  36. data/test/backend/agent_test.rb +54 -0
  37. data/test/backend/gc_snapshot_test.rb +11 -0
  38. data/test/backend/host_agent_activation_observer_test.rb +65 -0
  39. data/test/backend/host_agent_lookup_test.rb +78 -0
  40. data/test/backend/host_agent_reporting_observer_test.rb +192 -0
  41. data/test/backend/host_agent_test.rb +32 -0
  42. data/test/backend/process_info_test.rb +63 -0
  43. data/test/backend/request_client_test.rb +61 -0
  44. data/test/backend/serverless_agent_test.rb +73 -0
  45. data/test/config_test.rb +10 -0
  46. data/test/instana_test.rb +11 -4
  47. data/test/instrumentation/rack_instrumented_request_test.rb +3 -2
  48. data/test/instrumentation/rack_test.rb +2 -14
  49. data/test/secrets_test.rb +41 -22
  50. data/test/snapshot/deltable_test.rb +17 -0
  51. data/test/snapshot/docker_container_test.rb +82 -0
  52. data/test/snapshot/fargate_container_test.rb +82 -0
  53. data/test/snapshot/fargate_process_test.rb +35 -0
  54. data/test/snapshot/fargate_task_test.rb +49 -0
  55. data/test/snapshot/ruby_process_test.rb +14 -0
  56. data/test/support/mock_timer.rb +20 -0
  57. data/test/test_helper.rb +15 -3
  58. data/test/tracing/custom_test.rb +1 -3
  59. data/test/tracing/id_management_test.rb +4 -0
  60. data/test/tracing/opentracing_test.rb +15 -2
  61. data/test/tracing/processor_test.rb +58 -0
  62. data/test/tracing/span_context_test.rb +22 -0
  63. data/test/tracing/span_test.rb +127 -0
  64. data/test/tracing/tracer_async_test.rb +29 -0
  65. data/test/tracing/tracer_test.rb +82 -16
  66. data/test/util_test.rb +10 -0
  67. metadata +72 -45
  68. data/lib/instana/agent.rb +0 -508
  69. data/lib/instana/agent/helpers.rb +0 -87
  70. data/lib/instana/agent/hooks.rb +0 -44
  71. data/lib/instana/agent/tasks.rb +0 -51
  72. data/lib/instana/collector.rb +0 -119
  73. data/lib/instana/collectors/gc.rb +0 -60
  74. data/lib/instana/collectors/memory.rb +0 -37
  75. data/lib/instana/collectors/thread.rb +0 -33
  76. data/lib/instana/eum/eum-test.js.erb +0 -17
  77. data/lib/instana/eum/eum.js.erb +0 -17
  78. data/lib/instana/helpers.rb +0 -47
  79. data/lib/instana/opentracing/tracer.rb +0 -21
  80. data/lib/instana/thread_local.rb +0 -18
  81. data/lib/oj_check.rb +0 -19
  82. data/test/agent/agent_test.rb +0 -151
@@ -0,0 +1,48 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Snapshot
6
+ # Describes the current Ruby process
7
+ # @since 1.197.0
8
+ class RubyProcess
9
+ ID = 'com.instana.plugin.ruby'.freeze
10
+
11
+ def initialize(pid: Process.pid)
12
+ @pid = pid
13
+ end
14
+
15
+ def entity_id
16
+ @pid.to_s
17
+ end
18
+
19
+ def data
20
+ metrics_data.merge(Util.take_snapshot)
21
+ end
22
+
23
+ def snapshot
24
+ {
25
+ name: ID,
26
+ entityId: entity_id,
27
+ data: data
28
+ }
29
+ end
30
+
31
+ private
32
+
33
+ def metrics_data
34
+ proc_table = Sys::ProcTable.ps(pid: Process.pid)
35
+ process = Backend::ProcessInfo.new(proc_table)
36
+
37
+ {
38
+ pid: @pid,
39
+ name: Util.get_app_name,
40
+ exec_args: process.arguments,
41
+ gc: Backend::GCSnapshot.instance.report,
42
+ thread: {count: ::Thread.list.count},
43
+ memory: {rss_size: proc_table.rss / 1024} # Bytes to Kilobytes
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,16 +1,11 @@
1
1
  # (c) Copyright IBM Corp. 2021
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
- require "instana/thread_local"
5
4
  require "instana/tracing/span"
6
5
  require "instana/tracing/span_context"
7
6
 
8
7
  module Instana
9
8
  class Tracer
10
- extend ::Instana::ThreadLocal
11
-
12
- thread_local :current_span
13
-
14
9
  # Support ::Instana::Tracer.xxx call style for the instantiated tracer
15
10
  class << self
16
11
  def method_missing(method, *args, &block)
@@ -22,6 +17,22 @@ module Instana
22
17
  end
23
18
  end
24
19
 
20
+ def initialize(logger: Instana.logger)
21
+ @current_span = Concurrent::ThreadLocalVar.new
22
+ @logger = logger
23
+ end
24
+
25
+ # @return [Instana::Span, NilClass] the current active span or nil if we are not tracing
26
+ def current_span
27
+ @current_span.value
28
+ end
29
+
30
+ # @param [Instana::Span, NilClas] v the new current span
31
+ # Set the value of the current span
32
+ def current_span=(v)
33
+ @current_span.value = v
34
+ end
35
+
25
36
  #######################################
26
37
  # Tracing blocks API methods
27
38
  #######################################
@@ -85,7 +96,6 @@ module Instana
85
96
  #
86
97
  def log_start_or_continue(name, kvs = {}, incoming_context = nil)
87
98
  return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled]
88
- ::Instana.logger.debug { "#{__method__} passed a block. Use `start_or_continue` instead!" } if block_given?
89
99
 
90
100
  # Handle the potential variations on `incoming_context`
91
101
  if incoming_context
@@ -125,11 +135,11 @@ module Instana
125
135
  def log_entry(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil)
126
136
  return unless self.current_span || child_of
127
137
 
128
- if child_of && (child_of.is_a?(::Instana::Span) || child_of.is_a?(::Instana::SpanContext))
129
- new_span = Span.new(name, parent_ctx: child_of, start_time: start_time)
130
- else
131
- new_span = Span.new(name, parent_ctx: self.current_span, start_time: start_time)
132
- end
138
+ new_span = if child_of.is_a?(::Instana::Span) || child_of.is_a?(::Instana::SpanContext)
139
+ Span.new(name, parent_ctx: child_of, start_time: start_time)
140
+ else
141
+ Span.new(name, parent_ctx: self.current_span, start_time: start_time)
142
+ end
133
143
  new_span.set_tags(kvs) if kvs
134
144
  self.current_span = new_span
135
145
  end
@@ -163,10 +173,8 @@ module Instana
163
173
  def log_exit(name, kvs = {})
164
174
  return unless self.current_span
165
175
 
166
- if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST')
167
- unless self.current_span.name == name
168
- ::Instana.logger.debug "Span mismatch: Attempt to exit #{name} span but #{self.current_span.name} is active."
169
- end
176
+ if self.current_span.name != name
177
+ @logger.warn "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active."
170
178
  end
171
179
 
172
180
  self.current_span.set_tags(kvs)
@@ -191,10 +199,8 @@ module Instana
191
199
  def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms)
192
200
  return unless self.current_span
193
201
 
194
- if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST')
195
- unless self.current_span.name == name
196
- ::Instana.logger.debug "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active."
197
- end
202
+ if self.current_span.name != name
203
+ @logger.warn "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active."
198
204
  end
199
205
 
200
206
  self.current_span.set_tags(kvs)
@@ -252,88 +258,6 @@ module Instana
252
258
  span.close
253
259
  end
254
260
 
255
- ###########################################################################
256
- # OpenTracing Support
257
- ###########################################################################
258
-
259
- # Start a new span
260
- #
261
- # @param operation_name [String] The name of the operation represented by the span
262
- # @param child_of [Span] A span to be used as the ChildOf reference
263
- # @param start_time [Time] the start time of the span
264
- # @param tags [Hash] Starting tags for the span
265
- #
266
- # @return [Span]
267
- #
268
- def start_span(operation_name, child_of: nil, start_time: ::Instana::Util.now_in_ms, tags: nil)
269
- if child_of && (child_of.is_a?(::Instana::Span) || child_of.is_a?(::Instana::SpanContext))
270
- new_span = Span.new(operation_name, parent_ctx: child_of, start_time: start_time)
271
- else
272
- new_span = Span.new(operation_name, start_time: start_time)
273
- end
274
- new_span.set_tags(tags) if tags
275
- new_span
276
- end
277
-
278
- # Start a new span which is the child of the current span
279
- #
280
- # @param operation_name [String] The name of the operation represented by the span
281
- # @param child_of [Span] A span to be used as the ChildOf reference
282
- # @param start_time [Time] the start time of the span
283
- # @param tags [Hash] Starting tags for the span
284
- #
285
- # @return [Span]
286
- #
287
- def start_active_span(operation_name, child_of: self.current_span, start_time: ::Instana::Util.now_in_ms, tags: nil)
288
- self.current_span = start_span(operation_name, child_of: child_of, start_time: start_time, tags: tags)
289
- end
290
-
291
- # Returns the currently active span
292
- #
293
- # @return [Span]
294
- #
295
- def active_span
296
- self.current_span
297
- end
298
-
299
- # Inject a span into the given carrier
300
- #
301
- # @param span_context [SpanContext]
302
- # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
303
- # @param carrier [Carrier]
304
- #
305
- def inject(span_context, format, carrier)
306
- case format
307
- when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY
308
- ::Instana.logger.debug 'Unsupported inject format'
309
- when OpenTracing::FORMAT_RACK
310
- carrier['X-Instana-T'] = ::Instana::Util.id_to_header(span_context.trace_id)
311
- carrier['X-Instana-S'] = ::Instana::Util.id_to_header(span_context.span_id)
312
- else
313
- ::Instana.logger.debug 'Unknown inject format'
314
- end
315
- end
316
-
317
- # Extract a span from a carrier
318
- #
319
- # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
320
- # @param carrier [Carrier]
321
- #
322
- # @return [SpanContext]
323
- #
324
- def extract(format, carrier)
325
- case format
326
- when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY
327
- ::Instana.logger.debug 'Unsupported extract format'
328
- when OpenTracing::FORMAT_RACK
329
- ::Instana::SpanContext.new(::Instana::Util.header_to_id(carrier['HTTP_X_INSTANA_T']),
330
- ::Instana::Util.header_to_id(carrier['HTTP_X_INSTANA_S']))
331
- else
332
- ::Instana.logger.debug 'Unknown inject format'
333
- nil
334
- end
335
- end
336
-
337
261
  ###########################################################################
338
262
  # Helper methods
339
263
  ###########################################################################
@@ -374,48 +298,6 @@ module Instana
374
298
  self.current_span.context
375
299
  end
376
300
 
377
- # Take the current trace_id and convert it to a header compatible
378
- # format.
379
- #
380
- # @return [String] a hexadecimal representation of the current trace ID
381
- #
382
- def trace_id_header
383
- if self.current_span
384
- self.current_span.context.trace_id_header
385
- else
386
- ""
387
- end
388
- end
389
-
390
- # Take the current span_id and convert it to a header compatible
391
- # formate.
392
- #
393
- # @return [String] a hexadecimal representation of the current span ID
394
- #
395
- def span_id_header
396
- if self.current_span
397
- self.current_span.context.span_id_header
398
- else
399
- ""
400
- end
401
- end
402
-
403
- # Returns the trace ID for the active trace (if there is one),
404
- # otherwise nil.
405
- #
406
- def trace_id
407
- self.current_span ? self.current_span.id : nil
408
- ::Instana.logger.debug("tracer.trace_id will deprecated in a future version.")
409
- end
410
-
411
- # Returns the current [Span] ID for the active trace (if there is one),
412
- # otherwise nil.
413
- #
414
- def span_id
415
- self.current_span ? self.current_span.span_id : nil
416
- ::Instana.logger.debug("tracer.span_id will deprecated in a future version.")
417
- end
418
-
419
301
  # Used in the test suite, this resets the tracer to non-tracing state.
420
302
  #
421
303
  def clear!
@@ -16,23 +16,10 @@ module Instana
16
16
  @batch_size = 3000
17
17
  end
18
18
 
19
- # Adds a Set of spans to the queue
20
- #
21
- # @param [spans] - the trace to be added to the queue
22
- def add_spans(spans)
23
- spans.each { |span| @queue.push(span)}
24
- end
25
-
26
19
  # Adds a span to the span queue
27
20
  #
28
21
  # @param [Trace] - the trace to be added to the queue
29
22
  def add_span(span)
30
- # Occasionally, do a checkup on our background thread.
31
- if rand(10) > 8
32
- if ::Instana.agent.collect_thread.nil? || !::Instana.agent.collect_thread.alive?
33
- ::Instana.agent.spawn_background_thread
34
- end
35
- end
36
23
  @queue.push(span)
37
24
  end
38
25
 
@@ -46,18 +33,14 @@ module Instana
46
33
  # - Out of control/growing queue
47
34
  # - Prevent another run of the timer while this is running
48
35
  #
49
- def send
36
+ def send(&block)
50
37
  return if @queue.empty? || ENV.key?('INSTANA_TEST')
51
38
 
52
39
  # Retrieve all spans for queued traces
53
40
  spans = queued_spans
54
41
 
55
42
  # Report spans in batches
56
- batch = spans.shift(@batch_size)
57
- while !batch.empty? do
58
- ::Instana.agent.report_spans(batch)
59
- batch = spans.shift(@batch_size)
60
- end
43
+ spans.each_slice(@batch_size, &block)
61
44
  end
62
45
 
63
46
  # Retrieves all of the traces in @queue and returns
@@ -75,10 +58,9 @@ module Instana
75
58
  until @queue.empty? do
76
59
  # Non-blocking pop; ignore exception
77
60
  span = @queue.pop(true) rescue nil
78
- if span
79
- spans << span.raw
80
- end
61
+ spans << span.raw if span.is_a?(Span) && span.context.level == 1
81
62
  end
63
+
82
64
  spans
83
65
  end
84
66
 
@@ -20,38 +20,34 @@ module Instana
20
20
  def initialize(name, parent_ctx: nil, start_time: ::Instana::Util.now_in_ms)
21
21
  @data = {}
22
22
 
23
- if parent_ctx == nil
24
- # No parent specified so we're starting a new Trace - this will be the root span
25
- id = ::Instana::Util.generate_id
26
- @data[:t] = id # Trace ID
27
- @data[:s] = id # Span ID
28
- @is_root = true
29
- else
30
- if parent_ctx.is_a?(::Instana::Span)
31
- @parent = parent_ctx
32
- parent_context = parent_ctx.context
33
- elsif parent_ctx.is_a?(::Instana::SpanContext)
34
- parent_context = parent_ctx
35
- end
23
+ if parent_ctx.is_a?(::Instana::Span)
24
+ @parent = parent_ctx
25
+ parent_ctx = parent_ctx.context
26
+ end
27
+
28
+ if parent_ctx.is_a?(::Instana::SpanContext)
29
+ @is_root = false
36
30
 
37
- @data[:t] = parent_context.trace_id # Trace ID
31
+ @data[:t] = parent_ctx.trace_id # Trace ID
38
32
  @data[:s] = ::Instana::Util.generate_id # Span ID
39
- @data[:p] = parent_context.span_id # Parent ID
33
+ @data[:p] = parent_ctx.span_id # Parent ID
40
34
 
41
- if parent_context.baggage
42
- @baggage = parent_ctx.baggage.dup
43
- else
44
- @baggage = nil
45
- end
35
+ @baggage = parent_ctx.baggage.dup
36
+ @level = parent_ctx.level
37
+ else
38
+ # No parent specified so we're starting a new Trace - this will be the root span
39
+ @is_root = true
40
+ @level = 1
46
41
 
47
- @is_root = false
42
+ id = ::Instana::Util.generate_id
43
+ @data[:t] = id # Trace ID
44
+ @data[:s] = id # Span ID
48
45
  end
49
46
 
50
47
  @data[:data] = {}
51
48
 
52
49
  # Entity Source
53
- @data[:f] = { :e => ::Instana.agent.report_pid,
54
- :h => ::Instana.agent.agent_uuid }
50
+ @data[:f] = ::Instana.agent.source
55
51
  # Start time
56
52
  if start_time.is_a?(Time)
57
53
  @data[:ts] = ::Instana::Util.time_to_ms(start_time)
@@ -59,17 +55,15 @@ module Instana
59
55
  @data[:ts] = start_time
60
56
  end
61
57
 
62
- if ::Instana.config[:collect_backtraces]
63
- # Attach a backtrace to all exit spans
64
- add_stack if EXIT_SPANS.include?(name)
65
- end
66
-
67
58
  # Check for custom tracing
68
59
  if REGISTERED_SPANS.include?(name.to_sym)
69
60
  @data[:n] = name.to_sym
70
61
  else
71
62
  configure_custom(name)
72
63
  end
64
+
65
+ # Attach a backtrace to all exit spans
66
+ add_stack if ::Instana.config[:collect_backtraces] && exit_span?
73
67
  end
74
68
 
75
69
  # Adds a backtrace to this span
@@ -195,7 +189,7 @@ module Instana
195
189
  # @return [Instana::SpanContext]
196
190
  #
197
191
  def context
198
- @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], 1, @baggage)
192
+ @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @level, @baggage)
199
193
  end
200
194
 
201
195
  # Retrieve the ID for this span
@@ -344,9 +338,7 @@ module Instana
344
338
  end
345
339
  end
346
340
  else
347
- if !@data[:data].key?(key)
348
- @data[:data][key] = value
349
- elsif value.is_a?(Hash) && self[:data][key].is_a?(Hash)
341
+ if value.is_a?(Hash) && @data[:data][key].is_a?(Hash)
350
342
  @data[:data][key].merge!(value)
351
343
  else
352
344
  @data[:data][key] = value
@@ -381,7 +373,7 @@ module Instana
381
373
  if @context
382
374
  @context.baggage = @baggage
383
375
  else
384
- @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], 1, @baggage)
376
+ @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @level, @baggage)
385
377
  end
386
378
  self
387
379
  end
@@ -393,7 +385,6 @@ module Instana
393
385
  # @return Value of the baggage item
394
386
  #
395
387
  def get_baggage_item(key)
396
- return nil if @baggage.nil?
397
388
  @baggage[key]
398
389
  end
399
390
 
@@ -403,7 +394,7 @@ module Instana
403
394
  if custom?
404
395
  tags = @data[:data][:sdk][:custom][:tags]
405
396
  else
406
- tags = @data[:data][key]
397
+ tags = @data[:data]
407
398
  end
408
399
  key ? tags[key] : tags
409
400
  end