instana 0.9.2 → 0.10.1

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: e4e0afa7990ec121d8542873c665d2ddda7e1ee9
4
- data.tar.gz: 33143dc761cf85e27ab21ed22c9f64f8670c3a2b
3
+ metadata.gz: 7e188f12fcff2a78ced457b2640b460b257e5684
4
+ data.tar.gz: c149e734156bf8b02ffd757cc564618c83ba7153
5
5
  SHA512:
6
- metadata.gz: 85b7857890a0da50ef837027a1c5e0e7f413189b60175d1f26e682f5c109c7f98534efa2a84ef0f2cbf0e1162eb00f88b10604118fc18ca8036b3aef94e4c02e
7
- data.tar.gz: 57d956387066525d20f4e6efc108115f4b02d001418fdad0cdf639143be00e32bfc26173eccc96cfed2bf63be36dbc3b0e09fd96db9209c1037f44ff27a36801
6
+ metadata.gz: 46e488894d84fa5b4afd32b486ae5c4af61ce30ceee001b6395f5c4dbb7fdfe68421093d765e59ecab0c647ef63992d0ebeb9c6abc1eed7af401cd69ad742cb1
7
+ data.tar.gz: 26be2c7a4a825baa23897a143ddbaabf631a1797e43716066509f984f84aa0d9c85054f7a67e3f9b8d59e3c9054f952c1769fd2b73a6d880c50df204585f46f1
data/README.md CHANGED
@@ -1,17 +1,17 @@
1
1
  <div align="center">
2
- <img src="https://www.instana.com/wp-content/uploads/2016/04/stan@2x.png">
2
+ <img src="https://www.instana.com/wp-content/uploads/2016/04/stan@2x.png" height="300px"/>
3
3
  </div>
4
4
 
5
5
  # Instana
6
6
 
7
- The Instana gem provides Ruby metrics for [Instana](https://www.instana.com/).
7
+ The Instana gem provides Ruby metrics and traces (request, queue & cross-host) for [Instana](https://www.instana.com/).
8
8
 
9
9
  [![Build Status](https://travis-ci.org/instana/ruby-sensor.svg?branch=master)](https://travis-ci.org/instana/ruby-sensor)
10
10
  [![Gem Version](https://badge.fury.io/rb/instana.svg)](https://badge.fury.io/rb/instana)
11
11
 
12
12
  ## Note
13
13
 
14
- This gem is currently in beta and supports Ruby versions 2.0 or greater.
14
+ This gem supports Ruby versions 2.0 or greater.
15
15
 
16
16
  Any and all feedback is welcome. Happy Ruby visibility.
17
17
 
@@ -37,7 +37,33 @@ The instana gem is a zero configuration tool that will automatically collect key
37
37
 
38
38
  ## Configuration
39
39
 
40
- Although the gem has no configuration required for metrics, individual components can be disabled with a local config.
40
+ Although the gem has no configuration required for out of the box metrics and tracing, components can be configured if needed.
41
+
42
+ ### Agent Reporting
43
+
44
+ This agent spawns a lightweight background thread to periodically collect and report metrics and traces. Be default, this uses a standard Ruby thread. If you wish to have greater control and potentially boot the agent reporting manually in an alternative thread system (such as actor based threads), you can do so with the following:
45
+
46
+ ```Ruby
47
+ gem "instana", :require => "instana/setup"
48
+ ```
49
+
50
+ ...then in the background thread of your choice simply call:
51
+
52
+ ```Ruby
53
+ ::Instana.agent.start
54
+ ```
55
+
56
+ Note that this call is blocking. It kicks off a loop of timers that periodically collects and reports metrics and trace data. This should only be called from inside an already initialized background thread:
57
+
58
+ ```Ruby
59
+ Thread.new do
60
+ ::Instana.agent.start
61
+ end
62
+ ```
63
+
64
+ ### Components
65
+
66
+ Individual components can be disabled with a local config.
41
67
 
42
68
  To disable a single component in the gem, you can disable a single component with the following code:
43
69
 
@@ -46,6 +72,17 @@ To disable a single component in the gem, you can disable a single component wit
46
72
  ```
47
73
  Current components are `:gc`, `:memory` and `:thread`.
48
74
 
75
+ ### Rack Middleware
76
+
77
+ This gem will detect and automagically insert the Instana Rack middleware into the middleware stack when Ruby on Rails is present. We are currently adding support for more frameworks. If you are using a framework other than Ruby on Rails, you can insert the Instana Rack middleware with the following:
78
+
79
+ ```Ruby
80
+ require "instana/rack"
81
+ config.middleware.use ::Instana::Rack
82
+ ```
83
+
84
+ ...or whatever specific middleware call is appropriate for your framework.
85
+
49
86
  ## Documentation
50
87
 
51
88
  You can find more documentation covering supported components and minimum versions in the Instana [documentation portal](https://instana.atlassian.net/wiki/display/DOCS/Ruby).
data/lib/instana.rb CHANGED
@@ -1,57 +1,13 @@
1
-
2
- require 'logger'
3
- require "instana/version"
4
- require "instana/util"
5
-
6
- module Instana
7
- class << self
8
- attr_accessor :agent
9
- attr_accessor :collectors
10
- attr_accessor :tracer
11
- attr_accessor :processor
12
- attr_accessor :config
13
- attr_accessor :logger
14
- attr_accessor :pid
15
-
16
- ##
17
- # start
18
- #
19
- # Initialize the Instana language agent
20
- #
21
- def start
22
- @agent = ::Instana::Agent.new
23
- @tracer = ::Instana::Tracer.new
24
- @processor = ::Instana::Processor.new
25
- @collectors = []
26
-
27
- @logger = Logger.new(STDOUT)
28
- if ENV.key?('INSTANA_GEM_TEST') || ENV.key?('INSTANA_GEM_DEV')
29
- @logger.level = Logger::DEBUG
30
- else
31
- @logger.level = Logger::WARN
32
- end
33
- @logger.unknown "Stan is on the scene. Starting Instana instrumentation."
34
-
35
- # Store the current pid so we can detect a potential fork
36
- # later on
37
- @pid = ::Process.pid
38
- end
39
-
40
- def pid_change?
41
- @pid != ::Process.pid
42
- end
43
- end
1
+ require "instana/setup"
2
+
3
+ # Boot the instana agent background thread. If you wish to have greater
4
+ # control on the where and which thread this is run in, instead use
5
+ #
6
+ # gem "instana", :require "instana/setup"
7
+ #
8
+ # ...and manually call ::Instana.agent.start in the thread
9
+ # of your choice
10
+ #
11
+ Thread.new do
12
+ ::Instana.agent.start
44
13
  end
45
-
46
-
47
- require "instana/config"
48
- require "instana/agent"
49
- require "instana/tracer"
50
- require "instana/tracing/processor"
51
-
52
- ::Instana.start
53
-
54
- require "instana/collectors"
55
- require "instana/instrumentation"
56
-
57
- ::Instana.agent.start
data/lib/instana/agent.rb CHANGED
@@ -94,33 +94,50 @@ module Instana
94
94
  # the host agent.
95
95
  #
96
96
  def after_fork
97
- ::Instana.logger.debug "after_fork hook called. Falling back to unannounced state."
97
+ ::Instana.logger.debug "after_fork hook called. Falling back to unannounced state and spawning a new background agent thread."
98
98
 
99
99
  # Re-collect process information post fork
100
100
  @pid = Process.pid
101
101
  collect_process_info
102
102
 
103
- # Set last snapshot to 10 minutes ago
104
- # so we send a snapshot sooner than later
105
- @last_snapshot = Time.now - 600
106
-
107
103
  transition_to(:unannounced)
108
- start
104
+ setup
105
+ spawn_background_thread
106
+ end
107
+
108
+ # Spawns the background thread and calls start. This method is separated
109
+ # out for those who wish to control which thread the background agent will
110
+ # run in.
111
+ #
112
+ # This method can be overridden with the following:
113
+ #
114
+ # module Instana
115
+ # class Agent
116
+ # def spawn_background_thread
117
+ # # start thread
118
+ # start
119
+ # end
120
+ # end
121
+ # end
122
+ #
123
+ def spawn_background_thread
124
+ # The thread calling fork is the only thread in the created child process.
125
+ # fork doesn’t copy other threads.
126
+ # Restart our background thread
127
+ Thread.new do
128
+ start
129
+ end
109
130
  end
110
131
 
111
132
  # Sets up periodic timers and starts the agent in a background thread.
112
133
  #
113
- def start
134
+ def setup
114
135
  # The announce timer
115
136
  # We attempt to announce this ruby sensor to the host agent.
116
137
  # In case of failure, we try again in 30 seconds.
117
138
  @announce_timer = @timers.now_and_every(30) do
118
- if forked?
119
- after_fork
120
- break
121
- end
122
139
  if host_agent_ready? && announce_sensor
123
- ::Instana.logger.debug "Announce successful. Switching to metrics collection."
140
+ ::Instana.logger.debug "Announce successful. Switching to metrics collection. pid: #{Process.pid}"
124
141
  transition_to(:announced)
125
142
  end
126
143
  end
@@ -130,10 +147,6 @@ module Instana
130
147
  # every ::Instana::Collector.interval seconds.
131
148
  @collect_timer = @timers.every(::Instana::Collector.interval) do
132
149
  if @state == :announced
133
- if forked?
134
- after_fork
135
- break
136
- end
137
150
  unless ::Instana::Collector.collect_and_report
138
151
  # If report has been failing for more than 1 minute,
139
152
  # fall back to unannounced state
@@ -145,31 +158,44 @@ module Instana
145
158
  ::Instana.processor.send
146
159
  end
147
160
  end
161
+ end
148
162
 
149
- # Start the background ruby sensor thread. It works off of timers and
150
- # is sleeping otherwise
151
- Thread.new do
152
- loop {
153
- if @state == :unannounced
154
- @collect_timer.pause
155
- @announce_timer.resume
156
- else
157
- @announce_timer.pause
158
- @collect_timer.resume
159
- end
160
- @timers.wait
161
- }
163
+ # Starts the timer loop for the timers that were initialized
164
+ # in the setup method. This is blocking and should only be
165
+ # called from an already initialized background thread.
166
+ #
167
+ def start
168
+ loop do
169
+ if @state == :unannounced
170
+ @collect_timer.pause
171
+ @announce_timer.resume
172
+ else
173
+ @announce_timer.pause
174
+ @collect_timer.resume
175
+ end
176
+ @timers.wait
162
177
  end
178
+ ensure
179
+ Instana.logger.debug "Agent start method exiting. state: #{@state} pid: #{Process.pid}"
163
180
  end
164
181
 
165
182
  # Indicates if the agent is ready to send metrics
166
- # or data.
183
+ # and/or data.
167
184
  #
168
185
  def ready?
169
186
  # In test, we're always ready :-)
170
187
  return true if ENV['INSTANA_GEM_TEST']
171
188
 
189
+ if forked?
190
+ ::Instana.logger.debug "Instana: detected fork. Calling after_fork"
191
+ after_fork
192
+ end
193
+
172
194
  @state == :announced
195
+ rescue => e
196
+ Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
197
+ Instana.logger.debug e.backtrace.join("\r\n")
198
+ return false
173
199
  end
174
200
 
175
201
  # Returns the PID that we are reporting to
@@ -341,6 +367,10 @@ module Instana
341
367
  @last_snapshot = Time.now - 601
342
368
  when :unannounced
343
369
  @state = :unannounced
370
+
371
+ # Set last snapshot to 10 minutes ago
372
+ # so we send a snapshot on first report
373
+ @last_snapshot = Time.now - 601
344
374
  else
345
375
  ::Instana.logger.warn "Uknown agent state: #{state}"
346
376
  end
@@ -0,0 +1,44 @@
1
+ require 'logger'
2
+ require "instana/version"
3
+ require "instana/util"
4
+
5
+ module Instana
6
+ class << self
7
+ attr_accessor :agent
8
+ attr_accessor :collectors
9
+ attr_accessor :tracer
10
+ attr_accessor :processor
11
+ attr_accessor :config
12
+ attr_accessor :logger
13
+ attr_accessor :pid
14
+
15
+ ##
16
+ # setup
17
+ #
18
+ # Setup the Instana language agent to an informal "ready
19
+ # to run" state.
20
+ #
21
+ def setup
22
+ @logger = Logger.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
+ @logger.unknown "Stan is on the scene. Starting Instana instrumentation."
29
+
30
+ @agent = ::Instana::Agent.new
31
+ @tracer = ::Instana::Tracer.new
32
+ @processor = ::Instana::Processor.new
33
+ @collectors = []
34
+
35
+ # Store the current pid so we can detect a potential fork
36
+ # later on
37
+ @pid = ::Process.pid
38
+ end
39
+
40
+ def pid_change?
41
+ @pid != ::Process.pid
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ require "instana/rack"
2
+
3
+ if defined?(::Rails)
4
+ # In Rails, let's use the Rails logger
5
+ ::Instana.logger = ::Rails.logger if ::Rails.logger
6
+
7
+ if ::Rails::VERSION::MAJOR < 3
8
+ ::Rails.configuration.after_initialization do
9
+ ::Instana.logger.warn "Instana: Instrumenting Rack"
10
+ ::Rails.configuration.middleware.insert 0, ::Instana::Rack
11
+ end
12
+ else
13
+ module ::Instana
14
+ class Railtie < ::Rails::Railtie
15
+ initializer 'instana.rack' do |app|
16
+ ::Instana.logger.warn "Instana: Instrumenting Rack"
17
+ app.config.middleware.insert 0, ::Instana::Rack
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -10,3 +10,16 @@ Dir.glob(pattern) do |f|
10
10
  Instana.logger.debug e.backtrace.join("\r\n")
11
11
  end
12
12
  end
13
+
14
+ #
15
+ # Load all of the files in the frameworks subdirectory
16
+ #
17
+ pattern = File.join(File.dirname(__FILE__), 'frameworks', '*.rb')
18
+ Dir.glob(pattern) do |f|
19
+ begin
20
+ require f
21
+ rescue => e
22
+ Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
23
+ Instana.logger.debug e.backtrace.join("\r\n")
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require "instana/base"
2
+ require "instana/config"
3
+ require "instana/agent"
4
+ require "instana/tracer"
5
+ require "instana/tracing/processor"
6
+
7
+ ::Instana.setup
8
+
9
+ require "instana/collectors"
10
+ require "instana/instrumentation"
11
+
12
+ ::Instana.agent.setup
13
+
14
+ # The Instana agent is now setup. The only remaining
15
+ # task for a complete boot is to call
16
+ # `Instana.agent.start` in the thread of your choice.
17
+ # This can be in a simple `Thread.new` block or
18
+ # any other thread system you may use (e.g. actor
19
+ # threads).
20
+ #
21
+ # Note that `start` should only be called once per process.
22
+ #
23
+ # Thread.new do
24
+ # ::Instana.agent.start
25
+ # end
@@ -152,7 +152,10 @@ module Instana
152
152
  Instana.logger.debug "id_to_header received a #{id.class}: returning empty string"
153
153
  return String.new
154
154
  end
155
- id.to_i.to_s(16)
155
+ [id.to_i].pack('q>').unpack('H*')[0]
156
+ rescue => e
157
+ Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
158
+ Instana.logger.debug e.backtrace.join("\r\n")
156
159
  end
157
160
 
158
161
  # Convert a received header value into a valid ID
@@ -166,7 +169,10 @@ module Instana
166
169
  Instana.logger.debug "header_to_id received a #{header_id.class}: returning 0"
167
170
  return 0
168
171
  end
169
- header_id.to_i(16)
172
+ [header_id].pack("H*").unpack("q>")[0]
173
+ rescue => e
174
+ Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
175
+ Instana.logger.debug e.backtrace.join("\r\n")
170
176
  end
171
177
 
172
178
  # Returns the trace ID for the active trace (if there is one),
@@ -164,7 +164,7 @@ module Instana
164
164
  #
165
165
  def generate_id
166
166
  # Max value is 9223372036854775807 (signed long in Java)
167
- rand(2**32..2**63-1)
167
+ rand(-2**63..2**63-1)
168
168
  end
169
169
  end
170
170
  end
@@ -1,3 +1,3 @@
1
1
  module Instana
2
- VERSION = "0.9.2"
2
+ VERSION = "0.10.1"
3
3
  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.9.2
4
+ version: 0.10.1
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-11-24 00:00:00.000000000 Z
11
+ date: 2016-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -126,15 +126,18 @@ files:
126
126
  - instana.gemspec
127
127
  - lib/instana.rb
128
128
  - lib/instana/agent.rb
129
+ - lib/instana/base.rb
129
130
  - lib/instana/collectors.rb
130
131
  - lib/instana/collectors/gc.rb
131
132
  - lib/instana/collectors/memory.rb
132
133
  - lib/instana/collectors/thread.rb
133
134
  - lib/instana/config.rb
135
+ - lib/instana/frameworks/rails.rb
134
136
  - lib/instana/instrumentation.rb
135
137
  - lib/instana/instrumentation/net-http.rb
136
138
  - lib/instana/instrumentation/rack.rb
137
139
  - lib/instana/rack.rb
140
+ - lib/instana/setup.rb
138
141
  - lib/instana/thread_local.rb
139
142
  - lib/instana/tracer.rb
140
143
  - lib/instana/tracing/processor.rb