instana 0.14.0 → 0.14.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 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