instana 1.193.6 → 1.195.4
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +16 -2
- data/Appraisals +13 -1
- data/docker-compose.yml +20 -0
- data/gemfiles/aws_30.gemfile +3 -0
- data/gemfiles/excon_021.gemfile +18 -0
- data/gemfiles/excon_079.gemfile +18 -0
- data/gemfiles/shoryuken_50.gemfile +19 -0
- data/lib/instana/activators/aws_sdk_s3.rb +20 -0
- data/lib/instana/activators/aws_sdk_sns.rb +20 -0
- data/lib/instana/activators/aws_sdk_sqs.rb +20 -0
- data/lib/instana/activators/excon.rb +1 -1
- data/lib/instana/activators/shoryuken.rb +24 -0
- data/lib/instana/config.rb +3 -0
- data/lib/instana/instrumentation/aws_sdk_dynamodb.rb +21 -2
- data/lib/instana/instrumentation/aws_sdk_s3.rb +55 -0
- data/lib/instana/instrumentation/aws_sdk_sns.rb +29 -0
- data/lib/instana/instrumentation/aws_sdk_sqs.rb +98 -0
- data/lib/instana/instrumentation/excon.rb +17 -4
- data/lib/instana/instrumentation/instrumented_request.rb +64 -7
- data/lib/instana/instrumentation/net-http.rb +9 -2
- data/lib/instana/instrumentation/rack.rb +35 -15
- data/lib/instana/instrumentation/shoryuken.rb +44 -0
- data/lib/instana/secrets.rb +2 -2
- data/lib/instana/tracer.rb +14 -11
- data/lib/instana/tracing/span.rb +3 -3
- data/lib/instana/tracing/span_context.rb +25 -1
- data/lib/instana/version.rb +1 -1
- data/test/instrumentation/aws_test.rb +130 -2
- data/test/instrumentation/excon_test.rb +16 -1
- data/test/instrumentation/net_http_test.rb +18 -0
- data/test/instrumentation/rack_instrumented_request_test.rb +50 -3
- data/test/instrumentation/rack_test.rb +141 -0
- data/test/instrumentation/shoryuken_test.rb +47 -0
- data/test/tracing/opentracing_test.rb +3 -3
- metadata +16 -3
- data/Dockerfile +0 -16
@@ -5,12 +5,13 @@ module Instana
|
|
5
5
|
module Instrumentation
|
6
6
|
class Excon < ::Excon::Middleware::Base
|
7
7
|
def request_call(datum)
|
8
|
-
return @stack.request_call(datum) unless
|
8
|
+
return @stack.request_call(datum) unless traceable?
|
9
9
|
|
10
10
|
payload = { :http => {} }
|
11
|
-
path = datum[:path].split('?')
|
11
|
+
path, query = datum[:path].split('?', 2)
|
12
12
|
payload[:http][:url] = ::Instana.secrets.remove_from_query("#{datum[:connection].instance_variable_get(:@socket_key)}#{path}")
|
13
13
|
payload[:http][:method] = datum[:method] if datum.key?(:method)
|
14
|
+
payload[:http][:params] = ::Instana.secrets.remove_from_query(query || '')
|
14
15
|
|
15
16
|
if datum[:pipeline] == true
|
16
17
|
# Pass the context along in the datum so we get back on response
|
@@ -26,11 +27,16 @@ module Instana
|
|
26
27
|
datum[:headers]['X-Instana-T'] = t_context.trace_id_header
|
27
28
|
datum[:headers]['X-Instana-S'] = t_context.span_id_header
|
28
29
|
|
30
|
+
if ::Instana.config[:w3_trace_correlation]
|
31
|
+
datum[:headers]['Traceparent'] = t_context.trace_parent_header
|
32
|
+
datum[:headers]['Tracestate'] = t_context.trace_state_header
|
33
|
+
end
|
34
|
+
|
29
35
|
@stack.request_call(datum)
|
30
36
|
end
|
31
37
|
|
32
38
|
def error_call(datum)
|
33
|
-
return @stack.error_call(datum) unless
|
39
|
+
return @stack.error_call(datum) unless traceable?
|
34
40
|
|
35
41
|
if datum[:pipeline] == true
|
36
42
|
::Instana.tracer.log_async_error(datum[:error], datum[:instana_span])
|
@@ -43,7 +49,7 @@ module Instana
|
|
43
49
|
def response_call(datum)
|
44
50
|
# FIXME: Will connect exceptions call a response?
|
45
51
|
#
|
46
|
-
return @stack.response_call(datum) unless
|
52
|
+
return @stack.response_call(datum) unless traceable?
|
47
53
|
|
48
54
|
result = @stack.response_call(datum)
|
49
55
|
|
@@ -66,6 +72,13 @@ module Instana
|
|
66
72
|
end
|
67
73
|
result
|
68
74
|
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def traceable?
|
79
|
+
::Instana.tracer.tracing? &&
|
80
|
+
(!Instana.tracer.current_span.exit_span? || Instana.tracer.current_span.name == :excon)
|
81
|
+
end
|
69
82
|
end
|
70
83
|
end
|
71
84
|
end
|
@@ -9,19 +9,24 @@ require 'rack/request'
|
|
9
9
|
|
10
10
|
module Instana
|
11
11
|
class InstrumentedRequest < Rack::Request
|
12
|
+
W3_TRACE_PARENT_FORMAT = /00-(?<trace>[0-9a-f]+)-(?<parent>[0-9a-f]+)-(?<flags>[0-9a-f]+)/.freeze
|
13
|
+
INSTANA_TRACE_STATE = /in=(?<trace>[0-9a-f]+);(?<span>[0-9a-f]+)/.freeze
|
14
|
+
|
12
15
|
def skip_trace?
|
13
16
|
# Honor X-Instana-L
|
14
17
|
@env.has_key?('HTTP_X_INSTANA_L') && @env['HTTP_X_INSTANA_L'].start_with?('0')
|
15
18
|
end
|
16
19
|
|
17
20
|
def incoming_context
|
18
|
-
context =
|
21
|
+
context = if @env['HTTP_X_INSTANA_T']
|
22
|
+
context_from_instana_headers
|
23
|
+
elsif @env['HTTP_TRACEPARENT'] && ::Instana.config[:w3_trace_correlation]
|
24
|
+
context_from_trace_parent
|
25
|
+
else
|
26
|
+
{}
|
27
|
+
end
|
19
28
|
|
20
|
-
if @env['
|
21
|
-
context[:trace_id] = ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_T'])
|
22
|
-
context[:span_id] = ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_S']) if @env['HTTP_X_INSTANA_S']
|
23
|
-
context[:level] = @env['HTTP_X_INSTANA_L'][0] if @env['HTTP_X_INSTANA_L']
|
24
|
-
end
|
29
|
+
context[:level] = @env['HTTP_X_INSTANA_L'][0] if @env['HTTP_X_INSTANA_L']
|
25
30
|
|
26
31
|
context
|
27
32
|
end
|
@@ -41,12 +46,17 @@ module Instana
|
|
41
46
|
headers
|
42
47
|
end
|
43
48
|
|
49
|
+
def request_params
|
50
|
+
::Instana.secrets.remove_from_query(@env['QUERY_STRING'])
|
51
|
+
end
|
52
|
+
|
44
53
|
def request_tags
|
45
54
|
{
|
46
55
|
method: request_method,
|
47
56
|
url: CGI.unescape(path_info),
|
48
57
|
host: host_with_port,
|
49
|
-
header: extra_header_tags
|
58
|
+
header: extra_header_tags,
|
59
|
+
params: request_params
|
50
60
|
}.compact
|
51
61
|
end
|
52
62
|
|
@@ -54,8 +64,55 @@ module Instana
|
|
54
64
|
@correlation_data ||= parse_correlation_data
|
55
65
|
end
|
56
66
|
|
67
|
+
def instana_ancestor
|
68
|
+
@instana_ancestor ||= parse_trace_state
|
69
|
+
end
|
70
|
+
|
71
|
+
def continuing_from_trace_parent?
|
72
|
+
incoming_context.include?(:external_trace_id)
|
73
|
+
end
|
74
|
+
|
75
|
+
def synthetic?
|
76
|
+
@env.has_key?('HTTP_X_INSTANA_SYNTHETIC') && @env['HTTP_X_INSTANA_SYNTHETIC'].eql?('1')
|
77
|
+
end
|
78
|
+
|
57
79
|
private
|
58
80
|
|
81
|
+
def context_from_instana_headers
|
82
|
+
{
|
83
|
+
trace_id: ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_T']),
|
84
|
+
span_id: ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_S'])
|
85
|
+
}.compact
|
86
|
+
end
|
87
|
+
|
88
|
+
def context_from_trace_parent
|
89
|
+
return {} unless @env.has_key?('HTTP_TRACEPARENT')
|
90
|
+
matches = @env['HTTP_TRACEPARENT'].match(W3_TRACE_PARENT_FORMAT)
|
91
|
+
return {} unless matches
|
92
|
+
|
93
|
+
{
|
94
|
+
external_trace_id: matches['trace'],
|
95
|
+
external_state: @env['HTTP_TRACESTATE'],
|
96
|
+
trace_id: ::Instana::Util.header_to_id(matches['trace'][16..-1]), # rubocop:disable Style/SlicingWithRange, Lint/RedundantCopDisableDirective
|
97
|
+
span_id: ::Instana::Util.header_to_id(matches['parent'])
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_trace_state
|
102
|
+
return {} unless @env.has_key?('HTTP_TRACESTATE')
|
103
|
+
token = @env['HTTP_TRACESTATE']
|
104
|
+
.split(/,/)
|
105
|
+
.map { |t| t.match(INSTANA_TRACE_STATE) }
|
106
|
+
.reject { |t| t.nil? }
|
107
|
+
.first
|
108
|
+
return {} unless token
|
109
|
+
|
110
|
+
{
|
111
|
+
t: token['trace'],
|
112
|
+
p: token['span']
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
59
116
|
def parse_correlation_data
|
60
117
|
return {} unless @env.has_key?('HTTP_X_INSTANA_L')
|
61
118
|
_level, *tokens = @env['HTTP_X_INSTANA_L'].split(/[,=;]/)
|
@@ -22,12 +22,19 @@ module Instana
|
|
22
22
|
request['X-Instana-T'] = t_context.trace_id_header
|
23
23
|
request['X-Instana-S'] = t_context.span_id_header
|
24
24
|
|
25
|
+
if ::Instana.config[:w3_trace_correlation]
|
26
|
+
request['Traceparent'] = t_context.trace_parent_header
|
27
|
+
request['Tracestate'] = t_context.trace_state_header
|
28
|
+
end
|
29
|
+
|
25
30
|
# Collect up KV info now in case any exception is raised
|
26
31
|
kv_payload = { :http => {} }
|
27
32
|
kv_payload[:http][:method] = request.method
|
28
33
|
|
29
34
|
if request.uri
|
30
|
-
|
35
|
+
uri_without_query = request.uri.dup.tap { |r| r.query = nil }
|
36
|
+
kv_payload[:http][:url] = uri_without_query.to_s.gsub(/\?\z/, '')
|
37
|
+
kv_payload[:http][:params] = ::Instana.secrets.remove_from_query(request.uri.query)
|
31
38
|
else
|
32
39
|
if use_ssl?
|
33
40
|
kv_payload[:http][:url] = "https://#{@address}:#{@port}#{request.path}"
|
@@ -36,7 +43,7 @@ module Instana
|
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
39
|
-
kv_payload[:http][:url] = ::Instana.secrets.remove_from_query(kv_payload[:http][:url])
|
46
|
+
kv_payload[:http][:url] = ::Instana.secrets.remove_from_query(kv_payload[:http][:url]).gsub(/\?\z/, '')
|
40
47
|
|
41
48
|
# The core call
|
42
49
|
response = super(*args, &block)
|
@@ -20,14 +20,26 @@ module Instana
|
|
20
20
|
|
21
21
|
current_span = ::Instana.tracer.log_start_or_continue(:rack, {}, req.incoming_context)
|
22
22
|
|
23
|
-
unless req.correlation_data.empty?
|
24
|
-
current_span[:crid] = req.correlation_data[:id]
|
25
|
-
current_span[:crtp] = req.correlation_data[:type]
|
26
|
-
end
|
27
|
-
|
28
23
|
status, headers, response = @app.call(env)
|
29
24
|
|
30
25
|
if ::Instana.tracer.tracing?
|
26
|
+
unless req.correlation_data.empty?
|
27
|
+
current_span[:crid] = req.correlation_data[:id]
|
28
|
+
current_span[:crtp] = req.correlation_data[:type]
|
29
|
+
end
|
30
|
+
|
31
|
+
if !req.instana_ancestor.empty? && req.continuing_from_trace_parent?
|
32
|
+
current_span[:ia] = req.instana_ancestor
|
33
|
+
end
|
34
|
+
|
35
|
+
if req.continuing_from_trace_parent?
|
36
|
+
current_span[:tp] = true
|
37
|
+
current_span[:lt] = req.incoming_context[:external_trace_id]
|
38
|
+
end
|
39
|
+
|
40
|
+
if req.synthetic?
|
41
|
+
current_span[:sy] = true
|
42
|
+
end
|
31
43
|
# In case some previous middleware returned a string status, make sure that we're dealing with
|
32
44
|
# an integer. In Ruby nil.to_i, "asdfasdf".to_i will always return 0 from Ruby versions 1.8.7 and newer.
|
33
45
|
# So if an 0 status is reported here, it indicates some other issue (e.g. no status from previous middleware)
|
@@ -45,23 +57,31 @@ module Instana
|
|
45
57
|
# See: https://www.instana.com/docs/tracing/custom-best-practices/#path-templates-visual-grouping-of-http-endpoints
|
46
58
|
kvs[:http][:path_tpl] = env['INSTANA_HTTP_PATH_TEMPLATE'] if env['INSTANA_HTTP_PATH_TEMPLATE']
|
47
59
|
|
48
|
-
# Save the
|
60
|
+
# Save the span context before the trace ends so we can place
|
49
61
|
# them in the response headers in the ensure block
|
50
|
-
|
51
|
-
span_id = ::Instana.tracer.current_span.id
|
62
|
+
trace_context = ::Instana.tracer.current_span.context
|
52
63
|
end
|
53
64
|
|
54
65
|
[status, headers, response]
|
55
66
|
rescue Exception => e
|
56
|
-
::Instana.tracer.log_error(e)
|
67
|
+
::Instana.tracer.log_error(e) if ::Instana.tracer.tracing?
|
57
68
|
raise
|
58
69
|
ensure
|
59
|
-
if
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
70
|
+
if ::Instana.tracer.tracing?
|
71
|
+
if headers
|
72
|
+
# Set response headers; encode as hex string
|
73
|
+
headers['X-Instana-T'] = trace_context.trace_id_header
|
74
|
+
headers['X-Instana-S'] = trace_context.span_id_header
|
75
|
+
headers['X-Instana-L'] = '1'
|
76
|
+
|
77
|
+
if ::Instana.config[:w3_trace_correlation]
|
78
|
+
headers['Traceparent'] = trace_context.trace_parent_header
|
79
|
+
headers['Tracestate'] = trace_context.trace_state_header
|
80
|
+
end
|
81
|
+
|
82
|
+
headers['Server-Timing'] = "intid;desc=#{trace_context.trace_id_header}"
|
83
|
+
end
|
84
|
+
|
65
85
|
::Instana.tracer.log_end(:rack, kvs)
|
66
86
|
end
|
67
87
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
module Instrumentation
|
6
|
+
class Shoryuken
|
7
|
+
def call(_worker_instance, _queue, sqs_message, _body, &block)
|
8
|
+
if sqs_message.is_a? Array
|
9
|
+
return yield
|
10
|
+
end
|
11
|
+
|
12
|
+
sqs_tags = {
|
13
|
+
sort: 'entry',
|
14
|
+
queue: sqs_message.queue_url
|
15
|
+
}
|
16
|
+
|
17
|
+
context = incomming_context_from(sqs_message.message_attributes)
|
18
|
+
::Instana.tracer.start_or_continue_trace(:sqs, {sqs: sqs_tags}, context, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def incomming_context_from(attributes)
|
24
|
+
trace_id = try(attributes, 'X_INSTANA_T', 'X_INSTANA_ST')
|
25
|
+
span_id = try(attributes, 'X_INSTANA_S', 'X_INSTANA_SS')
|
26
|
+
level = try(attributes, 'X_INSTANA_L', 'X_INSTANA_SL')
|
27
|
+
|
28
|
+
{
|
29
|
+
trace_id: trace_id,
|
30
|
+
span_id: span_id,
|
31
|
+
level: level
|
32
|
+
}.compact
|
33
|
+
end
|
34
|
+
|
35
|
+
def try(attributes, *args)
|
36
|
+
key = args.detect do |a|
|
37
|
+
attributes && attributes[a] && attributes[a].respond_to?(:string_value)
|
38
|
+
end
|
39
|
+
|
40
|
+
attributes[key].string_value if attributes && key
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/instana/secrets.rb
CHANGED
@@ -10,7 +10,7 @@ module Instana
|
|
10
10
|
return str unless secret_values
|
11
11
|
|
12
12
|
url = URI(str)
|
13
|
-
params = CGI.parse(url.query || '')
|
13
|
+
params = url.scheme ? CGI.parse(url.query || '') : CGI.parse(url.to_s)
|
14
14
|
|
15
15
|
redacted = params.map do |k, v|
|
16
16
|
needs_redaction = secret_values['list']
|
@@ -19,7 +19,7 @@ module Instana
|
|
19
19
|
end
|
20
20
|
|
21
21
|
url.query = URI.encode_www_form(redacted)
|
22
|
-
CGI.unescape(url.to_s)
|
22
|
+
url.scheme ? CGI.unescape(url.to_s) : CGI.unescape(url.query)
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
data/lib/instana/tracer.rb
CHANGED
@@ -38,8 +38,8 @@ module Instana
|
|
38
38
|
# :level specifies data collection level (optional)
|
39
39
|
#
|
40
40
|
def start_or_continue_trace(name, kvs = {}, incoming_context = nil, &block)
|
41
|
-
log_start_or_continue(name, kvs, incoming_context)
|
42
|
-
yield
|
41
|
+
span = log_start_or_continue(name, kvs, incoming_context)
|
42
|
+
yield(span)
|
43
43
|
rescue Exception => e
|
44
44
|
log_error(e)
|
45
45
|
raise
|
@@ -59,8 +59,8 @@ module Instana
|
|
59
59
|
# @param kvs [Hash] list of key values to be reported in this new span
|
60
60
|
#
|
61
61
|
def trace(name, kvs = {}, &block)
|
62
|
-
log_entry(name, kvs)
|
63
|
-
yield
|
62
|
+
span = log_entry(name, kvs)
|
63
|
+
yield(span)
|
64
64
|
rescue Exception => e
|
65
65
|
log_error(e)
|
66
66
|
raise
|
@@ -91,7 +91,15 @@ module Instana
|
|
91
91
|
if incoming_context
|
92
92
|
if incoming_context.is_a?(Hash)
|
93
93
|
if !incoming_context.empty?
|
94
|
-
parent_context = SpanContext.new(
|
94
|
+
parent_context = SpanContext.new(
|
95
|
+
incoming_context[:trace_id],
|
96
|
+
incoming_context[:span_id],
|
97
|
+
incoming_context[:level],
|
98
|
+
{
|
99
|
+
external_trace_id: incoming_context[:external_trace_id],
|
100
|
+
external_state: incoming_context[:external_state]
|
101
|
+
}
|
102
|
+
)
|
95
103
|
end
|
96
104
|
else
|
97
105
|
parent_context = incoming_context
|
@@ -103,12 +111,7 @@ module Instana
|
|
103
111
|
else
|
104
112
|
self.current_span = Span.new(name)
|
105
113
|
end
|
106
|
-
|
107
|
-
if incoming_context.is_a?(Hash) && incoming_context[:correlation] && !incoming_context[:correlation].empty?
|
108
|
-
self.current_span[:crid] = incoming_context[:correlation][:id]
|
109
|
-
self.current_span[:crtp] = incoming_context[:correlation][:type]
|
110
|
-
end
|
111
|
-
|
114
|
+
|
112
115
|
self.current_span.set_tags(kvs) unless kvs.empty?
|
113
116
|
self.current_span
|
114
117
|
end
|
data/lib/instana/tracing/span.rb
CHANGED
@@ -6,10 +6,10 @@ 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 ].freeze
|
10
|
-
ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server' ].freeze
|
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
|
11
11
|
EXIT_SPANS = [ :activerecord, :excon, :'net-http', :'resque-client',
|
12
|
-
:'rpc-client', :'sidekiq-client', :redis, :dynamodb ].freeze
|
12
|
+
:'rpc-client', :'sidekiq-client', :redis, :dynamodb, :s3, :sns, :sqs ].freeze
|
13
13
|
HTTP_SPANS = [ :rack, :excon, :'net-http' ].freeze
|
14
14
|
|
15
15
|
attr_accessor :parent
|
@@ -6,6 +6,7 @@ module Instana
|
|
6
6
|
attr_accessor :trace_id
|
7
7
|
attr_accessor :span_id
|
8
8
|
attr_accessor :baggage
|
9
|
+
attr_reader :level
|
9
10
|
|
10
11
|
# Create a new SpanContext
|
11
12
|
#
|
@@ -18,7 +19,7 @@ module Instana
|
|
18
19
|
@trace_id = tid
|
19
20
|
@span_id = sid
|
20
21
|
@level = level
|
21
|
-
@baggage = baggage
|
22
|
+
@baggage = baggage || {}
|
22
23
|
end
|
23
24
|
|
24
25
|
def trace_id_header
|
@@ -29,8 +30,31 @@ module Instana
|
|
29
30
|
::Instana::Util.id_to_header(@span_id)
|
30
31
|
end
|
31
32
|
|
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')
|
38
|
+
flags = @level == 1 ? "01" : "00"
|
39
|
+
|
40
|
+
"00-#{trace}-#{parent}-#{flags}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def trace_state_header
|
44
|
+
return '' unless valid?
|
45
|
+
|
46
|
+
state = ["in=#{trace_id_header};#{span_id_header}", @baggage[:external_state]]
|
47
|
+
state.compact.join(',')
|
48
|
+
end
|
49
|
+
|
32
50
|
def to_hash
|
33
51
|
{ :trace_id => @trace_id, :span_id => @span_id }
|
34
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def valid?
|
57
|
+
@baggage && @trace_id && @span_id
|
58
|
+
end
|
35
59
|
end
|
36
60
|
end
|