instana 1.11.8 → 1.193.2
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/.editorconfig +10 -0
- data/Rakefile +26 -37
- data/gemfiles/libraries.gemfile +2 -0
- data/lib/instana/agent.rb +6 -0
- data/lib/instana/base.rb +2 -0
- data/lib/instana/config.rb +11 -0
- data/lib/instana/frameworks/cuba.rb +33 -0
- data/lib/instana/frameworks/instrumentation/abstract_mysql_adapter.rb +5 -7
- data/lib/instana/frameworks/instrumentation/action_controller.rb +11 -0
- data/lib/instana/frameworks/instrumentation/action_view.rb +6 -10
- data/lib/instana/frameworks/instrumentation/active_record.rb +4 -4
- data/lib/instana/frameworks/instrumentation/mysql2_adapter.rb +17 -15
- data/lib/instana/frameworks/instrumentation/mysql_adapter.rb +11 -7
- data/lib/instana/frameworks/instrumentation/postgresql_adapter.rb +33 -19
- data/lib/instana/frameworks/roda.rb +41 -0
- data/lib/instana/frameworks/sinatra.rb +17 -0
- data/lib/instana/instrumentation/dalli.rb +9 -14
- data/lib/instana/instrumentation/excon.rb +1 -1
- data/lib/instana/instrumentation/graphql.rb +77 -0
- data/lib/instana/instrumentation/grpc.rb +72 -62
- data/lib/instana/instrumentation/instrumented_request.rb +68 -0
- data/lib/instana/instrumentation/net-http.rb +44 -43
- data/lib/instana/instrumentation/rack.rb +17 -52
- data/lib/instana/instrumentation/redis.rb +15 -18
- data/lib/instana/instrumentation/resque.rb +17 -28
- data/lib/instana/instrumentation/rest-client.rb +3 -13
- data/lib/instana/secrets.rb +42 -0
- data/lib/instana/setup.rb +1 -0
- data/lib/instana/tracer.rb +6 -0
- data/lib/instana/tracing/span.rb +14 -10
- data/lib/instana/util.rb +15 -69
- data/lib/instana/version.rb +1 -1
- data/test/apps/cuba.rb +4 -0
- data/test/apps/roda.rb +3 -0
- data/test/apps/sinatra.rb +4 -0
- data/test/config_test.rb +1 -17
- data/test/frameworks/cuba_test.rb +14 -1
- data/test/frameworks/rack_test.rb +52 -19
- data/test/frameworks/rails/actioncontroller_test.rb +12 -0
- data/test/frameworks/rails/activerecord_test.rb +80 -28
- data/test/frameworks/roda_test.rb +14 -0
- data/test/frameworks/sinatra_test.rb +14 -0
- data/test/instrumentation/excon_test.rb +0 -2
- data/test/instrumentation/graphql_test.rb +116 -0
- data/test/instrumentation/instrumented_request_test.rb +84 -0
- data/test/instrumentation/redis_test.rb +10 -0
- data/test/secrets_test.rb +73 -0
- data/test/test_helper.rb +3 -9
- data/test/tracing/id_management_test.rb +4 -66
- metadata +16 -6
@@ -0,0 +1,68 @@
|
|
1
|
+
# Note: We really only need "cgi/util" here but Ruby 2.4.1 has an issue:
|
2
|
+
# https://bugs.ruby-lang.org/issues/13539
|
3
|
+
require "cgi"
|
4
|
+
|
5
|
+
module Instana
|
6
|
+
class InstrumentedRequest < Rack::Request
|
7
|
+
def skip_trace?
|
8
|
+
# Honor X-Instana-L
|
9
|
+
@env.has_key?('HTTP_X_INSTANA_L') && @env['HTTP_X_INSTANA_L'].start_with?('0')
|
10
|
+
end
|
11
|
+
|
12
|
+
def incoming_context
|
13
|
+
context = {}
|
14
|
+
|
15
|
+
if @env['HTTP_X_INSTANA_T']
|
16
|
+
context[:trace_id] = ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_T'])
|
17
|
+
context[:span_id] = ::Instana::Util.header_to_id(@env['HTTP_X_INSTANA_S']) if @env['HTTP_X_INSTANA_S']
|
18
|
+
context[:level] = @env['HTTP_X_INSTANA_L'][0] if @env['HTTP_X_INSTANA_L']
|
19
|
+
end
|
20
|
+
|
21
|
+
context
|
22
|
+
end
|
23
|
+
|
24
|
+
def extra_header_tags
|
25
|
+
return nil unless ::Instana.agent.extra_headers
|
26
|
+
headers = {}
|
27
|
+
|
28
|
+
::Instana.agent.extra_headers.each do |custom_header|
|
29
|
+
# Headers are available in this format: HTTP_X_CAPTURE_THIS
|
30
|
+
rack_header = 'HTTP_' + custom_header.upcase
|
31
|
+
rack_header.tr!('-', '_')
|
32
|
+
|
33
|
+
headers[custom_header.to_sym] = @env[rack_header] if @env.has_key?(rack_header)
|
34
|
+
end
|
35
|
+
|
36
|
+
headers
|
37
|
+
end
|
38
|
+
|
39
|
+
def request_tags
|
40
|
+
{
|
41
|
+
method: request_method,
|
42
|
+
url: CGI.unescape(path_info),
|
43
|
+
host: host_with_port,
|
44
|
+
header: extra_header_tags
|
45
|
+
}.compact
|
46
|
+
end
|
47
|
+
|
48
|
+
def correlation_data
|
49
|
+
@correlation_data ||= parse_correlation_data
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def parse_correlation_data
|
55
|
+
return {} unless @env.has_key?('HTTP_X_INSTANA_L')
|
56
|
+
_level, *tokens = @env['HTTP_X_INSTANA_L'].split(/[,=;]/)
|
57
|
+
data = tokens
|
58
|
+
.map { |t| t.strip }
|
59
|
+
.each_slice(2)
|
60
|
+
.select { |a| a.length == 2 }.to_h
|
61
|
+
|
62
|
+
{
|
63
|
+
type: data['correlationType'],
|
64
|
+
id: data['correlationId']
|
65
|
+
}.compact
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -1,59 +1,60 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
|
3
3
|
if defined?(::Net::HTTP) && ::Instana.config[:nethttp][:enabled]
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module Instana
|
5
|
+
module NetHTTPInstrumentation
|
6
|
+
def request(*args, &block)
|
7
|
+
if !Instana.tracer.tracing? || !started?
|
8
|
+
do_skip = true
|
9
|
+
return super(*args, &block)
|
10
|
+
end
|
11
11
|
|
12
|
-
|
12
|
+
::Instana.tracer.log_entry(:'net-http')
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
# Send out the tracing context with the request
|
15
|
+
request = args[0]
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
# Set request headers; encode IDs as hexadecimal strings
|
18
|
+
t_context = ::Instana.tracer.context
|
19
|
+
request['X-Instana-T'] = t_context.trace_id_header
|
20
|
+
request['X-Instana-S'] = t_context.span_id_header
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
# Collect up KV info now in case any exception is raised
|
23
|
+
kv_payload = { :http => {} }
|
24
|
+
kv_payload[:http][:method] = request.method
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
if use_ssl?
|
30
|
-
kv_payload[:http][:url] = "https://#{@address}:#{@port}#{request.path}"
|
26
|
+
if request.uri
|
27
|
+
kv_payload[:http][:url] = request.uri.to_s
|
31
28
|
else
|
32
|
-
|
29
|
+
if use_ssl?
|
30
|
+
kv_payload[:http][:url] = "https://#{@address}:#{@port}#{request.path}"
|
31
|
+
else
|
32
|
+
kv_payload[:http][:url] = "http://#{@address}:#{@port}#{request.path}"
|
33
|
+
end
|
33
34
|
end
|
34
|
-
end
|
35
35
|
|
36
|
-
|
37
|
-
response = request_without_instana(*args, &block)
|
36
|
+
kv_payload[:http][:url] = ::Instana.secrets.remove_from_query(kv_payload[:http][:url])
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
# Because of the 5xx response, we flag this span as errored but
|
42
|
-
# without a backtrace (no exception)
|
43
|
-
::Instana.tracer.log_error(nil)
|
44
|
-
end
|
38
|
+
# The core call
|
39
|
+
response = super(*args, &block)
|
45
40
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
41
|
+
kv_payload[:http][:status] = response.code
|
42
|
+
if response.code.to_i.between?(500, 511)
|
43
|
+
# Because of the 5xx response, we flag this span as errored but
|
44
|
+
# without a backtrace (no exception)
|
45
|
+
::Instana.tracer.log_error(nil)
|
46
|
+
end
|
53
47
|
|
54
|
-
|
48
|
+
response
|
49
|
+
rescue => e
|
50
|
+
::Instana.tracer.log_error(e)
|
51
|
+
raise
|
52
|
+
ensure
|
53
|
+
::Instana.tracer.log_exit(:'net-http', kv_payload) unless do_skip
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
55
57
|
|
56
|
-
|
57
|
-
|
58
|
-
}
|
58
|
+
::Instana.logger.debug "Instrumenting Net::HTTP"
|
59
|
+
Net::HTTP.prepend(::Instana::NetHTTPInstrumentation)
|
59
60
|
end
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
# https://bugs.ruby-lang.org/issues/13539
|
3
|
-
require "cgi"
|
1
|
+
require 'instana/instrumentation/instrumented_request'
|
4
2
|
|
5
3
|
module Instana
|
6
4
|
class Rack
|
@@ -8,58 +6,20 @@ module Instana
|
|
8
6
|
@app = app
|
9
7
|
end
|
10
8
|
|
11
|
-
def collect_kvs(env)
|
12
|
-
kvs = {}
|
13
|
-
kvs[:http] = {}
|
14
|
-
kvs[:http][:method] = env['REQUEST_METHOD']
|
15
|
-
kvs[:http][:url] = ::CGI.unescape(env['PATH_INFO'])
|
16
|
-
|
17
|
-
if env.key?('HTTP_HOST')
|
18
|
-
kvs[:http][:host] = env['HTTP_HOST']
|
19
|
-
elsif env.key?('SERVER_NAME')
|
20
|
-
kvs[:http][:host] = env['SERVER_NAME']
|
21
|
-
end
|
22
|
-
|
23
|
-
if ENV.key?('INSTANA_SERVICE_NAME')
|
24
|
-
kvs[:service] = ENV['INSTANA_SERVICE_NAME']
|
25
|
-
end
|
26
|
-
|
27
|
-
if ::Instana.agent.extra_headers
|
28
|
-
::Instana.agent.extra_headers.each { |custom_header|
|
29
|
-
# Headers are available in this format: HTTP_X_CAPTURE_THIS
|
30
|
-
rack_header = 'HTTP_' + custom_header.upcase
|
31
|
-
rack_header.tr!('-', '_')
|
32
|
-
|
33
|
-
if env.key?(rack_header)
|
34
|
-
unless kvs[:http].key?(:header)
|
35
|
-
kvs[:http][:header] = {}
|
36
|
-
end
|
37
|
-
kvs[:http][:header][custom_header.to_sym] = env[rack_header]
|
38
|
-
end
|
39
|
-
}
|
40
|
-
end
|
41
|
-
return kvs
|
42
|
-
end
|
43
|
-
|
44
9
|
def call(env)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
10
|
+
req = InstrumentedRequest.new(env)
|
11
|
+
return @app.call(env) if req.skip_trace?
|
12
|
+
kvs = {
|
13
|
+
http: req.request_tags,
|
14
|
+
service: ENV['INSTANA_SERVICE_NAME']
|
15
|
+
}.compact
|
51
16
|
|
52
|
-
|
53
|
-
if incoming_context[:level] and incoming_context[:level].length > 0
|
54
|
-
if incoming_context[:level][0] == "0"
|
55
|
-
return @app.call(env)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
17
|
+
current_span = ::Instana.tracer.log_start_or_continue(:rack, {}, req.incoming_context)
|
59
18
|
|
60
|
-
|
61
|
-
|
62
|
-
|
19
|
+
unless req.correlation_data.empty?
|
20
|
+
current_span[:crid] = req.correlation_data[:id]
|
21
|
+
current_span[:crtp] = req.correlation_data[:type]
|
22
|
+
end
|
63
23
|
|
64
24
|
status, headers, response = @app.call(env)
|
65
25
|
|
@@ -76,6 +36,11 @@ module Instana
|
|
76
36
|
::Instana.tracer.log_error(nil)
|
77
37
|
end
|
78
38
|
|
39
|
+
# If the framework instrumentation provides a path template,
|
40
|
+
# pass it into the span here.
|
41
|
+
# See: https://www.instana.com/docs/tracing/custom-best-practices/#path-templates-visual-grouping-of-http-endpoints
|
42
|
+
kvs[:http][:path_tpl] = env['INSTANA_HTTP_PATH_TEMPLATE'] if env['INSTANA_HTTP_PATH_TEMPLATE']
|
43
|
+
|
79
44
|
# Save the IDs before the trace ends so we can place
|
80
45
|
# them in the response headers in the ensure block
|
81
46
|
trace_id = ::Instana.tracer.current_span.trace_id
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
def
|
1
|
+
module Instana
|
2
|
+
module RedisInstrumentation
|
3
|
+
def call(*args, &block)
|
4
4
|
kv_payload = { redis: {} }
|
5
5
|
dnt_spans = [:redis, :'resque-client', :'sidekiq-client']
|
6
6
|
|
7
|
-
if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name)
|
8
|
-
return
|
7
|
+
if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name) || !Instana.config[:redis][:enabled]
|
8
|
+
return super(*args, &block)
|
9
9
|
end
|
10
10
|
|
11
11
|
begin
|
@@ -19,7 +19,7 @@ if defined?(::Redis) && ::Instana.config[:redis][:enabled]
|
|
19
19
|
nil
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
super(*args, &block)
|
23
23
|
rescue => e
|
24
24
|
::Instana.tracer.log_info({ redis: {error: true} })
|
25
25
|
::Instana.tracer.log_error(e)
|
@@ -29,17 +29,12 @@ if defined?(::Redis) && ::Instana.config[:redis][:enabled]
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
alias call_without_instana call
|
35
|
-
alias call call_with_instana
|
36
|
-
|
37
|
-
def call_pipeline_with_instana(*args, &block)
|
32
|
+
def call_pipeline(*args, &block)
|
38
33
|
kv_payload = { redis: {} }
|
39
34
|
dnt_spans = [:redis, :'resque-client', :'sidekiq-client']
|
40
35
|
|
41
|
-
if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name)
|
42
|
-
return
|
36
|
+
if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name) || !Instana.config[:redis][:enabled]
|
37
|
+
return super(*args, &block)
|
43
38
|
end
|
44
39
|
|
45
40
|
begin
|
@@ -54,7 +49,7 @@ if defined?(::Redis) && ::Instana.config[:redis][:enabled]
|
|
54
49
|
nil
|
55
50
|
end
|
56
51
|
|
57
|
-
|
52
|
+
super(*args, &block)
|
58
53
|
rescue => e
|
59
54
|
::Instana.tracer.log_info({ redis: {error: true} })
|
60
55
|
::Instana.tracer.log_error(e)
|
@@ -63,8 +58,10 @@ if defined?(::Redis) && ::Instana.config[:redis][:enabled]
|
|
63
58
|
::Instana.tracer.log_exit(:redis, kv_payload)
|
64
59
|
end
|
65
60
|
end
|
66
|
-
|
67
|
-
alias call_pipeline_without_instana call_pipeline
|
68
|
-
alias call_pipeline call_pipeline_with_instana
|
69
61
|
end
|
70
62
|
end
|
63
|
+
|
64
|
+
if defined?(::Redis) && ::Instana.config[:redis][:enabled]
|
65
|
+
::Instana.logger.debug "Instrumenting Redis"
|
66
|
+
Redis::Client.prepend(::Instana::RedisInstrumentation)
|
67
|
+
end
|
@@ -3,11 +3,8 @@ require 'socket'
|
|
3
3
|
module Instana
|
4
4
|
module Instrumentation
|
5
5
|
module ResqueClient
|
6
|
-
def self.
|
6
|
+
def self.prepended(klass)
|
7
7
|
klass.send :extend, ::Resque
|
8
|
-
::Instana::Util.method_alias(klass, :enqueue)
|
9
|
-
::Instana::Util.method_alias(klass, :enqueue_to)
|
10
|
-
::Instana::Util.method_alias(klass, :dequeue)
|
11
8
|
end
|
12
9
|
|
13
10
|
def collect_kvs(op, klass, args)
|
@@ -23,50 +20,46 @@ module Instana
|
|
23
20
|
{ :'resque-client' => kvs }
|
24
21
|
end
|
25
22
|
|
26
|
-
def
|
23
|
+
def enqueue(klass, *args)
|
27
24
|
if Instana.tracer.tracing?
|
28
25
|
kvs = collect_kvs(:enqueue, klass, args)
|
29
26
|
|
30
27
|
Instana.tracer.trace(:'resque-client', kvs) do
|
31
|
-
|
28
|
+
super(klass, *args)
|
32
29
|
end
|
33
30
|
else
|
34
|
-
|
31
|
+
super(klass, *args)
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
38
|
-
def
|
35
|
+
def enqueue_to(queue, klass, *args)
|
39
36
|
if Instana.tracer.tracing? && !Instana.tracer.tracing_span?(:'resque-client')
|
40
37
|
kvs = collect_kvs(:enqueue_to, klass, args)
|
41
38
|
kvs[:Queue] = queue.to_s if queue
|
42
39
|
|
43
40
|
Instana.tracer.trace(:'resque-client', kvs) do
|
44
|
-
|
41
|
+
super(queue, klass, *args)
|
45
42
|
end
|
46
43
|
else
|
47
|
-
|
44
|
+
super(queue, klass, *args)
|
48
45
|
end
|
49
46
|
end
|
50
47
|
|
51
|
-
def
|
48
|
+
def dequeue(klass, *args)
|
52
49
|
if Instana.tracer.tracing?
|
53
50
|
kvs = collect_kvs(:dequeue, klass, args)
|
54
51
|
|
55
52
|
Instana.tracer.trace(:'resque-client', kvs) do
|
56
|
-
|
53
|
+
super(klass, *args)
|
57
54
|
end
|
58
55
|
else
|
59
|
-
|
56
|
+
super(klass, *args)
|
60
57
|
end
|
61
58
|
end
|
62
59
|
end
|
63
60
|
|
64
61
|
module ResqueWorker
|
65
|
-
def
|
66
|
-
::Instana::Util.method_alias(klass, :perform)
|
67
|
-
end
|
68
|
-
|
69
|
-
def perform_with_instana(job)
|
62
|
+
def perform(job)
|
70
63
|
kvs = {}
|
71
64
|
kvs[:'resque-worker'] = {}
|
72
65
|
|
@@ -81,17 +74,13 @@ module Instana
|
|
81
74
|
end
|
82
75
|
|
83
76
|
Instana.tracer.start_or_continue_trace(:'resque-worker', kvs) do
|
84
|
-
|
77
|
+
super(job)
|
85
78
|
end
|
86
79
|
end
|
87
80
|
end
|
88
81
|
|
89
82
|
module ResqueJob
|
90
|
-
def
|
91
|
-
::Instana::Util.method_alias(klass, :fail)
|
92
|
-
end
|
93
|
-
|
94
|
-
def fail_with_instana(exception)
|
83
|
+
def fail(exception)
|
95
84
|
if Instana.tracer.tracing?
|
96
85
|
::Instana.tracer.log_info(:'resque-worker' => { :error => "#{exception.class}: #{exception}"})
|
97
86
|
::Instana.tracer.log_error(exception)
|
@@ -99,7 +88,7 @@ module Instana
|
|
99
88
|
rescue Exception => e
|
100
89
|
::Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" } if Instana::Config[:verbose]
|
101
90
|
ensure
|
102
|
-
|
91
|
+
super(exception)
|
103
92
|
end
|
104
93
|
end
|
105
94
|
end
|
@@ -109,14 +98,14 @@ if defined?(::Resque) && RUBY_VERSION >= '1.9.3'
|
|
109
98
|
|
110
99
|
if ::Instana.config[:'resque-client'][:enabled]
|
111
100
|
::Instana.logger.debug 'Instrumenting Resque Client'
|
112
|
-
::
|
101
|
+
::Resque.prepend(::Instana::Instrumentation::ResqueClient)
|
113
102
|
end
|
114
103
|
|
115
104
|
if ::Instana.config[:'resque-worker'][:enabled]
|
116
105
|
::Instana.logger.debug 'Instrumenting Resque Worker'
|
117
106
|
|
118
|
-
::
|
119
|
-
::
|
107
|
+
::Resque::Worker.prepend(::Instana::Instrumentation::ResqueWorker)
|
108
|
+
::Resque::Job.prepend(::Instana::Instrumentation::ResqueJob)
|
120
109
|
|
121
110
|
::Resque.before_fork do |job|
|
122
111
|
::Instana.agent.before_resque_fork
|