instana 1.195.2 → 1.197.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/.rubocop.yml +6 -2
- data/Rakefile +1 -1
- data/instana.gemspec +3 -7
- data/lib/instana.rb +3 -0
- data/lib/instana/activator.rb +2 -0
- data/lib/instana/backend/agent.rb +60 -0
- data/lib/instana/backend/gc_snapshot.rb +41 -0
- data/lib/instana/backend/host_agent.rb +74 -0
- data/lib/instana/backend/host_agent_activation_observer.rb +97 -0
- data/lib/instana/backend/host_agent_lookup.rb +57 -0
- data/lib/instana/backend/host_agent_reporting_observer.rb +106 -0
- data/lib/instana/backend/process_info.rb +64 -0
- data/lib/instana/backend/request_client.rb +73 -0
- data/lib/instana/backend/serverless_agent.rb +118 -0
- data/lib/instana/base.rb +8 -27
- data/lib/instana/config.rb +8 -22
- data/lib/instana/instrumentation/excon.rb +17 -8
- 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/logger_delegator.rb +31 -0
- data/lib/instana/{opentracing → open_tracing}/carrier.rb +0 -0
- data/lib/instana/open_tracing/instana_tracer.rb +99 -0
- data/lib/instana/secrets.rb +6 -2
- data/lib/instana/setup.rb +20 -11
- data/lib/instana/snapshot/deltable.rb +25 -0
- data/lib/instana/snapshot/docker_container.rb +151 -0
- data/lib/instana/snapshot/fargate_container.rb +88 -0
- data/lib/instana/snapshot/fargate_process.rb +67 -0
- data/lib/instana/snapshot/fargate_task.rb +72 -0
- data/lib/instana/snapshot/lambda_function.rb +36 -0
- data/lib/instana/snapshot/ruby_process.rb +48 -0
- data/lib/instana/tracer.rb +25 -143
- data/lib/instana/tracing/processor.rb +14 -22
- data/lib/instana/tracing/span.rb +31 -34
- data/lib/instana/tracing/span_context.rb +15 -10
- data/lib/instana/util.rb +8 -69
- data/lib/instana/version.rb +1 -1
- data/lib/opentracing.rb +26 -3
- data/test/backend/agent_test.rb +54 -0
- data/test/backend/gc_snapshot_test.rb +11 -0
- data/test/backend/host_agent_activation_observer_test.rb +72 -0
- data/test/backend/host_agent_lookup_test.rb +78 -0
- data/test/backend/host_agent_reporting_observer_test.rb +192 -0
- data/test/backend/host_agent_test.rb +47 -0
- data/test/backend/process_info_test.rb +63 -0
- data/test/backend/request_client_test.rb +39 -0
- data/test/backend/serverless_agent_test.rb +73 -0
- data/test/config_test.rb +10 -0
- data/test/instana_test.rb +11 -4
- data/test/instrumentation/excon_test.rb +15 -1
- data/test/instrumentation/rack_instrumented_request_test.rb +5 -2
- data/test/instrumentation/rack_test.rb +2 -14
- data/test/secrets_test.rb +41 -22
- data/test/snapshot/deltable_test.rb +17 -0
- data/test/snapshot/docker_container_test.rb +82 -0
- data/test/snapshot/fargate_container_test.rb +82 -0
- data/test/snapshot/fargate_process_test.rb +35 -0
- data/test/snapshot/fargate_task_test.rb +49 -0
- data/test/snapshot/ruby_process_test.rb +14 -0
- data/test/support/mock_timer.rb +20 -0
- data/test/test_helper.rb +16 -4
- data/test/tracing/custom_test.rb +1 -3
- data/test/tracing/id_management_test.rb +4 -0
- data/test/tracing/opentracing_test.rb +15 -2
- data/test/tracing/processor_test.rb +58 -0
- data/test/tracing/span_context_test.rb +21 -0
- data/test/tracing/span_test.rb +136 -0
- data/test/tracing/tracer_async_test.rb +29 -0
- data/test/tracing/tracer_test.rb +82 -16
- data/test/util_test.rb +10 -0
- metadata +71 -43
- data/lib/instana/agent.rb +0 -508
- data/lib/instana/agent/helpers.rb +0 -87
- data/lib/instana/agent/hooks.rb +0 -44
- data/lib/instana/agent/tasks.rb +0 -51
- data/lib/instana/collector.rb +0 -119
- data/lib/instana/collectors/gc.rb +0 -60
- data/lib/instana/collectors/memory.rb +0 -37
- data/lib/instana/collectors/thread.rb +0 -33
- data/lib/instana/eum/eum-test.js.erb +0 -17
- data/lib/instana/eum/eum.js.erb +0 -17
- data/lib/instana/helpers.rb +0 -47
- data/lib/instana/opentracing/tracer.rb +0 -21
- data/lib/instana/thread_local.rb +0 -18
- data/lib/oj_check.rb +0 -19
- data/test/agent/agent_test.rb +0 -151
@@ -0,0 +1,64 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
module Backend
|
6
|
+
# Wrapper around {Sys::ProcTable} that adds support for reading the /proc
|
7
|
+
# file system for extra information around containers
|
8
|
+
# @since 1.197.0
|
9
|
+
class ProcessInfo < SimpleDelegator
|
10
|
+
def name
|
11
|
+
cmdline
|
12
|
+
.split(' ').first
|
13
|
+
end
|
14
|
+
|
15
|
+
def arguments
|
16
|
+
_, *arguments = cmdline.split(' ')
|
17
|
+
clean_arguments(arguments)
|
18
|
+
end
|
19
|
+
|
20
|
+
def parent_pid
|
21
|
+
if in_container? && sched_pid != pid
|
22
|
+
sched_pid
|
23
|
+
else
|
24
|
+
pid
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def from_parent_namespace
|
29
|
+
!in_container? || in_container? && sched_pid != pid
|
30
|
+
end
|
31
|
+
|
32
|
+
def cpuset
|
33
|
+
path = "/proc/#{pid}/cpuset"
|
34
|
+
return unless File.exist?(path)
|
35
|
+
|
36
|
+
File.read(path).strip
|
37
|
+
end
|
38
|
+
|
39
|
+
def in_container?
|
40
|
+
!cpuset.nil? && cpuset != '/'
|
41
|
+
end
|
42
|
+
|
43
|
+
def sched_pid
|
44
|
+
path = '/proc/self/sched'
|
45
|
+
return unless File.exist?(path)
|
46
|
+
|
47
|
+
File.read(path).match(/\d+/).to_s.to_i
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def clean_arguments(arguments)
|
53
|
+
return arguments unless RbConfig::CONFIG['host_os'].include?('darwin')
|
54
|
+
|
55
|
+
arguments.reject do |a|
|
56
|
+
if a.include?('=')
|
57
|
+
k, = a.split('=', 2)
|
58
|
+
ENV[k]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
require 'net/http'
|
5
|
+
require 'delegate'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
# :nocov:
|
9
|
+
begin
|
10
|
+
require 'oj'
|
11
|
+
rescue LoadError => _e
|
12
|
+
Instana.logger.warn("Unable to load Oj.")
|
13
|
+
end
|
14
|
+
# :nocov:
|
15
|
+
|
16
|
+
module Instana
|
17
|
+
module Backend
|
18
|
+
# Convince wrapper around {Net::HTTP}.
|
19
|
+
# @since 1.197.0
|
20
|
+
class RequestClient
|
21
|
+
attr_reader :host, :port
|
22
|
+
|
23
|
+
class Response < SimpleDelegator
|
24
|
+
# @return [Hash] the decoded json response
|
25
|
+
def json
|
26
|
+
JSON.parse(body)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Boolean] true if the request was successful
|
30
|
+
def ok?
|
31
|
+
__getobj__.is_a?(Net::HTTPSuccess)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(host, port, use_ssl: false)
|
36
|
+
@host = host
|
37
|
+
@port = port
|
38
|
+
@client = Net::HTTP.start(host, port, use_ssl: use_ssl)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Send a request to the backend. If data is a {Hash},
|
42
|
+
# encode the object as JSON and set the proper headers.
|
43
|
+
#
|
44
|
+
# @param [String] method request method
|
45
|
+
# @param [String] path request path
|
46
|
+
# @param [Hash, String] data request body
|
47
|
+
# @param [Hash] headers extra request headers to send
|
48
|
+
def send_request(method, path, data = nil, headers = {})
|
49
|
+
body = if data.is_a?(Hash) || data.is_a?(Array)
|
50
|
+
headers['Content-Type'] = 'application/json'
|
51
|
+
headers['Accept'] = 'application/json'
|
52
|
+
|
53
|
+
encode_body(data)
|
54
|
+
else
|
55
|
+
headers['Content-Type'] = 'application/octet-stream'
|
56
|
+
|
57
|
+
data
|
58
|
+
end
|
59
|
+
|
60
|
+
response = @client.send_request(method, path, body, headers)
|
61
|
+
Response.new(response)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def encode_body(data)
|
67
|
+
# :nocov:
|
68
|
+
defined?(Oj) ? Oj.dump(data, mode: :strict) : JSON.dump(data)
|
69
|
+
# :nocov:
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2021
|
2
|
+
# (c) Copyright Instana Inc. 2021
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
module Backend
|
6
|
+
# @since 1.197.0
|
7
|
+
class ServerlessAgent
|
8
|
+
DEFAULT_SECRETS = 'contains-ignore-case:key,password,secret'.freeze
|
9
|
+
attr_reader :timer
|
10
|
+
|
11
|
+
# rubocop:disable Metrics/ParameterLists
|
12
|
+
def initialize(snapshots,
|
13
|
+
timer_class: Concurrent::TimerTask,
|
14
|
+
processor: ::Instana.processor,
|
15
|
+
logger: ::Instana.logger,
|
16
|
+
backend_uri: ENV['INSTANA_ENDPOINT_URL'],
|
17
|
+
secrets: ENV.fetch('INSTANA_SECRETS', DEFAULT_SECRETS), headers: ENV.fetch('INSTANA_EXTRA_HTTP_HEADERS', ''))
|
18
|
+
@snapshots = snapshots
|
19
|
+
@processor = processor
|
20
|
+
@logger = logger
|
21
|
+
@timer = timer_class.new(execution_interval: 1, run_now: true) { send_bundle }
|
22
|
+
@backend_uri = URI(backend_uri)
|
23
|
+
@client = Backend::RequestClient.new(@backend_uri.host, @backend_uri.port, use_ssl: @backend_uri.scheme == "https")
|
24
|
+
@secrets = secrets
|
25
|
+
@headers = headers
|
26
|
+
end
|
27
|
+
# rubocop:enable Metrics/ParameterLists
|
28
|
+
|
29
|
+
def setup; end
|
30
|
+
|
31
|
+
def spawn_background_thread
|
32
|
+
@timer.execute
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Boolean] true if the agent able to send spans to the backend
|
36
|
+
def ready?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Hash, NilClass] the backend friendly description of the current in process collector
|
41
|
+
def source
|
42
|
+
return @source if @source
|
43
|
+
|
44
|
+
snapshot = @snapshots.detect { |s| s.respond_to?(:source) }
|
45
|
+
|
46
|
+
if snapshot
|
47
|
+
@source = snapshot.source
|
48
|
+
else
|
49
|
+
@logger.warn('Unable to find a snapshot which provides a source.')
|
50
|
+
{}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Array] extra headers to include in the trace
|
55
|
+
def extra_headers
|
56
|
+
@headers.split(';')
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Hash] values which are removed from urls sent to the backend
|
60
|
+
def secret_values
|
61
|
+
# TODO: Parse from env
|
62
|
+
matcher, *keys = @secrets.split(/[:,]/)
|
63
|
+
{'matcher' => matcher, 'list' => keys}
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def request_headers
|
69
|
+
{
|
70
|
+
'X-Instana-Host' => host_name,
|
71
|
+
'X-Instana-Key' => ENV['INSTANA_AGENT_KEY'],
|
72
|
+
'X-Instana-Time' => (Time.now.to_i * 1000).to_s
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def send_bundle
|
77
|
+
spans = @processor.queued_spans
|
78
|
+
bundle = {
|
79
|
+
spans: spans,
|
80
|
+
metrics: {
|
81
|
+
plugins: agent_snapshots
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
path = "#{@backend_uri.path}/bundle"
|
86
|
+
response = @client.send_request('POST', path, bundle, request_headers)
|
87
|
+
|
88
|
+
return if response.ok?
|
89
|
+
|
90
|
+
@logger.warn("Recived a `#{response.code}` when sending data.")
|
91
|
+
end
|
92
|
+
|
93
|
+
def agent_snapshots
|
94
|
+
@snapshots.map do |snapshot|
|
95
|
+
begin # rubocop:disable Style/RedundantBegin, Lint/RedundantCopDisableDirective
|
96
|
+
snapshot.snapshot
|
97
|
+
rescue StandardError => e
|
98
|
+
@logger.error(e.message)
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end.compact
|
102
|
+
end
|
103
|
+
|
104
|
+
def host_name
|
105
|
+
return @host_name if @host_name
|
106
|
+
|
107
|
+
snapshot = @snapshots.detect { |s| s.respond_to?(:host_name) }
|
108
|
+
|
109
|
+
if snapshot
|
110
|
+
@host_name = snapshot.host_name
|
111
|
+
else
|
112
|
+
@logger.warn('Unable to find a snapshot which provides a host_name.')
|
113
|
+
''
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/instana/base.rb
CHANGED
@@ -4,16 +4,13 @@
|
|
4
4
|
require "logger"
|
5
5
|
require "instana/version"
|
6
6
|
require "instana/util"
|
7
|
-
require "instana/helpers"
|
8
7
|
|
9
8
|
module Instana
|
10
9
|
class << self
|
11
10
|
attr_accessor :agent
|
12
|
-
attr_accessor :collector
|
13
11
|
attr_accessor :tracer
|
14
12
|
attr_accessor :processor
|
15
13
|
attr_accessor :config
|
16
|
-
attr_accessor :logger
|
17
14
|
attr_accessor :pid
|
18
15
|
attr_reader :secrets
|
19
16
|
|
@@ -24,36 +21,20 @@ module Instana
|
|
24
21
|
# to run" state.
|
25
22
|
#
|
26
23
|
def setup
|
27
|
-
@agent = ::Instana::Agent.new
|
24
|
+
@agent = ::Instana::Backend::Agent.new
|
28
25
|
@tracer = ::Instana::Tracer.new
|
29
26
|
@processor = ::Instana::Processor.new
|
30
|
-
@collector = ::Instana::Collector.new
|
31
27
|
@secrets = ::Instana::Secrets.new
|
32
28
|
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Setup the logger as early as possible
|
37
|
-
|
38
|
-
# Default Logger outputs to STDOUT
|
39
|
-
::Instana.logger = Logger.new(STDOUT)
|
40
|
-
|
41
|
-
# Can instead log to a file that is rotated every 10M
|
42
|
-
# ::Instana.logger = Logger.new("instana.log", 10, 1073741824)
|
43
29
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
::Instana.logger.level = Logger::DEBUG
|
48
|
-
elsif ENV.key?('INSTANA_QUIET')
|
49
|
-
::Instana.logger.level = Logger::FATAL
|
50
|
-
else
|
51
|
-
::Instana.logger.level = Logger::WARN
|
52
|
-
end
|
30
|
+
def logger
|
31
|
+
@logger ||= ::Instana::LoggerDelegator.new(Logger.new(STDOUT))
|
32
|
+
end
|
53
33
|
|
54
|
-
|
55
|
-
|
34
|
+
def logger=(val)
|
35
|
+
@logger.__setobj__(val)
|
36
|
+
end
|
37
|
+
end
|
56
38
|
end
|
57
39
|
|
58
|
-
|
59
40
|
::Instana.logger.info "Stan is on the scene. Starting Instana instrumentation version #{::Instana::VERSION}"
|
data/lib/instana/config.rb
CHANGED
@@ -3,26 +3,21 @@
|
|
3
3
|
|
4
4
|
module Instana
|
5
5
|
class Config
|
6
|
-
|
7
|
-
def initialize
|
6
|
+
def initialize(logger: ::Instana.logger, agent_host: ENV['INSTANA_AGENT_HOST'], agent_port: ENV['INSTANA_AGENT_PORT'])
|
8
7
|
@config = {}
|
9
|
-
if
|
10
|
-
|
11
|
-
@config[:agent_host] =
|
8
|
+
if agent_host
|
9
|
+
logger.debug "Using custom agent host location specified in INSTANA_AGENT_HOST (#{ENV['INSTANA_AGENT_HOST']})"
|
10
|
+
@config[:agent_host] = agent_host
|
12
11
|
else
|
13
12
|
@config[:agent_host] = '127.0.0.1'
|
14
13
|
end
|
15
|
-
if
|
16
|
-
|
17
|
-
@config[:agent_port] =
|
14
|
+
if agent_port
|
15
|
+
logger.debug "Using custom agent port specified in INSTANA_AGENT_PORT (#{ENV['INSTANA_AGENT_PORT']})"
|
16
|
+
@config[:agent_port] = agent_port
|
18
17
|
else
|
19
18
|
@config[:agent_port] = 42699
|
20
19
|
end
|
21
20
|
|
22
|
-
# This option has been DEPRECATED. Use the INSTANA_DISABLE environment variable instead.
|
23
|
-
# https://docs.instana.io/ecosystem/ruby/configuration/
|
24
|
-
@config[:enabled] = true
|
25
|
-
|
26
21
|
# Enable/disable metrics globally or individually (default: all enabled)
|
27
22
|
@config[:metrics] = { :enabled => true }
|
28
23
|
@config[:metrics][:gc] = { :enabled => true }
|
@@ -56,7 +51,7 @@ module Instana
|
|
56
51
|
@config[:sanitize_sql] = true
|
57
52
|
|
58
53
|
# W3 Trace Context Support
|
59
|
-
@config[:w3_trace_correlation] = ENV
|
54
|
+
@config[:w3_trace_correlation] = ENV['INSTANA_DISABLE_W3C_TRACE_CORRELATION'].nil?
|
60
55
|
|
61
56
|
@config[:action_controller] = { :enabled => true }
|
62
57
|
@config[:action_view] = { :enabled => true }
|
@@ -80,15 +75,6 @@ module Instana
|
|
80
75
|
|
81
76
|
def []=(key, value)
|
82
77
|
@config[key.to_sym] = value
|
83
|
-
|
84
|
-
if key == :enabled
|
85
|
-
# Configuring global enable/disable flag, then set the
|
86
|
-
# appropriate children flags.
|
87
|
-
@config[:metrics][:enabled] = value
|
88
|
-
@config[:tracing][:enabled] = value
|
89
|
-
|
90
|
-
::Instana.logger.warn "::Instana.config[:enabled] has been deprecated. Set INSTANA_DISABLE environment variable to any value instead."
|
91
|
-
end
|
92
78
|
end
|
93
79
|
end
|
94
80
|
end
|
@@ -5,7 +5,7 @@ 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
11
|
path, query = datum[:path].split('?', 2)
|
@@ -24,19 +24,21 @@ module Instana
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Set request headers; encode IDs as hexadecimal strings
|
27
|
-
datum[:headers]['X-Instana-
|
28
|
-
datum[:headers]['X-Instana-S'] = t_context.span_id_header
|
27
|
+
datum[:headers]['X-Instana-L'] = t_context.level.to_s
|
29
28
|
|
30
|
-
if
|
31
|
-
datum[:headers]['
|
32
|
-
datum[:headers]['
|
29
|
+
if t_context.active?
|
30
|
+
datum[:headers]['X-Instana-T'] = t_context.trace_id_header
|
31
|
+
datum[:headers]['X-Instana-S'] = t_context.span_id_header
|
33
32
|
end
|
34
33
|
|
34
|
+
datum[:headers]['Traceparent'] = t_context.trace_parent_header
|
35
|
+
datum[:headers]['Tracestate'] = t_context.trace_state_header unless t_context.trace_state_header.empty?
|
36
|
+
|
35
37
|
@stack.request_call(datum)
|
36
38
|
end
|
37
39
|
|
38
40
|
def error_call(datum)
|
39
|
-
return @stack.error_call(datum) unless
|
41
|
+
return @stack.error_call(datum) unless traceable?
|
40
42
|
|
41
43
|
if datum[:pipeline] == true
|
42
44
|
::Instana.tracer.log_async_error(datum[:error], datum[:instana_span])
|
@@ -49,7 +51,7 @@ module Instana
|
|
49
51
|
def response_call(datum)
|
50
52
|
# FIXME: Will connect exceptions call a response?
|
51
53
|
#
|
52
|
-
return @stack.response_call(datum) unless
|
54
|
+
return @stack.response_call(datum) unless traceable?
|
53
55
|
|
54
56
|
result = @stack.response_call(datum)
|
55
57
|
|
@@ -72,6 +74,13 @@ module Instana
|
|
72
74
|
end
|
73
75
|
result
|
74
76
|
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def traceable?
|
81
|
+
::Instana.tracer.tracing? &&
|
82
|
+
(!Instana.tracer.current_span.exit_span? || Instana.tracer.current_span.name == :excon)
|
83
|
+
end
|
75
84
|
end
|
76
85
|
end
|
77
86
|
end
|
@@ -18,16 +18,33 @@ module Instana
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def incoming_context
|
21
|
-
context = if
|
21
|
+
context = if !correlation_data.empty?
|
22
|
+
{}
|
23
|
+
elsif @env['HTTP_X_INSTANA_T']
|
22
24
|
context_from_instana_headers
|
23
|
-
elsif @env['HTTP_TRACEPARENT']
|
25
|
+
elsif @env['HTTP_TRACEPARENT']
|
24
26
|
context_from_trace_parent
|
27
|
+
elsif @env['HTTP_TRACESTATE']
|
28
|
+
context_from_trace_state
|
25
29
|
else
|
26
30
|
{}
|
27
31
|
end
|
28
32
|
|
29
33
|
context[:level] = @env['HTTP_X_INSTANA_L'][0] if @env['HTTP_X_INSTANA_L']
|
30
34
|
|
35
|
+
unless ::Instana.config[:w3_trace_correlation]
|
36
|
+
trace_state = parse_trace_state
|
37
|
+
|
38
|
+
if context[:from_w3] && trace_state.empty?
|
39
|
+
context.delete(:span_id)
|
40
|
+
context[:from_w3] = false
|
41
|
+
elsif context[:from_w3] && !trace_state.empty?
|
42
|
+
context[:trace_id] = trace_state[:t]
|
43
|
+
context[:span_id] = trace_state[:p]
|
44
|
+
context[:from_w3] = false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
31
48
|
context
|
32
49
|
end
|
33
50
|
|
@@ -69,19 +86,43 @@ module Instana
|
|
69
86
|
end
|
70
87
|
|
71
88
|
def continuing_from_trace_parent?
|
72
|
-
incoming_context
|
89
|
+
incoming_context[:from_w3]
|
73
90
|
end
|
74
91
|
|
75
92
|
def synthetic?
|
76
93
|
@env.has_key?('HTTP_X_INSTANA_SYNTHETIC') && @env['HTTP_X_INSTANA_SYNTHETIC'].eql?('1')
|
77
94
|
end
|
78
95
|
|
96
|
+
def long_instana_id?
|
97
|
+
::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_T']).length == 32
|
98
|
+
end
|
99
|
+
|
100
|
+
def external_trace_id?
|
101
|
+
continuing_from_trace_parent? || long_instana_id?
|
102
|
+
end
|
103
|
+
|
104
|
+
def external_trace_id
|
105
|
+
incoming_context[:long_instana_id] || incoming_context[:external_trace_id]
|
106
|
+
end
|
107
|
+
|
79
108
|
private
|
80
109
|
|
81
110
|
def context_from_instana_headers
|
111
|
+
sanitized_t = ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_T'])
|
112
|
+
sanitized_s = ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_S'])
|
113
|
+
external_trace_id = if @env['HTTP_TRACEPARENT']
|
114
|
+
context_from_trace_parent[:external_trace_id]
|
115
|
+
elsif long_instana_id?
|
116
|
+
sanitized_t
|
117
|
+
end
|
118
|
+
|
82
119
|
{
|
83
|
-
|
84
|
-
|
120
|
+
span_id: sanitized_s,
|
121
|
+
trace_id: long_instana_id? ? sanitized_t[16..-1] : sanitized_t, # rubocop:disable Style/SlicingWithRange, Lint/RedundantCopDisableDirective
|
122
|
+
long_instana_id: long_instana_id? ? sanitized_t : nil,
|
123
|
+
external_trace_id: external_trace_id,
|
124
|
+
external_state: @env['HTTP_TRACESTATE'],
|
125
|
+
from_w3: false
|
85
126
|
}.compact
|
86
127
|
end
|
87
128
|
|
@@ -90,14 +131,28 @@ module Instana
|
|
90
131
|
matches = @env['HTTP_TRACEPARENT'].match(W3_TRACE_PARENT_FORMAT)
|
91
132
|
return {} unless matches
|
92
133
|
|
134
|
+
trace_id = ::Instana::Util.header_to_id(matches['trace'][16..-1]) # rubocop:disable Style/SlicingWithRange, Lint/RedundantCopDisableDirective
|
135
|
+
span_id = ::Instana::Util.header_to_id(matches['parent'])
|
136
|
+
|
93
137
|
{
|
94
138
|
external_trace_id: matches['trace'],
|
95
139
|
external_state: @env['HTTP_TRACESTATE'],
|
96
|
-
trace_id:
|
97
|
-
span_id:
|
140
|
+
trace_id: trace_id,
|
141
|
+
span_id: span_id,
|
142
|
+
from_w3: true
|
98
143
|
}
|
99
144
|
end
|
100
145
|
|
146
|
+
def context_from_trace_state
|
147
|
+
state = parse_trace_state
|
148
|
+
|
149
|
+
{
|
150
|
+
trace_id: state[:t],
|
151
|
+
span_id: state[:p],
|
152
|
+
from_w3: false
|
153
|
+
}.compact
|
154
|
+
end
|
155
|
+
|
101
156
|
def parse_trace_state
|
102
157
|
return {} unless @env.has_key?('HTTP_TRACESTATE')
|
103
158
|
token = @env['HTTP_TRACESTATE']
|