instana 0.14.0 → 0.14.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -0
- data/README.md +4 -0
- data/Tracing.md +11 -2
- data/lib/instana/agent.rb +3 -29
- data/lib/instana/base.rb +13 -10
- data/lib/instana/collectors.rb +0 -1
- data/lib/instana/collectors/gc.rb +2 -2
- data/lib/instana/instrumentation/excon.rb +6 -0
- data/lib/instana/instrumentation/net-http.rb +26 -14
- data/lib/instana/instrumentation/rack.rb +6 -0
- data/lib/instana/logger.rb +9 -2
- data/lib/instana/tracing/trace.rb +40 -12
- data/lib/instana/util.rb +23 -0
- data/lib/instana/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce0309a7d8eace834f73f721b1e3b008562f9a32
|
4
|
+
data.tar.gz: 1ff1ad55ad736c0ef64f1dca370100143f390cbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a65f865e28aea63228d6c4bfce3c7b5eb4ba1bb6dd1370ce6b3e674083c69905879658e23ecb5329afbab03723ee1aca4c7643db7ea3ba71460d6e59fd5059ed
|
7
|
+
data.tar.gz: 5a7b593a95f1f9857f7d6944f0bac2716767b4ec4c720aabd6852e21e20a15d17c841fe862bb715fc47a642062d4053567efa4cfe967ec69b5888c8c183c150c
|
data/.codeclimate.yml
CHANGED
data/README.md
CHANGED
@@ -56,6 +56,10 @@ See [Tracing.md](https://github.com/instana/ruby-sensor/blob/master/Tracing.md)
|
|
56
56
|
|
57
57
|
You can find more documentation covering supported components and minimum versions in the Instana [documentation portal](https://instana.atlassian.net/wiki/display/DOCS/Ruby).
|
58
58
|
|
59
|
+
## Want End User Monitoring?
|
60
|
+
|
61
|
+
Instana provides deep end user monitoring that links server side traces with browser events. See [End User Monitoring](https://instana.atlassian.net/wiki/display/DOCS/Web+End-User+Monitoring) in the Instana documentation portal.
|
62
|
+
|
59
63
|
## Development
|
60
64
|
|
61
65
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Tracing.md
CHANGED
@@ -21,8 +21,17 @@ ensure
|
|
21
21
|
end
|
22
22
|
```
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
or alternatively you can use the `trace` block method that will automagically capture and
|
25
|
+
log any exceptions raised:
|
26
|
+
|
27
|
+
```Ruby
|
28
|
+
::Instana.tracer.trace(:mywork, { :helpful_kvs => @user.id }) do
|
29
|
+
# The code to be instrumented
|
30
|
+
@id = User.find_by_name('john.smith')
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
The above are simple examples but shows how easy it is to instrument any arbitrary piece of code you like.
|
26
35
|
|
27
36
|
See the [examples directory](https://github.com/instana/ruby-sensor/blob/master/examples/tracing.rb) for
|
28
37
|
an expanded view and quick cheat sheet on tracing.
|
data/lib/instana/agent.rb
CHANGED
@@ -22,9 +22,6 @@ module Instana
|
|
22
22
|
# Supported two states (unannounced & announced)
|
23
23
|
@state = :unannounced
|
24
24
|
|
25
|
-
# Store the pid from process boot so we can detect forks
|
26
|
-
@pid = Process.pid
|
27
|
-
|
28
25
|
# Snapshot data is collected once per process but resent
|
29
26
|
# every 10 minutes along side process metrics.
|
30
27
|
@snapshot = ::Instana::Util.take_snapshot
|
@@ -57,29 +54,7 @@ module Instana
|
|
57
54
|
# The agent UUID returned from the host agent
|
58
55
|
@agent_uuid = nil
|
59
56
|
|
60
|
-
collect_process_info
|
61
|
-
end
|
62
|
-
|
63
|
-
# Used in class initialization and after a fork, this method
|
64
|
-
# collects up process information and stores it in @process
|
65
|
-
#
|
66
|
-
def collect_process_info
|
67
|
-
@process = {}
|
68
|
-
cmdline = ProcTable.ps(Process.pid).cmdline.split("\0")
|
69
|
-
@process[:name] = cmdline.shift
|
70
|
-
@process[:arguments] = cmdline
|
71
|
-
|
72
|
-
if @is_osx
|
73
|
-
# Handle OSX bug where env vars show up at the end of process name
|
74
|
-
# such as MANPATH etc..
|
75
|
-
@process[:name].gsub!(/[_A-Z]+=\S+/, '')
|
76
|
-
@process[:name].rstrip!
|
77
|
-
end
|
78
|
-
|
79
|
-
@process[:original_pid] = @pid
|
80
|
-
# This is usually Process.pid but in the case of docker, the host agent
|
81
|
-
# will return to us the true host pid in which we use to report data.
|
82
|
-
@process[:report_pid] = nil
|
57
|
+
@process = ::Instana::Util.collect_process_info
|
83
58
|
end
|
84
59
|
|
85
60
|
# Used post fork to re-initialize state and restart communications with
|
@@ -89,8 +64,7 @@ module Instana
|
|
89
64
|
::Instana.logger.agent "after_fork hook called. Falling back to unannounced state and spawning a new background agent thread."
|
90
65
|
|
91
66
|
# Re-collect process information post fork
|
92
|
-
@
|
93
|
-
collect_process_info
|
67
|
+
@process = ::Instana::Util.collect_process_info
|
94
68
|
|
95
69
|
transition_to(:unannounced)
|
96
70
|
setup
|
@@ -451,7 +425,7 @@ module Instana
|
|
451
425
|
# @ return [Boolean] true or false to indicate if forked
|
452
426
|
#
|
453
427
|
def forked?
|
454
|
-
@pid != Process.pid
|
428
|
+
@process[:pid] != Process.pid
|
455
429
|
end
|
456
430
|
end
|
457
431
|
end
|
data/lib/instana/base.rb
CHANGED
@@ -20,25 +20,28 @@ module Instana
|
|
20
20
|
#
|
21
21
|
def setup
|
22
22
|
@logger = ::Instana::XLogger.new(STDOUT)
|
23
|
-
if ENV.key?('INSTANA_GEM_TEST') || ENV.key?('INSTANA_GEM_DEV')
|
24
|
-
@logger.level = Logger::DEBUG
|
25
|
-
else
|
26
|
-
@logger.level = Logger::WARN
|
27
|
-
end
|
28
23
|
@logger.unknown "Stan is on the scene. Starting Instana instrumentation."
|
29
24
|
|
30
25
|
@agent = ::Instana::Agent.new
|
31
26
|
@tracer = ::Instana::Tracer.new
|
32
27
|
@processor = ::Instana::Processor.new
|
33
28
|
@collectors = []
|
29
|
+
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
# Indicates whether we are running in a development environment.
|
32
|
+
#
|
33
|
+
# @return Boolean
|
34
|
+
#
|
35
|
+
def debug?
|
36
|
+
ENV.key?('INSTANA_GEM_DEV')
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
|
39
|
+
# Indicates whether we are running in the test environment.
|
40
|
+
#
|
41
|
+
# @return Boolean
|
42
|
+
#
|
43
|
+
def test?
|
44
|
+
ENV.key?('INSTANA_GEM_TEST')
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
data/lib/instana/collectors.rb
CHANGED
@@ -28,8 +28,8 @@ module Instana
|
|
28
28
|
# GC metrics only available on newer Ruby versions
|
29
29
|
if RUBY_VERSION >= '2.1'
|
30
30
|
# GC runs. Calculate how many have occurred since the last call
|
31
|
-
@this_gc[:minorGcs]
|
32
|
-
@this_gc[:majorGcs]
|
31
|
+
@this_gc[:minorGcs] = stats[:minor_gc_count] - @last_minor_count
|
32
|
+
@this_gc[:majorGcs] = stats[:major_gc_count] - @last_major_count
|
33
33
|
|
34
34
|
# Store these counts so that we have something to compare to next
|
35
35
|
# time around.
|
@@ -46,6 +46,12 @@ if defined?(::Excon) && ::Instana.config[:excon][:enabled]
|
|
46
46
|
status = datum[:response][:status]
|
47
47
|
end
|
48
48
|
|
49
|
+
if status.between?(500, 511)
|
50
|
+
# Because of the 5xx response, we flag this span as errored but
|
51
|
+
# without a backtrace (no exception)
|
52
|
+
::Instana.tracer.log_error(nil)
|
53
|
+
end
|
54
|
+
|
49
55
|
if datum[:pipeline] == true
|
50
56
|
# Pickup context of this async span from datum[:instana_id]
|
51
57
|
::Instana.tracer.log_async_exit(:excon, { :http => {:status => status } }, datum[:instana_context])
|
@@ -11,36 +11,48 @@ Net::HTTP.class_eval {
|
|
11
11
|
|
12
12
|
# Send out the tracing context with the request
|
13
13
|
request = args[0]
|
14
|
-
our_trace_id = ::Instana.tracer.trace_id
|
15
|
-
our_span_id = ::Instana.tracer.span_id
|
16
14
|
|
17
15
|
# Set request headers; encode IDs as hexadecimal strings
|
18
|
-
request['X-Instana-T'] = ::Instana.tracer.
|
19
|
-
request['X-Instana-S'] = ::Instana.tracer.
|
16
|
+
request['X-Instana-T'] = ::Instana.tracer.trace_id_header
|
17
|
+
request['X-Instana-S'] = ::Instana.tracer.span_id_header
|
20
18
|
|
19
|
+
# Collect up KV info now in case any exception is raised
|
20
|
+
kv_payload = { :http => {} }
|
21
|
+
kv_payload[:http][:method] = request.method
|
22
|
+
|
23
|
+
if request.uri
|
24
|
+
kv_payload[:http][:url] = request.uri.to_s
|
25
|
+
else
|
26
|
+
if use_ssl?
|
27
|
+
kv_payload[:http][:url] = "https://#{@address}:#{@port}#{request.path}"
|
28
|
+
else
|
29
|
+
kv_payload[:http][:url] = "http://#{@address}:#{@port}#{request.path}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# The core call
|
21
34
|
response = request_without_instana(*args, &block)
|
22
35
|
|
23
36
|
# Pickup response headers; convert back to base 10 integer
|
24
|
-
if response.key?('X-Instana-T')
|
25
|
-
|
26
|
-
|
27
|
-
if our_trace_id != their_trace_id
|
28
|
-
::Instana.logger.debug "#{Thread.current}: Trace ID mismatch on net/http response! ours: #{our_trace_id} theirs: #{their_trace_id}"
|
37
|
+
if ::Instana.debug? && response.key?('X-Instana-T')
|
38
|
+
if ::Instana.tracer.trace_id != ::Instana.tracer.header_to_id(response.header['X-Instana-T'])
|
39
|
+
::Instana.logger.debug "#{Thread.current}: Trace ID mismatch on net/http response! ours: #{::Instana.tracer.trace_id} theirs: #{their_trace_id}"
|
29
40
|
end
|
30
41
|
end
|
31
42
|
|
32
|
-
kv_payload = { :http => {} }
|
33
43
|
kv_payload[:http][:status] = response.code
|
34
|
-
|
35
|
-
|
36
|
-
|
44
|
+
if response.code.to_i.between?(500, 511)
|
45
|
+
# Because of the 5xx response, we flag this span as errored but
|
46
|
+
# without a backtrace (no exception)
|
47
|
+
add_error(nil)
|
48
|
+
end
|
37
49
|
|
38
50
|
response
|
39
51
|
rescue => e
|
40
52
|
::Instana.tracer.log_error(e)
|
41
53
|
raise
|
42
54
|
ensure
|
43
|
-
::Instana.tracer.log_exit(:'net-http')
|
55
|
+
::Instana.tracer.log_exit(:'net-http', kv_payload)
|
44
56
|
end
|
45
57
|
|
46
58
|
Instana.logger.warn "Instrumenting Net::HTTP"
|
@@ -30,6 +30,12 @@ module Instana
|
|
30
30
|
if ::Instana.tracer.tracing?
|
31
31
|
kvs[:http][:status] = status
|
32
32
|
|
33
|
+
if status.between?(500, 511)
|
34
|
+
# Because of the 5xx response, we flag this span as errored but
|
35
|
+
# without a backtrace (no exception)
|
36
|
+
::Instana.tracer.log_error(nil)
|
37
|
+
end
|
38
|
+
|
33
39
|
# Save the IDs before the trace ends so we can place
|
34
40
|
# them in the response headers in the ensure block
|
35
41
|
trace_id = ::Instana.tracer.trace_id
|
data/lib/instana/logger.rb
CHANGED
@@ -6,8 +6,13 @@ module Instana
|
|
6
6
|
STAMP = "Instana: ".freeze
|
7
7
|
|
8
8
|
def initialize(*args)
|
9
|
-
if ENV
|
10
|
-
self.
|
9
|
+
if ENV.key?('INSTANA_GEM_TEST')
|
10
|
+
self.level = Logger::DEBUG
|
11
|
+
elsif ENV.key?('INSTANA_GEM_DEV')
|
12
|
+
self.level = Logger::DEBUG
|
13
|
+
self.debug_level = nil
|
14
|
+
else
|
15
|
+
self.level = Logger::WARN
|
11
16
|
end
|
12
17
|
super(*args)
|
13
18
|
end
|
@@ -24,6 +29,8 @@ module Instana
|
|
24
29
|
# ::Instana.logger.debug_level = [:agent_comm, :trace]
|
25
30
|
#
|
26
31
|
def debug_level=(levels)
|
32
|
+
return unless levels
|
33
|
+
|
27
34
|
LEVELS.each do |l|
|
28
35
|
instance_variable_set("@level_#{l}", false)
|
29
36
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module Instana
|
2
2
|
class Trace
|
3
|
-
REGISTERED_SPANS = [ :rack, :'net-http', :excon ]
|
4
|
-
ENTRY_SPANS = [ :rack ]
|
5
|
-
EXIT_SPANS = [ :'net-http', :excon ]
|
3
|
+
REGISTERED_SPANS = [ :rack, :'net-http', :excon ].freeze
|
4
|
+
ENTRY_SPANS = [ :rack ].freeze
|
5
|
+
EXIT_SPANS = [ :'net-http', :excon ].freeze
|
6
|
+
HTTP_SPANS = ENTRY_SPANS + EXIT_SPANS
|
6
7
|
|
7
8
|
# @return [Integer] the ID for this trace
|
8
9
|
attr_reader :id
|
@@ -135,6 +136,10 @@ module Instana
|
|
135
136
|
# @param e [Exception] Add exception to the current span
|
136
137
|
#
|
137
138
|
def add_error(e, span = nil)
|
139
|
+
# Return if we've already logged this exception and it
|
140
|
+
# is just propogating up the spans.
|
141
|
+
return if e && e.instance_variable_get(:@instana_logged)
|
142
|
+
|
138
143
|
span ||= @current_span
|
139
144
|
|
140
145
|
span[:error] = true
|
@@ -145,9 +150,22 @@ module Instana
|
|
145
150
|
span[:ec] = 1
|
146
151
|
end
|
147
152
|
|
148
|
-
|
149
|
-
|
150
|
-
|
153
|
+
# If a valid exception has been passed in, log the information about it
|
154
|
+
# In case of just logging an error for things such as HTTP client 5xx
|
155
|
+
# responses, an exception/backtrace may not exist.
|
156
|
+
if e
|
157
|
+
if e.backtrace.is_a?(Array)
|
158
|
+
add_backtrace_to_span(e.backtrace, nil, span)
|
159
|
+
end
|
160
|
+
|
161
|
+
if HTTP_SPANS.include?(span.name)
|
162
|
+
add_info(:http => { :error => "#{e.class}: #{e.message}" })
|
163
|
+
else
|
164
|
+
add_info(:log => { :message => e.message, :parameters => e.class })
|
165
|
+
end
|
166
|
+
e.instance_variable_set(:@instana_logged, true)
|
167
|
+
end
|
168
|
+
|
151
169
|
end
|
152
170
|
|
153
171
|
# Close out the current span and set the parent as
|
@@ -157,7 +175,7 @@ module Instana
|
|
157
175
|
#
|
158
176
|
def end_span(kvs = {})
|
159
177
|
@current_span[:d] = ts_now - @current_span[:ts]
|
160
|
-
add_info(kvs)
|
178
|
+
add_info(kvs) if kvs && !kvs.empty?
|
161
179
|
@current_span = @current_span.parent unless @current_span.is_root?
|
162
180
|
end
|
163
181
|
|
@@ -398,8 +416,7 @@ module Instana
|
|
398
416
|
end
|
399
417
|
end
|
400
418
|
|
401
|
-
# Adds a backtrace to the passed in span or on
|
402
|
-
# @current_span if not.
|
419
|
+
# Adds a backtrace to the passed in span or on @current_span if not.
|
403
420
|
#
|
404
421
|
# @param limit [Integer] Limit the backtrace to the top <limit> frames
|
405
422
|
# @param span [Span] the span to add the backtrace to or if unspecified
|
@@ -407,10 +424,21 @@ module Instana
|
|
407
424
|
#
|
408
425
|
def add_stack(limit = nil, span = nil)
|
409
426
|
span ||= @current_span
|
410
|
-
span[:stack] = []
|
411
|
-
frame_count = 0
|
412
427
|
|
413
|
-
|
428
|
+
add_backtrace_to_span(Kernel.caller, limit, span)
|
429
|
+
end
|
430
|
+
|
431
|
+
# Adds the passed in backtrace to the specified span. Backtrace can be one
|
432
|
+
# generated from Kernel.caller or one attached to an exception
|
433
|
+
#
|
434
|
+
# @param bt [Array] the backtrace
|
435
|
+
# @param limit [Integer] Limit the backtrace to the top <limit> frames
|
436
|
+
# @param span [Span] the span to add the backtrace to or if unspecified
|
437
|
+
# the current span
|
438
|
+
#
|
439
|
+
def add_backtrace_to_span(bt, limit = nil, span)
|
440
|
+
frame_count = 0
|
441
|
+
span[:stack] = []
|
414
442
|
|
415
443
|
bt.each do |i|
|
416
444
|
# If the stack has the full instana gem version in it's path
|
data/lib/instana/util.rb
CHANGED
@@ -117,6 +117,29 @@ module Instana
|
|
117
117
|
::Instana.logger.debug e.backtrace.join("\r\n")
|
118
118
|
return data
|
119
119
|
end
|
120
|
+
|
121
|
+
# Used in class initialization and after a fork, this method
|
122
|
+
# collects up process information
|
123
|
+
#
|
124
|
+
def collect_process_info
|
125
|
+
process = {}
|
126
|
+
cmdline = ProcTable.ps(Process.pid).cmdline.split("\0")
|
127
|
+
process[:name] = cmdline.shift
|
128
|
+
process[:arguments] = cmdline
|
129
|
+
|
130
|
+
if RUBY_PLATFORM =~ /darwin/i
|
131
|
+
# Handle OSX bug where env vars show up at the end of process name
|
132
|
+
# such as MANPATH etc..
|
133
|
+
process[:name].gsub!(/[_A-Z]+=\S+/, '')
|
134
|
+
process[:name].rstrip!
|
135
|
+
end
|
136
|
+
|
137
|
+
process[:pid] = Process.pid
|
138
|
+
# This is usually Process.pid but in the case of docker, the host agent
|
139
|
+
# will return to us the true host pid in which we use to report data.
|
140
|
+
process[:report_pid] = nil
|
141
|
+
process
|
142
|
+
end
|
120
143
|
end
|
121
144
|
end
|
122
145
|
end
|
data/lib/instana/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: instana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Giacomo Lombardo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|