instana 1.197.0.pre1 → 1.199.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.
- checksums.yaml +4 -4
- data/lib/instana/backend/agent.rb +9 -1
- data/lib/instana/backend/host_agent.rb +27 -10
- data/lib/instana/backend/host_agent_activation_observer.rb +17 -7
- data/lib/instana/backend/request_client.rb +6 -16
- data/lib/instana/backend/serverless_agent.rb +13 -18
- data/lib/instana/base.rb +2 -0
- data/lib/instana/config.rb +1 -1
- data/lib/instana/instrumentation/excon.rb +7 -5
- data/lib/instana/instrumentation/instrumented_request.rb +62 -7
- data/lib/instana/instrumentation/net-http.rb +7 -5
- data/lib/instana/instrumentation/rack.rb +12 -7
- data/lib/instana/serverless.rb +139 -0
- data/lib/instana/setup.rb +5 -0
- data/lib/instana/snapshot/google_cloud_run_instance.rb +69 -0
- data/lib/instana/snapshot/google_cloud_run_process.rb +58 -0
- data/lib/instana/snapshot/lambda_function.rb +39 -0
- data/lib/instana/tracing/processor.rb +11 -1
- data/lib/instana/tracing/span.rb +10 -4
- data/lib/instana/tracing/span_context.rb +14 -9
- data/lib/instana/util.rb +4 -2
- data/lib/instana/version.rb +1 -1
- data/test/backend/agent_test.rb +26 -0
- data/test/backend/host_agent_activation_observer_test.rb +16 -9
- data/test/backend/host_agent_test.rb +17 -2
- data/test/backend/request_client_test.rb +0 -22
- data/test/instrumentation/rack_instrumented_request_test.rb +2 -0
- data/test/serverless_test.rb +323 -0
- data/test/snapshot/google_cloud_run_instance_test.rb +74 -0
- data/test/snapshot/google_cloud_run_process_test.rb +33 -0
- data/test/snapshot/lambda_function_test.rb +37 -0
- data/test/test_helper.rb +1 -1
- data/test/tracing/id_management_test.rb +4 -0
- data/test/tracing/span_context_test.rb +3 -3
- data/test/tracing/span_test.rb +9 -0
- metadata +16 -4
@@ -12,7 +12,6 @@ module Instana
|
|
12
12
|
|
13
13
|
def call(env)
|
14
14
|
req = InstrumentedRequest.new(env)
|
15
|
-
return @app.call(env) if req.skip_trace?
|
16
15
|
kvs = {
|
17
16
|
http: req.request_tags,
|
18
17
|
service: ENV['INSTANA_SERVICE_NAME']
|
@@ -34,12 +33,16 @@ module Instana
|
|
34
33
|
|
35
34
|
if req.continuing_from_trace_parent?
|
36
35
|
current_span[:tp] = true
|
37
|
-
|
36
|
+
end
|
37
|
+
|
38
|
+
if req.external_trace_id?
|
39
|
+
current_span[:lt] = req.external_trace_id
|
38
40
|
end
|
39
41
|
|
40
42
|
if req.synthetic?
|
41
43
|
current_span[:sy] = true
|
42
44
|
end
|
45
|
+
|
43
46
|
# In case some previous middleware returned a string status, make sure that we're dealing with
|
44
47
|
# an integer. In Ruby nil.to_i, "asdfasdf".to_i will always return 0 from Ruby versions 1.8.7 and newer.
|
45
48
|
# So if an 0 status is reported here, it indicates some other issue (e.g. no status from previous middleware)
|
@@ -70,15 +73,17 @@ module Instana
|
|
70
73
|
if ::Instana.tracer.tracing?
|
71
74
|
if headers
|
72
75
|
# Set response headers; encode as hex string
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
+
if trace_context.active?
|
77
|
+
headers['X-Instana-T'] = trace_context.trace_id_header
|
78
|
+
headers['X-Instana-S'] = trace_context.span_id_header
|
79
|
+
headers['X-Instana-L'] = '1'
|
76
80
|
|
77
|
-
if ::Instana.config[:w3_trace_correlation]
|
78
|
-
headers['Traceparent'] = trace_context.trace_parent_header
|
79
81
|
headers['Tracestate'] = trace_context.trace_state_header
|
82
|
+
else
|
83
|
+
headers['X-Instana-L'] = '0'
|
80
84
|
end
|
81
85
|
|
86
|
+
headers['Traceparent'] = trace_context.trace_parent_header
|
82
87
|
headers['Server-Timing'] = "intid;desc=#{trace_context.trace_id_header}"
|
83
88
|
end
|
84
89
|
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
require 'base64'
|
5
|
+
require 'zlib'
|
6
|
+
|
7
|
+
# :nocov:
|
8
|
+
begin
|
9
|
+
require 'instana/instrumentation/instrumented_request'
|
10
|
+
rescue LoadError => _e
|
11
|
+
Instana.logger.warn("Unable to Instana::InstrumentedRequest. HTTP based triggers won't generate spans.")
|
12
|
+
end
|
13
|
+
# :nocov:
|
14
|
+
|
15
|
+
module Instana
|
16
|
+
# @since 1.198.0
|
17
|
+
class Serverless
|
18
|
+
def initialize(agent: ::Instana.agent, tracer: ::Instana.tracer, logger: ::Instana.logger)
|
19
|
+
@agent = agent
|
20
|
+
@tracer = tracer
|
21
|
+
@logger = logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def wrap_aws(event, context, &block)
|
25
|
+
Thread.current[:instana_function_arn] = [context.invoked_function_arn, context.function_version].join(':')
|
26
|
+
trigger, event_tags, span_context = trigger_from_event(event)
|
27
|
+
|
28
|
+
tags = {
|
29
|
+
lambda: {
|
30
|
+
arn: context.invoked_function_arn,
|
31
|
+
functionName: context.function_name,
|
32
|
+
functionVersion: context.function_version,
|
33
|
+
runtime: 'ruby',
|
34
|
+
trigger: trigger
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
if event_tags.key?(:http)
|
39
|
+
tags = tags.merge(event_tags)
|
40
|
+
else
|
41
|
+
tags[:lambda] = tags[:lambda].merge(event_tags)
|
42
|
+
end
|
43
|
+
|
44
|
+
@tracer.start_or_continue_trace(:'aws.lambda.entry', tags, span_context, &block)
|
45
|
+
ensure
|
46
|
+
begin
|
47
|
+
@agent.send_bundle
|
48
|
+
rescue StandardError => e
|
49
|
+
@logger.error(e.message)
|
50
|
+
end
|
51
|
+
Thread.current[:instana_function_arn] = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def trigger_from_event(event) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
57
|
+
case event
|
58
|
+
when ->(e) { defined?(::Instana::InstrumentedRequest) && e.is_a?(Hash) && e.key?('requestContext') && e['requestContext'].key?('elb') }
|
59
|
+
request = InstrumentedRequest.new(event_to_rack(event))
|
60
|
+
['aws:application.load.balancer', {http: request.request_tags}, request.incoming_context]
|
61
|
+
when ->(e) { defined?(::Instana::InstrumentedRequest) && e.is_a?(Hash) && e.key?('httpMethod') && e.key?('path') && e.key?('headers') }
|
62
|
+
request = InstrumentedRequest.new(event_to_rack(event))
|
63
|
+
['aws:api.gateway', {http: request.request_tags}, request.incoming_context]
|
64
|
+
when ->(e) { e.is_a?(Hash) && e['source'] == 'aws.events' && e['detail-type'] == 'Scheduled Event' }
|
65
|
+
tags = decode_cloudwatch_events(event)
|
66
|
+
['aws:cloudwatch.events', {cw: tags}, {}]
|
67
|
+
when ->(e) { e.is_a?(Hash) && e.key?('awslogs') }
|
68
|
+
tags = decode_cloudwatch_logs(event)
|
69
|
+
['aws:cloudwatch.logs', {cw: tags}, {}]
|
70
|
+
when ->(e) { e.is_a?(Hash) && e.key?('Records') && e['Records'].is_a?(Array) && e['Records'].first && e['Records'].first['source'] == 'aws:s3' }
|
71
|
+
tags = decode_s3(event)
|
72
|
+
['aws:s3', {s3: tags}, {}]
|
73
|
+
when ->(e) { e.is_a?(Hash) && e.key?('Records') && e['Records'].is_a?(Array) && e['Records'].first && e['Records'].first['source'] == 'aws:sqs' }
|
74
|
+
tags = decode_sqs(event)
|
75
|
+
['aws:sqs', {sqs: tags}, {}]
|
76
|
+
else
|
77
|
+
['aws:api.gateway.noproxy', {}, {}]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def event_to_rack(event)
|
82
|
+
event['headers']
|
83
|
+
.transform_keys { |k| "HTTP_#{k.gsub('-', '_').upcase}" }
|
84
|
+
.merge(
|
85
|
+
'QUERY_STRING' => URI.encode_www_form(event['queryStringParameters'] || {}),
|
86
|
+
'PATH_INFO' => event['path'],
|
87
|
+
'REQUEST_METHOD' => event['httpMethod']
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
def decode_cloudwatch_events(event)
|
92
|
+
{
|
93
|
+
events: {
|
94
|
+
id: event['id'],
|
95
|
+
resources: event['resources']
|
96
|
+
}
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def decode_cloudwatch_logs(event)
|
101
|
+
logs = begin
|
102
|
+
payload = JSON.parse(Zlib::Inflate.inflate(Base64.decode64(event['awslogs']['data'])))
|
103
|
+
|
104
|
+
{
|
105
|
+
group: payload['logGroup'],
|
106
|
+
stream: payload['logStream']
|
107
|
+
}
|
108
|
+
rescue StandardError => e
|
109
|
+
{
|
110
|
+
decodingError: e.message
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
{logs: logs}
|
115
|
+
end
|
116
|
+
|
117
|
+
def decode_s3(event)
|
118
|
+
span_events = event['Records'].map do |record|
|
119
|
+
{
|
120
|
+
name: record['eventName'],
|
121
|
+
bucket: record['s3'] && record['s3']['bucket'] ? record['s3']['bucket']['name'] : nil,
|
122
|
+
object: record['s3'] && record['s3']['object'] ? record['s3']['object']['key'] : nil
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
{events: span_events}
|
127
|
+
end
|
128
|
+
|
129
|
+
def decode_sqs(event)
|
130
|
+
span_events = event['Records'].map do |record|
|
131
|
+
{
|
132
|
+
queue: record['eventSourceARN']
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
{messages: span_events}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/instana/setup.rb
CHANGED
@@ -9,6 +9,8 @@ require "instana/secrets"
|
|
9
9
|
require "instana/tracer"
|
10
10
|
require "instana/tracing/processor"
|
11
11
|
|
12
|
+
require 'instana/serverless'
|
13
|
+
|
12
14
|
require 'instana/activator'
|
13
15
|
|
14
16
|
require 'instana/backend/request_client'
|
@@ -21,6 +23,9 @@ require 'instana/snapshot/fargate_process'
|
|
21
23
|
require 'instana/snapshot/fargate_task'
|
22
24
|
require 'instana/snapshot/fargate_container'
|
23
25
|
require 'instana/snapshot/docker_container'
|
26
|
+
require 'instana/snapshot/lambda_function'
|
27
|
+
require 'instana/snapshot/google_cloud_run_instance'
|
28
|
+
require 'instana/snapshot/google_cloud_run_process'
|
24
29
|
|
25
30
|
require 'instana/backend/host_agent_lookup'
|
26
31
|
require 'instana/backend/host_agent_activation_observer'
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
module Snapshot
|
6
|
+
# @since 1.199
|
7
|
+
class GoogleCloudRunInstance
|
8
|
+
ID = 'com.instana.plugin.gcp.run.revision.instance'.freeze
|
9
|
+
|
10
|
+
def initialize(metadata_uri: 'http://metadata.google.internal')
|
11
|
+
@metadata_uri = URI(metadata_uri)
|
12
|
+
@client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
|
13
|
+
end
|
14
|
+
|
15
|
+
def entity_id
|
16
|
+
lookup('/computeMetadata/v1/instance/id')
|
17
|
+
end
|
18
|
+
|
19
|
+
def data
|
20
|
+
{
|
21
|
+
runtime: 'ruby',
|
22
|
+
region: gcp_region,
|
23
|
+
service: ENV['K_SERVICE'],
|
24
|
+
configuration: ENV['K_CONFIGURATION'],
|
25
|
+
revision: ENV['K_REVISION'],
|
26
|
+
instanceId: entity_id,
|
27
|
+
port: ENV['PORT'],
|
28
|
+
numericProjectId: lookup('/computeMetadata/v1/project/numeric-project-id'),
|
29
|
+
projectId: lookup('/computeMetadata/v1/project/project-id')
|
30
|
+
}.compact
|
31
|
+
end
|
32
|
+
|
33
|
+
def snapshot
|
34
|
+
{
|
35
|
+
name: ID,
|
36
|
+
entityId: entity_id,
|
37
|
+
data: data
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def source
|
42
|
+
{
|
43
|
+
hl: true,
|
44
|
+
cp: 'gcp',
|
45
|
+
e: entity_id
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def host_name
|
50
|
+
"gcp:cloud-run:revision:#{ENV['K_REVISION']}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def gcp_region
|
56
|
+
lookup('/computeMetadata/v1/instance/zone').split('/').last
|
57
|
+
end
|
58
|
+
|
59
|
+
def lookup(resource)
|
60
|
+
path = @metadata_uri.path + resource
|
61
|
+
response = @client.send_request('GET', path, nil, {'Metadata-Flavor' => 'Google'})
|
62
|
+
|
63
|
+
raise "Unable to get `#{path}`. Got `#{response.code}` `#{response['location']}`." unless response.ok?
|
64
|
+
|
65
|
+
response.body
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
module Snapshot
|
6
|
+
# @since 1.199.0
|
7
|
+
class GoogleCloudRunProcess
|
8
|
+
ID = 'com.instana.plugin.process'.freeze
|
9
|
+
|
10
|
+
def initialize(metadata_uri: 'http://metadata.google.internal')
|
11
|
+
@metadata_uri = URI(metadata_uri)
|
12
|
+
@client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
|
13
|
+
@start_time = Time.now
|
14
|
+
end
|
15
|
+
|
16
|
+
def entity_id
|
17
|
+
Process.pid.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def data
|
21
|
+
proc_table = Sys::ProcTable.ps(pid: Process.pid)
|
22
|
+
process = Backend::ProcessInfo.new(proc_table)
|
23
|
+
|
24
|
+
{
|
25
|
+
pid: process.pid.to_i,
|
26
|
+
env: ENV.to_h,
|
27
|
+
exec: process.name,
|
28
|
+
args: process.arguments,
|
29
|
+
user: process.uid,
|
30
|
+
group: process.gid,
|
31
|
+
start: @start_time.to_i * 1000,
|
32
|
+
containerType: 'gcpCloudRunInstance',
|
33
|
+
container: lookup('/computeMetadata/v1/instance/id'),
|
34
|
+
"com.instana.plugin.host.name": "gcp:cloud-run:revision:#{ENV['K_REVISION']}"
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def snapshot
|
39
|
+
{
|
40
|
+
name: ID,
|
41
|
+
entityId: entity_id,
|
42
|
+
data: data
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def lookup(resource)
|
49
|
+
path = @metadata_uri.path + resource
|
50
|
+
response = @client.send_request('GET', path, nil, {'Metadata-Flavor' => 'Google'})
|
51
|
+
|
52
|
+
raise "Unable to get `#{path}`. Got `#{response.code}` `#{response['location']}`." unless response.ok?
|
53
|
+
|
54
|
+
response.body
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
module Snapshot
|
6
|
+
# @since 1.198.0
|
7
|
+
class LambdaFunction
|
8
|
+
ID = "com.instana.plugin.aws.lambda".freeze
|
9
|
+
|
10
|
+
def entity_id
|
11
|
+
Thread.current[:instana_function_arn]
|
12
|
+
end
|
13
|
+
|
14
|
+
def data
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
|
18
|
+
def snapshot
|
19
|
+
{
|
20
|
+
name: ID,
|
21
|
+
entityId: entity_id,
|
22
|
+
data: data
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def source
|
27
|
+
{
|
28
|
+
hl: true,
|
29
|
+
cp: "aws",
|
30
|
+
e: entity_id
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def host_name
|
35
|
+
entity_id
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -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,12 +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
|
+
@logger = logger
|
18
|
+
@pid = $PROCESS_ID
|
17
19
|
end
|
18
20
|
|
19
21
|
# Adds a span to the span queue
|
20
22
|
#
|
21
23
|
# @param [Trace] - the trace to be added to the queue
|
22
24
|
def add_span(span)
|
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
|
30
|
+
end
|
31
|
+
# :nocov:
|
32
|
+
|
23
33
|
@queue.push(span)
|
24
34
|
end
|
25
35
|
|
data/lib/instana/tracing/span.rb
CHANGED
@@ -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
|
@@ -28,9 +28,15 @@ module Instana
|
|
28
28
|
if parent_ctx.is_a?(::Instana::SpanContext)
|
29
29
|
@is_root = false
|
30
30
|
|
31
|
-
|
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
|
35
|
+
else
|
36
|
+
@data[:t] = ::Instana::Util.generate_id
|
37
|
+
end
|
38
|
+
|
32
39
|
@data[:s] = ::Instana::Util.generate_id # Span ID
|
33
|
-
@data[:p] = parent_ctx.span_id # Parent ID
|
34
40
|
|
35
41
|
@baggage = parent_ctx.baggage.dup
|
36
42
|
@level = parent_ctx.level
|
@@ -31,19 +31,22 @@ module Instana
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def trace_parent_header
|
34
|
-
|
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
|
-
|
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 &&
|
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
|