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
@@ -1,34 +1,24 @@
|
|
1
1
|
module Instana
|
2
2
|
module Instrumentation
|
3
3
|
module RestClientRequest
|
4
|
-
def
|
5
|
-
if klass.method_defined?(:execute)
|
6
|
-
klass.class_eval do
|
7
|
-
alias execute_without_instana execute
|
8
|
-
alias execute execute_with_instana
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute_with_instana & block
|
4
|
+
def execute(&block)
|
14
5
|
# Since RestClient uses net/http under the covers, we just
|
15
6
|
# provide span visibility here. HTTP related KVs are reported
|
16
7
|
# in the Net::HTTP instrumentation
|
17
8
|
::Instana.tracer.log_entry(:'rest-client')
|
18
9
|
|
19
|
-
|
10
|
+
super(&block)
|
20
11
|
rescue => e
|
21
12
|
::Instana.tracer.log_error(e)
|
22
13
|
raise
|
23
14
|
ensure
|
24
15
|
::Instana.tracer.log_exit(:'rest-client')
|
25
16
|
end
|
26
|
-
|
27
17
|
end
|
28
18
|
end
|
29
19
|
end
|
30
20
|
|
31
21
|
if defined?(::RestClient::Request) && ::Instana.config[:'rest-client'][:enabled]
|
32
22
|
::Instana.logger.debug "Instrumenting RestClient"
|
33
|
-
::RestClient::Request.send(:
|
23
|
+
::RestClient::Request.send(:prepend, ::Instana::Instrumentation::RestClientRequest)
|
34
24
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Instana
|
5
|
+
class Secrets
|
6
|
+
def remove_from_query(str, secret_values = Instana.agent.secret_values)
|
7
|
+
return str unless secret_values
|
8
|
+
|
9
|
+
url = URI(str)
|
10
|
+
params = CGI.parse(url.query || '')
|
11
|
+
|
12
|
+
redacted = params.map do |k, v|
|
13
|
+
needs_redaction = secret_values['list']
|
14
|
+
.any? { |t| matcher(secret_values['matcher']).(t,k) }
|
15
|
+
[k, needs_redaction ? '<redacted>' : v]
|
16
|
+
end
|
17
|
+
|
18
|
+
url.query = URI.encode_www_form(redacted)
|
19
|
+
CGI.unescape(url.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def matcher(name)
|
25
|
+
case name
|
26
|
+
when 'equals-ignore-case'
|
27
|
+
->(expected, actual) { expected.casecmp(actual) == 0 }
|
28
|
+
when 'equals'
|
29
|
+
->(expected, actual) { (expected <=> actual) == 0 }
|
30
|
+
when 'contains-ignore-case'
|
31
|
+
->(expected, actual) { actual.downcase.include?(expected) }
|
32
|
+
when 'contains'
|
33
|
+
->(expected, actual) { actual.include?(expected) }
|
34
|
+
when 'regex'
|
35
|
+
->(expected, actual) { !Regexp.new(expected).match(actual).nil? }
|
36
|
+
else
|
37
|
+
::Instana.logger.warn("Matcher #{name} is not supported.")
|
38
|
+
lambda { false }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/instana/setup.rb
CHANGED
data/lib/instana/tracer.rb
CHANGED
@@ -100,6 +100,12 @@ module Instana
|
|
100
100
|
else
|
101
101
|
self.current_span = Span.new(name)
|
102
102
|
end
|
103
|
+
|
104
|
+
if incoming_context.is_a?(Hash) && incoming_context[:correlation] && !incoming_context[:correlation].empty?
|
105
|
+
self.current_span[:crid] = incoming_context[:correlation][:id]
|
106
|
+
self.current_span[:crtp] = incoming_context[:correlation][:type]
|
107
|
+
end
|
108
|
+
|
103
109
|
self.current_span.set_tags(kvs) unless kvs.empty?
|
104
110
|
self.current_span
|
105
111
|
end
|
data/lib/instana/tracing/span.rb
CHANGED
@@ -3,8 +3,8 @@ module Instana
|
|
3
3
|
REGISTERED_SPANS = [ :actioncontroller, :actionview, :activerecord, :excon,
|
4
4
|
:memcache, :'net-http', :rack, :render, :'rpc-client',
|
5
5
|
:'rpc-server', :'sidekiq-client', :'sidekiq-worker',
|
6
|
-
:redis, :'resque-client', :'resque-worker' ].freeze
|
7
|
-
ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker' ].freeze
|
6
|
+
:redis, :'resque-client', :'resque-worker', :'graphql.server' ].freeze
|
7
|
+
ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server' ].freeze
|
8
8
|
EXIT_SPANS = [ :activerecord, :excon, :'net-http', :'resque-client',
|
9
9
|
:'rpc-client', :'sidekiq-client', :redis ].freeze
|
10
10
|
HTTP_SPANS = [ :rack, :excon, :'net-http' ].freeze
|
@@ -57,9 +57,6 @@ module Instana
|
|
57
57
|
end
|
58
58
|
|
59
59
|
if ::Instana.config[:collect_backtraces]
|
60
|
-
# For entry spans, add a backtrace fingerprint
|
61
|
-
add_stack(limit: 2) if ENTRY_SPANS.include?(name)
|
62
|
-
|
63
60
|
# Attach a backtrace to all exit spans
|
64
61
|
add_stack if EXIT_SPANS.include?(name)
|
65
62
|
end
|
@@ -76,9 +73,11 @@ module Instana
|
|
76
73
|
#
|
77
74
|
# @param limit [Integer] Limit the backtrace to the top <limit> frames
|
78
75
|
#
|
79
|
-
def add_stack(limit:
|
76
|
+
def add_stack(limit: 30, stack: Kernel.caller)
|
80
77
|
frame_count = 0
|
78
|
+
sanitized_stack = []
|
81
79
|
@data[:stack] = []
|
80
|
+
limit = 40 if limit > 40
|
82
81
|
|
83
82
|
stack.each do |i|
|
84
83
|
# If the stack has the full instana gem version in it's path
|
@@ -86,18 +85,23 @@ module Instana
|
|
86
85
|
if !i.match(/instana\/instrumentation\/rack.rb/).nil? ||
|
87
86
|
(i.match(::Instana::VERSION_FULL).nil? && i.match('lib/instana/').nil?)
|
88
87
|
|
89
|
-
break if limit && frame_count >= limit
|
90
|
-
|
91
88
|
x = i.split(':')
|
92
89
|
|
93
|
-
|
90
|
+
sanitized_stack << {
|
94
91
|
:c => x[0],
|
95
92
|
:n => x[1],
|
96
93
|
:m => x[2]
|
97
94
|
}
|
98
|
-
frame_count = frame_count + 1 if limit
|
99
95
|
end
|
100
96
|
end
|
97
|
+
|
98
|
+
if sanitized_stack.length > limit
|
99
|
+
# (limit * -1) gives us negative form of <limit> used for
|
100
|
+
# slicing from the end of the list. e.g. stack[-30, 30]
|
101
|
+
@data[:stack] = sanitized_stack[limit*-1, limit]
|
102
|
+
else
|
103
|
+
@data[:stack] = sanitized_stack
|
104
|
+
end
|
101
105
|
end
|
102
106
|
|
103
107
|
# Log an error into the span
|
data/lib/instana/util.rb
CHANGED
@@ -2,46 +2,6 @@ module Instana
|
|
2
2
|
module Util
|
3
3
|
class << self
|
4
4
|
ID_RANGE = -2**63..2**63-1
|
5
|
-
|
6
|
-
# An agnostic approach to method aliasing.
|
7
|
-
#
|
8
|
-
# @param klass [Object] The class or module that holds the method to be alias'd.
|
9
|
-
# @param method [Symbol] The name of the method to be aliased.
|
10
|
-
#
|
11
|
-
def method_alias(klass, method)
|
12
|
-
if klass.method_defined?(method.to_sym) ||
|
13
|
-
klass.private_method_defined?(method.to_sym)
|
14
|
-
|
15
|
-
with = "#{method}_with_instana"
|
16
|
-
without = "#{method}_without_instana"
|
17
|
-
|
18
|
-
klass.class_eval do
|
19
|
-
alias_method without, method.to_s
|
20
|
-
alias_method method.to_s, with
|
21
|
-
end
|
22
|
-
else
|
23
|
-
::Instana.logger.debug "No such method (#{method}) to alias on #{klass}"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Calls on target_class to 'extend' cls
|
28
|
-
#
|
29
|
-
# @param target_cls [Object] the class/module to do the 'extending'
|
30
|
-
# @param cls [Object] the class/module to be 'extended'
|
31
|
-
#
|
32
|
-
def send_extend(target_cls, cls)
|
33
|
-
target_cls.send(:extend, cls) if defined?(target_cls)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Calls on <target_cls> to include <cls> into itself.
|
37
|
-
#
|
38
|
-
# @param target_cls [Object] the class/module to do the 'including'
|
39
|
-
# @param cls [Object] the class/module to be 'included'
|
40
|
-
#
|
41
|
-
def send_include(target_cls, cls)
|
42
|
-
target_cls.send(:include, cls) if defined?(target_cls)
|
43
|
-
end
|
44
|
-
|
45
5
|
# Debugging helper method
|
46
6
|
#
|
47
7
|
def pry!
|
@@ -225,53 +185,39 @@ module Instana
|
|
225
185
|
(time.to_f * 1000).floor
|
226
186
|
end
|
227
187
|
|
228
|
-
# Generate a random 64bit ID
|
188
|
+
# Generate a random 64bit/128bit ID
|
189
|
+
#
|
190
|
+
# @param size [Integer] Number of 64 bit integers used to generate the id
|
229
191
|
#
|
230
|
-
# @return [
|
192
|
+
# @return [String] a random 64bit/128bit hex encoded string
|
231
193
|
#
|
232
|
-
def generate_id
|
233
|
-
|
234
|
-
|
194
|
+
def generate_id(size = 1)
|
195
|
+
Array.new(size) { rand(ID_RANGE) }
|
196
|
+
.pack('q>*')
|
197
|
+
.unpack('H*')
|
198
|
+
.first
|
235
199
|
end
|
236
200
|
|
237
201
|
# Convert an ID to a value appropriate to pass in a header.
|
238
202
|
#
|
239
|
-
# @param id [
|
203
|
+
# @param id [String] the id to be converted
|
240
204
|
#
|
241
205
|
# @return [String]
|
242
206
|
#
|
243
207
|
def id_to_header(id)
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
end
|
248
|
-
[id.to_i].pack('q>').unpack('H*')[0].gsub(/^0+/, '')
|
249
|
-
rescue => e
|
250
|
-
Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
251
|
-
Instana.logger.debug { e.backtrace.join("\r\n") }
|
208
|
+
return '' unless id.is_a?(String)
|
209
|
+
# Only send 64bit IDs downstream for now
|
210
|
+
id.length == 32 ? id[16..-1] : id
|
252
211
|
end
|
253
212
|
|
254
213
|
# Convert a received header value into a valid ID
|
255
214
|
#
|
256
215
|
# @param header_id [String] the header value to be converted
|
257
216
|
#
|
258
|
-
# @return [
|
217
|
+
# @return [String]
|
259
218
|
#
|
260
219
|
def header_to_id(header_id)
|
261
|
-
|
262
|
-
Instana.logger.debug "header_to_id received a #{header_id.class}: returning 0"
|
263
|
-
return 0
|
264
|
-
end
|
265
|
-
if header_id.length < 16
|
266
|
-
# The header is less than 16 chars. Prepend
|
267
|
-
# zeros so we can convert correctly
|
268
|
-
missing = 16 - header_id.length
|
269
|
-
header_id = ("0" * missing) + header_id
|
270
|
-
end
|
271
|
-
[header_id].pack("H*").unpack("q>")[0]
|
272
|
-
rescue => e
|
273
|
-
Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
274
|
-
Instana.logger.debug { e.backtrace.join("\r\n") }
|
220
|
+
header_id.is_a?(String) && header_id.match(/\A[a-z\d]{16,32}\z/i) ? header_id : ''
|
275
221
|
end
|
276
222
|
end
|
277
223
|
end
|
data/lib/instana/version.rb
CHANGED
data/test/apps/cuba.rb
CHANGED
data/test/apps/roda.rb
CHANGED
data/test/apps/sinatra.rb
CHANGED
data/test/config_test.rb
CHANGED
@@ -10,28 +10,12 @@ class ConfigTest < Minitest::Test
|
|
10
10
|
assert_equal '127.0.0.1', ::Instana.config[:agent_host]
|
11
11
|
assert_equal 42699, ::Instana.config[:agent_port]
|
12
12
|
|
13
|
-
assert ::Instana.config[:enabled]
|
14
13
|
assert ::Instana.config[:tracing][:enabled]
|
15
14
|
assert ::Instana.config[:metrics][:enabled]
|
16
15
|
|
17
16
|
::Instana.config[:metrics].each do |k, v|
|
17
|
+
next unless v.is_a? Hash
|
18
18
|
assert_equal true, ::Instana.config[:metrics][k].key?(:enabled)
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
def test_that_global_affects_children
|
23
|
-
# Disabling the gem should explicitly disable
|
24
|
-
# metrics and tracing flags
|
25
|
-
::Instana.config[:enabled] = false
|
26
|
-
|
27
|
-
assert_equal false, ::Instana.config[:tracing][:enabled]
|
28
|
-
assert_equal false, ::Instana.config[:metrics][:enabled]
|
29
|
-
|
30
|
-
# Enabling the gem should explicitly enable
|
31
|
-
# metrics and tracing flags
|
32
|
-
::Instana.config[:enabled] = true
|
33
|
-
|
34
|
-
assert_equal ::Instana.config[:tracing][:enabled]
|
35
|
-
assert_equal ::Instana.config[:metrics][:enabled]
|
36
|
-
end
|
37
21
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
if defined?(::Cuba)
|
3
2
|
require 'test_helper'
|
4
3
|
require File.expand_path(File.dirname(__FILE__) + '/../apps/cuba')
|
@@ -40,5 +39,19 @@ if defined?(::Cuba)
|
|
40
39
|
assert first_span[:data][:http].key?(:host)
|
41
40
|
assert_equal "example.org", first_span[:data][:http][:host]
|
42
41
|
end
|
42
|
+
|
43
|
+
def test_path_template
|
44
|
+
clear_all!
|
45
|
+
|
46
|
+
r = get '/greet/instana'
|
47
|
+
assert last_response.ok?
|
48
|
+
|
49
|
+
spans = ::Instana.processor.queued_spans
|
50
|
+
assert_equal 1, spans.count
|
51
|
+
|
52
|
+
first_span = spans.first
|
53
|
+
assert_equal :rack, first_span[:n]
|
54
|
+
assert_equal '/greet/{name}', first_span[:data][:http][:path_tpl]
|
55
|
+
end
|
43
56
|
end
|
44
57
|
end
|
@@ -6,15 +6,21 @@ require "instana/rack"
|
|
6
6
|
class RackTest < Minitest::Test
|
7
7
|
include Rack::Test::Methods
|
8
8
|
|
9
|
+
class PathTemplateApp
|
10
|
+
def call(env)
|
11
|
+
env['INSTANA_HTTP_PATH_TEMPLATE'] = 'sample_template'
|
12
|
+
[200, {}, ['Ok']]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
9
16
|
def app
|
10
|
-
@app = Rack::Builder.new
|
17
|
+
@app = Rack::Builder.new do
|
11
18
|
use Rack::CommonLogger
|
12
19
|
use Rack::ShowExceptions
|
13
20
|
use Instana::Rack
|
14
|
-
map
|
15
|
-
|
16
|
-
|
17
|
-
}
|
21
|
+
map("/mrlobster") { run Rack::Lobster.new }
|
22
|
+
map("/path_tpl") { run PathTemplateApp.new }
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
def test_basic_get
|
@@ -51,11 +57,7 @@ class RackTest < Minitest::Test
|
|
51
57
|
assert rack_span[:f].key?(:e)
|
52
58
|
assert rack_span[:f].key?(:h)
|
53
59
|
assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
|
54
|
-
|
55
|
-
# Backtrace fingerprint validation
|
56
|
-
assert rack_span.key?(:stack)
|
57
|
-
assert_equal 2, rack_span[:stack].count
|
58
|
-
refute_nil rack_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
|
60
|
+
assert !rack_span.key?(:stack)
|
59
61
|
|
60
62
|
# Restore to default
|
61
63
|
::Instana.config[:collect_backtraces] = false
|
@@ -145,8 +147,9 @@ class RackTest < Minitest::Test
|
|
145
147
|
|
146
148
|
def test_context_continuation
|
147
149
|
clear_all!
|
148
|
-
|
149
|
-
header 'X-INSTANA-
|
150
|
+
continuation_id = Instana::Util.generate_id
|
151
|
+
header 'X-INSTANA-T', continuation_id
|
152
|
+
header 'X-INSTANA-S', continuation_id
|
150
153
|
|
151
154
|
get '/mrlobster'
|
152
155
|
assert last_response.ok?
|
@@ -180,10 +183,30 @@ class RackTest < Minitest::Test
|
|
180
183
|
# Context validation
|
181
184
|
# The first span should have the passed in trace ID
|
182
185
|
# and specify the passed in span ID as it's parent.
|
183
|
-
assert_equal
|
184
|
-
assert_equal
|
186
|
+
assert_equal continuation_id, rack_span[:t]
|
187
|
+
assert_equal continuation_id, rack_span[:p]
|
185
188
|
end
|
186
189
|
|
190
|
+
def test_correlation_information
|
191
|
+
clear_all!
|
192
|
+
|
193
|
+
header 'X-INSTANA-L', '1,correlationType=test;correlationId=abcdefh123'
|
194
|
+
|
195
|
+
get '/mrlobster'
|
196
|
+
assert last_response.ok?
|
197
|
+
|
198
|
+
spans = ::Instana.processor.queued_spans
|
199
|
+
|
200
|
+
# Span validation
|
201
|
+
assert_equal 1, spans.count
|
202
|
+
rack_span = spans.first
|
203
|
+
assert_equal :rack, rack_span[:n]
|
204
|
+
|
205
|
+
assert_equal 'abcdefh123', rack_span[:crid]
|
206
|
+
assert_equal 'test', rack_span[:crtp]
|
207
|
+
end
|
208
|
+
|
209
|
+
|
187
210
|
def test_instana_response_headers
|
188
211
|
clear_all!
|
189
212
|
get '/mrlobster'
|
@@ -227,14 +250,24 @@ class RackTest < Minitest::Test
|
|
227
250
|
assert rack_span[:data][:http][:header].key?(:"X-Capture-This")
|
228
251
|
assert !rack_span[:data][:http][:header].key?(:"X-Capture-That")
|
229
252
|
assert_equal "ThereYouGo", rack_span[:data][:http][:header][:"X-Capture-This"]
|
230
|
-
|
231
|
-
# Backtrace fingerprint validation
|
232
|
-
assert rack_span.key?(:stack)
|
233
|
-
assert_equal 2, rack_span[:stack].count
|
234
|
-
refute_nil rack_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
|
253
|
+
assert !rack_span.key?(:stack)
|
235
254
|
|
236
255
|
# Restore to default
|
237
256
|
::Instana.config[:collect_backtraces] = false
|
238
257
|
::Instana.agent.extra_headers = nil
|
239
258
|
end
|
259
|
+
|
260
|
+
def test_capture_http_path_template
|
261
|
+
clear_all!
|
262
|
+
|
263
|
+
get '/path_tpl'
|
264
|
+
assert last_response.ok?
|
265
|
+
|
266
|
+
spans = ::Instana.processor.queued_spans
|
267
|
+
assert_equal 1, spans.length
|
268
|
+
|
269
|
+
rack_span = spans.first
|
270
|
+
assert_equal :rack, rack_span[:n]
|
271
|
+
assert_equal 'sample_template', rack_span[:data][:http][:path_tpl]
|
272
|
+
end
|
240
273
|
end
|