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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 72f8c1fa60c3d84f52025ce41ebb803ce83b36d8
4
- data.tar.gz: cb85eb7203cc6d028712351d642dc153a28a6468
3
+ metadata.gz: ce0309a7d8eace834f73f721b1e3b008562f9a32
4
+ data.tar.gz: 1ff1ad55ad736c0ef64f1dca370100143f390cbd
5
5
  SHA512:
6
- metadata.gz: 21b2723fc3ee132868586e0f4dd0ad218dafc0a6e39c0fd56ff18c508fe984c32f1431134d1f467a91c687b2b3eb1f34976b76629a675bbe0d829011415e70ad
7
- data.tar.gz: af75b8240335a5c8484400c6d1dca6197b0121d7a0d20569af8bbd0911ab336b68b935b352809f841a571b36cbbe789767dd99d54eeabdacb6084467d6a6c59c
6
+ metadata.gz: a65f865e28aea63228d6c4bfce3c7b5eb4ba1bb6dd1370ce6b3e674083c69905879658e23ecb5329afbab03723ee1aca4c7643db7ea3ba71460d6e59fd5059ed
7
+ data.tar.gz: 5a7b593a95f1f9857f7d6944f0bac2716767b4ec4c720aabd6852e21e20a15d17c841fe862bb715fc47a642062d4053567efa4cfe967ec69b5888c8c183c150c
data/.codeclimate.yml CHANGED
@@ -12,6 +12,9 @@ engines:
12
12
  enabled: true
13
13
  rubocop:
14
14
  enabled: true
15
+ checks:
16
+ Rubocop/Metrics/CyclomaticComplexity:
17
+ enabled: false
15
18
  ratings:
16
19
  paths:
17
20
  - "**.inc"
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
- The above is a simple example but shows how easy it is to instrument any code you like. Instana will
25
- take care of the rest.
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
- @pid = Process.pid
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
- # Store the current pid so we can detect a potential fork
36
- # later on
37
- @pid = ::Process.pid
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
- def pid_change?
41
- @pid != ::Process.pid
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
@@ -7,7 +7,6 @@ module Instana
7
7
  module Collector
8
8
  class << self
9
9
  attr_accessor :interval
10
- attr_accessor :snapshot
11
10
 
12
11
  ##
13
12
  # collect_and_report
@@ -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] = stats[:minor_gc_count] - @last_minor_count
32
- @this_gc[:majorGcs] = stats[:major_gc_count] - @last_major_count
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.id_to_header(our_trace_id)
19
- request['X-Instana-S'] = ::Instana.tracer.id_to_header(our_span_id)
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
- their_trace_id = ::Instana.tracer.header_to_id(response.header['X-Instana-T'])
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
- kv_payload[:http][:url] = request.uri.to_s
35
- kv_payload[:http][:method] = request.method
36
- ::Instana.tracer.log_info(kv_payload)
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
@@ -6,8 +6,13 @@ module Instana
6
6
  STAMP = "Instana: ".freeze
7
7
 
8
8
  def initialize(*args)
9
- if ENV['INSTANA_GEM_DEV']
10
- self.debug_level=:agent
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
- add_info(:log => {
149
- :message => e.message,
150
- :parameters => e.class })
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) unless kvs.empty?
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
- bt = Kernel.caller
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
@@ -1,4 +1,4 @@
1
1
  module Instana
2
- VERSION = "0.14.0"
2
+ VERSION = "0.14.2"
3
3
  VERSION_FULL = "instana-#{VERSION}"
4
4
  end
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.0
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-19 00:00:00.000000000 Z
11
+ date: 2016-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler