instana 1.195.4 → 1.198.0

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 (90) 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 +62 -0
  8. data/lib/instana/backend/gc_snapshot.rb +41 -0
  9. data/lib/instana/backend/host_agent.rb +74 -0
  10. data/lib/instana/backend/host_agent_activation_observer.rb +97 -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 +74 -0
  15. data/lib/instana/backend/serverless_agent.rb +113 -0
  16. data/lib/instana/base.rb +10 -27
  17. data/lib/instana/config.rb +8 -22
  18. data/lib/instana/instrumentation/excon.rb +7 -5
  19. data/lib/instana/instrumentation/instrumented_request.rb +62 -7
  20. data/lib/instana/instrumentation/net-http.rb +7 -5
  21. data/lib/instana/instrumentation/rack.rb +12 -7
  22. data/lib/instana/logger_delegator.rb +31 -0
  23. data/lib/instana/{opentracing → open_tracing}/carrier.rb +0 -0
  24. data/lib/instana/open_tracing/instana_tracer.rb +99 -0
  25. data/lib/instana/secrets.rb +6 -2
  26. data/lib/instana/serverless.rb +139 -0
  27. data/lib/instana/setup.rb +23 -11
  28. data/lib/instana/snapshot/deltable.rb +25 -0
  29. data/lib/instana/snapshot/docker_container.rb +151 -0
  30. data/lib/instana/snapshot/fargate_container.rb +88 -0
  31. data/lib/instana/snapshot/fargate_process.rb +67 -0
  32. data/lib/instana/snapshot/fargate_task.rb +72 -0
  33. data/lib/instana/snapshot/lambda_function.rb +39 -0
  34. data/lib/instana/snapshot/ruby_process.rb +48 -0
  35. data/lib/instana/tracer.rb +25 -143
  36. data/lib/instana/tracing/processor.rb +14 -22
  37. data/lib/instana/tracing/span.rb +33 -36
  38. data/lib/instana/tracing/span_context.rb +15 -10
  39. data/lib/instana/util.rb +8 -69
  40. data/lib/instana/version.rb +1 -1
  41. data/lib/opentracing.rb +26 -3
  42. data/test/backend/agent_test.rb +67 -0
  43. data/test/backend/gc_snapshot_test.rb +11 -0
  44. data/test/backend/host_agent_activation_observer_test.rb +72 -0
  45. data/test/backend/host_agent_lookup_test.rb +78 -0
  46. data/test/backend/host_agent_reporting_observer_test.rb +192 -0
  47. data/test/backend/host_agent_test.rb +47 -0
  48. data/test/backend/process_info_test.rb +63 -0
  49. data/test/backend/request_client_test.rb +39 -0
  50. data/test/backend/serverless_agent_test.rb +73 -0
  51. data/test/config_test.rb +10 -0
  52. data/test/instana_test.rb +11 -4
  53. data/test/instrumentation/rack_instrumented_request_test.rb +5 -2
  54. data/test/instrumentation/rack_test.rb +2 -14
  55. data/test/secrets_test.rb +41 -22
  56. data/test/serverless_test.rb +323 -0
  57. data/test/snapshot/deltable_test.rb +17 -0
  58. data/test/snapshot/docker_container_test.rb +82 -0
  59. data/test/snapshot/fargate_container_test.rb +82 -0
  60. data/test/snapshot/fargate_process_test.rb +35 -0
  61. data/test/snapshot/fargate_task_test.rb +49 -0
  62. data/test/snapshot/lambda_function_test.rb +37 -0
  63. data/test/snapshot/ruby_process_test.rb +14 -0
  64. data/test/support/mock_timer.rb +20 -0
  65. data/test/test_helper.rb +16 -4
  66. data/test/tracing/custom_test.rb +1 -3
  67. data/test/tracing/id_management_test.rb +8 -0
  68. data/test/tracing/opentracing_test.rb +15 -2
  69. data/test/tracing/processor_test.rb +58 -0
  70. data/test/tracing/span_context_test.rb +22 -0
  71. data/test/tracing/span_test.rb +136 -0
  72. data/test/tracing/tracer_async_test.rb +29 -0
  73. data/test/tracing/tracer_test.rb +82 -16
  74. data/test/util_test.rb +10 -0
  75. metadata +76 -43
  76. data/lib/instana/agent.rb +0 -508
  77. data/lib/instana/agent/helpers.rb +0 -87
  78. data/lib/instana/agent/hooks.rb +0 -44
  79. data/lib/instana/agent/tasks.rb +0 -51
  80. data/lib/instana/collector.rb +0 -119
  81. data/lib/instana/collectors/gc.rb +0 -60
  82. data/lib/instana/collectors/memory.rb +0 -37
  83. data/lib/instana/collectors/thread.rb +0 -33
  84. data/lib/instana/eum/eum-test.js.erb +0 -17
  85. data/lib/instana/eum/eum.js.erb +0 -17
  86. data/lib/instana/helpers.rb +0 -47
  87. data/lib/instana/opentracing/tracer.rb +0 -21
  88. data/lib/instana/thread_local.rb +0 -18
  89. data/lib/oj_check.rb +0 -19
  90. data/test/agent/agent_test.rb +0 -151
@@ -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!
@@ -5,7 +5,7 @@ require 'thread'
5
5
 
6
6
  module Instana
7
7
  class Processor
8
- def initialize
8
+ def initialize(logger: ::Instana.logger)
9
9
  # The main queue before being reported to the
10
10
  # host agent. Spans in this queue are complete
11
11
  # and ready to be sent.
@@ -14,25 +14,22 @@ module Instana
14
14
  # This is the maximum number of spans we send to the host
15
15
  # agent at once.
16
16
  @batch_size = 3000
17
- end
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)}
17
+ @logger = logger
18
+ @pid = $PROCESS_ID
24
19
  end
25
20
 
26
21
  # Adds a span to the span queue
27
22
  #
28
23
  # @param [Trace] - the trace to be added to the queue
29
24
  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
25
+ # :nocov:
26
+ if @pid != $PROCESS_ID
27
+ @logger.info("Proces `#{@pid}` has forked into #{$PROCESS_ID}. Resetting discovery.")
28
+ ::Instana.agent.spawn_background_thread
29
+ @pid = $PROCESS_ID
35
30
  end
31
+ # :nocov:
32
+
36
33
  @queue.push(span)
37
34
  end
38
35
 
@@ -46,18 +43,14 @@ module Instana
46
43
  # - Out of control/growing queue
47
44
  # - Prevent another run of the timer while this is running
48
45
  #
49
- def send
46
+ def send(&block)
50
47
  return if @queue.empty? || ENV.key?('INSTANA_TEST')
51
48
 
52
49
  # Retrieve all spans for queued traces
53
50
  spans = queued_spans
54
51
 
55
52
  # 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
53
+ spans.each_slice(@batch_size, &block)
61
54
  end
62
55
 
63
56
  # Retrieves all of the traces in @queue and returns
@@ -75,10 +68,9 @@ module Instana
75
68
  until @queue.empty? do
76
69
  # Non-blocking pop; ignore exception
77
70
  span = @queue.pop(true) rescue nil
78
- if span
79
- spans << span.raw
80
- end
71
+ spans << span.raw if span.is_a?(Span) && span.context.level == 1
81
72
  end
73
+
82
74
  spans
83
75
  end
84
76
 
@@ -6,8 +6,8 @@ module Instana
6
6
  REGISTERED_SPANS = [ :actioncontroller, :actionview, :activerecord, :excon,
7
7
  :memcache, :'net-http', :rack, :render, :'rpc-client',
8
8
  :'rpc-server', :'sidekiq-client', :'sidekiq-worker',
9
- :redis, :'resque-client', :'resque-worker', :'graphql.server', :dynamodb, :s3, :sns, :sqs ].freeze
10
- ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server', :sqs ].freeze
9
+ :redis, :'resque-client', :'resque-worker', :'graphql.server', :dynamodb, :s3, :sns, :sqs, :'aws.lambda.entry' ].freeze
10
+ ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server', :sqs, :'aws.lambda.entry' ].freeze
11
11
  EXIT_SPANS = [ :activerecord, :excon, :'net-http', :'resque-client',
12
12
  :'rpc-client', :'sidekiq-client', :redis, :dynamodb, :s3, :sns, :sqs ].freeze
13
13
  HTTP_SPANS = [ :rack, :excon, :'net-http' ].freeze
@@ -20,38 +20,40 @@ 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
36
27
 
37
- @data[:t] = parent_context.trace_id # Trace ID
38
- @data[:s] = ::Instana::Util.generate_id # Span ID
39
- @data[:p] = parent_context.span_id # Parent ID
28
+ if parent_ctx.is_a?(::Instana::SpanContext)
29
+ @is_root = false
40
30
 
41
- if parent_context.baggage
42
- @baggage = parent_ctx.baggage.dup
31
+ # If we have a parent trace, link to it
32
+ if parent_ctx.trace_id
33
+ @data[:t] = parent_ctx.trace_id # Trace ID
34
+ @data[:p] = parent_ctx.span_id # Parent ID
43
35
  else
44
- @baggage = nil
36
+ @data[:t] = ::Instana::Util.generate_id
45
37
  end
46
38
 
47
- @is_root = false
39
+ @data[:s] = ::Instana::Util.generate_id # Span ID
40
+
41
+ @baggage = parent_ctx.baggage.dup
42
+ @level = parent_ctx.level
43
+ else
44
+ # No parent specified so we're starting a new Trace - this will be the root span
45
+ @is_root = true
46
+ @level = 1
47
+
48
+ id = ::Instana::Util.generate_id
49
+ @data[:t] = id # Trace ID
50
+ @data[:s] = id # Span ID
48
51
  end
49
52
 
50
53
  @data[:data] = {}
51
54
 
52
55
  # Entity Source
53
- @data[:f] = { :e => ::Instana.agent.report_pid,
54
- :h => ::Instana.agent.agent_uuid }
56
+ @data[:f] = ::Instana.agent.source
55
57
  # Start time
56
58
  if start_time.is_a?(Time)
57
59
  @data[:ts] = ::Instana::Util.time_to_ms(start_time)
@@ -59,17 +61,15 @@ module Instana
59
61
  @data[:ts] = start_time
60
62
  end
61
63
 
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
64
  # Check for custom tracing
68
65
  if REGISTERED_SPANS.include?(name.to_sym)
69
66
  @data[:n] = name.to_sym
70
67
  else
71
68
  configure_custom(name)
72
69
  end
70
+
71
+ # Attach a backtrace to all exit spans
72
+ add_stack if ::Instana.config[:collect_backtraces] && exit_span?
73
73
  end
74
74
 
75
75
  # Adds a backtrace to this span
@@ -195,7 +195,7 @@ module Instana
195
195
  # @return [Instana::SpanContext]
196
196
  #
197
197
  def context
198
- @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], 1, @baggage)
198
+ @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @level, @baggage)
199
199
  end
200
200
 
201
201
  # Retrieve the ID for this span
@@ -344,9 +344,7 @@ module Instana
344
344
  end
345
345
  end
346
346
  else
347
- if !@data[:data].key?(key)
348
- @data[:data][key] = value
349
- elsif value.is_a?(Hash) && self[:data][key].is_a?(Hash)
347
+ if value.is_a?(Hash) && @data[:data][key].is_a?(Hash)
350
348
  @data[:data][key].merge!(value)
351
349
  else
352
350
  @data[:data][key] = value
@@ -381,7 +379,7 @@ module Instana
381
379
  if @context
382
380
  @context.baggage = @baggage
383
381
  else
384
- @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], 1, @baggage)
382
+ @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @level, @baggage)
385
383
  end
386
384
  self
387
385
  end
@@ -393,7 +391,6 @@ module Instana
393
391
  # @return Value of the baggage item
394
392
  #
395
393
  def get_baggage_item(key)
396
- return nil if @baggage.nil?
397
394
  @baggage[key]
398
395
  end
399
396
 
@@ -403,7 +400,7 @@ module Instana
403
400
  if custom?
404
401
  tags = @data[:data][:sdk][:custom][:tags]
405
402
  else
406
- tags = @data[:data][key]
403
+ tags = @data[:data]
407
404
  end
408
405
  key ? tags[key] : tags
409
406
  end
@@ -18,7 +18,7 @@ module Instana
18
18
  def initialize(tid, sid, level = 1, baggage = {})
19
19
  @trace_id = tid
20
20
  @span_id = sid
21
- @level = level
21
+ @level = Integer(level || 1)
22
22
  @baggage = baggage || {}
23
23
  end
24
24
 
@@ -31,19 +31,22 @@ module Instana
31
31
  end
32
32
 
33
33
  def trace_parent_header
34
- return '' unless valid?
35
-
36
- trace = (@baggage[:external_trace_id] || @trace_id).rjust(32, '0')
37
- parent = @span_id.rjust(16, '0')
34
+ trace = (@baggage[:external_trace_id] || trace_id_header).rjust(32, '0')
35
+ parent = span_id_header.rjust(16, '0')
38
36
  flags = @level == 1 ? "01" : "00"
39
37
 
40
38
  "00-#{trace}-#{parent}-#{flags}"
41
39
  end
42
40
 
43
41
  def trace_state_header
44
- return '' unless valid?
42
+ external_state = @baggage[:external_state] || ''
43
+ state = external_state.split(/,/)
44
+
45
+ if @level == 1
46
+ state = state.reject { |s| s.start_with?('in=') }
47
+ state.unshift("in=#{trace_id_header};#{span_id_header}")
48
+ end
45
49
 
46
- state = ["in=#{trace_id_header};#{span_id_header}", @baggage[:external_state]]
47
50
  state.compact.join(',')
48
51
  end
49
52
 
@@ -51,10 +54,12 @@ module Instana
51
54
  { :trace_id => @trace_id, :span_id => @span_id }
52
55
  end
53
56
 
54
- private
55
-
56
57
  def valid?
57
- @baggage && @trace_id && @span_id
58
+ @baggage && @trace_id && !@trace_id.emtpy?
59
+ end
60
+
61
+ def active?
62
+ @level == 1
58
63
  end
59
64
  end
60
65
  end