scout_rails 1.0.7 → 1.0.8.pre.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.markdown +5 -0
- data/lib/scout_rails.rb +1 -0
- data/lib/scout_rails/agent.rb +42 -40
- data/lib/scout_rails/background_worker.rb +43 -0
- data/lib/scout_rails/environment.rb +4 -0
- data/lib/scout_rails/version.rb +1 -1
- metadata +6 -5
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# 1.0.8
|
2
|
+
|
3
|
+
* Processing metrics when a process starts + exits to prevent losing in-memory metrics on process exit.
|
4
|
+
* Ensuring scope is nil for samplers (could be run when a process is killed before scope is reset)
|
5
|
+
|
1
6
|
# 1.0.7
|
2
7
|
|
3
8
|
* Sinatra 1.3+ compatibility (alias dispatch! instead of route_eval)
|
data/lib/scout_rails.rb
CHANGED
@@ -13,6 +13,7 @@ require File.expand_path('../scout_rails/agent/reporting.rb', __FILE__)
|
|
13
13
|
require File.expand_path('../scout_rails/layaway.rb', __FILE__)
|
14
14
|
require File.expand_path('../scout_rails/layaway_file.rb', __FILE__)
|
15
15
|
require File.expand_path('../scout_rails/config.rb', __FILE__)
|
16
|
+
require File.expand_path('../scout_rails/background_worker.rb', __FILE__)
|
16
17
|
require File.expand_path('../scout_rails/environment.rb', __FILE__)
|
17
18
|
require File.expand_path('../scout_rails/metric_meta.rb', __FILE__)
|
18
19
|
require File.expand_path('../scout_rails/metric_stats.rb', __FILE__)
|
data/lib/scout_rails/agent.rb
CHANGED
@@ -63,27 +63,46 @@ module ScoutRails
|
|
63
63
|
@started = true
|
64
64
|
logger.info "Starting monitoring. Framework [#{environment.framework}] App Server [#{environment.app_server}]."
|
65
65
|
start_instruments
|
66
|
-
if !
|
66
|
+
if !start_background_worker?
|
67
67
|
logger.debug "Not starting worker thread"
|
68
|
-
|
68
|
+
install_passenger_events if environment.app_server == :passenger
|
69
69
|
install_unicorn_worker_loop if environment.app_server == :unicorn
|
70
70
|
return
|
71
71
|
end
|
72
|
-
|
72
|
+
start_background_worker
|
73
73
|
handle_exit
|
74
74
|
logger.info "Scout Agent [#{ScoutRails::VERSION}] Initialized"
|
75
75
|
end
|
76
76
|
|
77
|
-
#
|
78
|
-
# whether we'll report these immediately or just store locally and risk having stale data.
|
77
|
+
# at_exit, calls Agent#shutdown to wrapup metric reporting.
|
79
78
|
def handle_exit
|
80
79
|
if environment.sinatra? || environment.jruby? || environment.rubinius?
|
81
80
|
logger.debug "Exit handler not supported"
|
82
81
|
else
|
83
|
-
at_exit
|
82
|
+
at_exit do
|
83
|
+
logger.debug "Shutdown!"
|
84
|
+
# MRI 1.9 bug drops exit codes.
|
85
|
+
# http://bugs.ruby-lang.org/issues/5218
|
86
|
+
if environment.ruby_19?
|
87
|
+
status = $!.status if $!.is_a?(SystemExit)
|
88
|
+
shutdown
|
89
|
+
exit status if status
|
90
|
+
else
|
91
|
+
shutdown
|
92
|
+
end
|
93
|
+
end # at_exit
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
97
|
+
# Called via an at_exit handler, it (1) stops the background worker and (2) runs it a final time.
|
98
|
+
# The final run ensures metrics are stored locally to the layaway / reported to scoutapp.com. Otherwise,
|
99
|
+
# in-memory metrics would be lost and a gap would appear on restarts.
|
100
|
+
def shutdown
|
101
|
+
return if !started?
|
102
|
+
@background_worker.stop
|
103
|
+
@background_worker.run_once
|
104
|
+
end
|
105
|
+
|
87
106
|
def started?
|
88
107
|
@started
|
89
108
|
end
|
@@ -96,14 +115,20 @@ module ScoutRails
|
|
96
115
|
# * A supported application server isn't detected (example: running via Rails console)
|
97
116
|
# * A supported application server is detected, but it forks (Passenger). In this case,
|
98
117
|
# the agent is started in the forked process.
|
99
|
-
def
|
118
|
+
def start_background_worker?
|
100
119
|
!environment.forking? or environment.app_server == :thin
|
101
120
|
end
|
102
121
|
|
103
|
-
def
|
122
|
+
def install_passenger_events
|
104
123
|
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
105
124
|
logger.debug "Passenger is starting a worker process. Starting worker thread."
|
106
|
-
self.class.instance.
|
125
|
+
self.class.instance.start_background_worker
|
126
|
+
end
|
127
|
+
# The agent's at_exit hook doesn't run when a Passenger process stops.
|
128
|
+
# This does run when a process stops.
|
129
|
+
PhusionPassenger.on_event(:stopping_worker_process) do
|
130
|
+
logger.debug "Passenger is stopping a worker process, shutting down the agent."
|
131
|
+
ScoutRails::Agent.instance.shutdown
|
107
132
|
end
|
108
133
|
end
|
109
134
|
|
@@ -112,52 +137,29 @@ module ScoutRails
|
|
112
137
|
Unicorn::HttpServer.class_eval do
|
113
138
|
old = instance_method(:worker_loop)
|
114
139
|
define_method(:worker_loop) do |worker|
|
115
|
-
ScoutRails::Agent.instance.
|
140
|
+
ScoutRails::Agent.instance.start_background_worker
|
116
141
|
old.bind(self).call(worker)
|
117
142
|
end
|
118
143
|
end
|
119
144
|
end
|
120
145
|
|
121
|
-
# in seconds, time between when the worker thread wakes up and runs.
|
122
|
-
def period
|
123
|
-
60
|
124
|
-
end
|
125
|
-
|
126
146
|
# Creates the worker thread. The worker thread is a loop that runs continuously. It sleeps for +Agent#period+ and when it wakes,
|
127
147
|
# processes data, either saving it to disk or reporting to Scout.
|
128
|
-
def
|
148
|
+
def start_background_worker
|
129
149
|
logger.debug "Creating worker thread."
|
130
|
-
@
|
131
|
-
|
132
|
-
|
133
|
-
next_time = Time.now + period
|
134
|
-
while true do
|
135
|
-
now = Time.now
|
136
|
-
while now < next_time
|
137
|
-
sleep_time = next_time - now
|
138
|
-
sleep(sleep_time) if sleep_time > 0
|
139
|
-
now = Time.now
|
140
|
-
end
|
141
|
-
process_metrics
|
142
|
-
while next_time <= now
|
143
|
-
next_time += period
|
144
|
-
end
|
145
|
-
end
|
146
|
-
rescue
|
147
|
-
logger.debug "Worker Thread Exception!!!!!!!"
|
148
|
-
logger.debug $!.message
|
149
|
-
logger.debug $!.backtrace
|
150
|
-
end
|
150
|
+
@background_worker = ScoutRails::BackgroundWorker.new
|
151
|
+
@background_worker_thread = Thread.new do
|
152
|
+
@background_worker.start { process_metrics }
|
151
153
|
end # thread new
|
152
154
|
logger.debug "Done creating worker thread."
|
153
155
|
end
|
154
156
|
|
155
|
-
# Called from #process_metrics, which is run via the worker
|
157
|
+
# Called from #process_metrics, which is run via the background worker.
|
156
158
|
def run_samplers
|
157
159
|
begin
|
158
160
|
cpu_util=@process_cpu.run # returns a hash
|
159
161
|
logger.debug "Process CPU: #{cpu_util.inspect} [#{environment.processors} CPU(s)]"
|
160
|
-
store.track!("CPU/Utilization",cpu_util) if cpu_util
|
162
|
+
store.track!("CPU/Utilization",cpu_util,:scope => nil) if cpu_util
|
161
163
|
rescue => e
|
162
164
|
logger.info "Error reading ProcessCpu"
|
163
165
|
logger.debug e.message
|
@@ -167,7 +169,7 @@ module ScoutRails
|
|
167
169
|
begin
|
168
170
|
mem_usage=@process_memory.run # returns a single number, in MB
|
169
171
|
logger.debug "Process Memory: #{mem_usage}MB"
|
170
|
-
store.track!("Memory/Physical",mem_usage) if mem_usage
|
172
|
+
store.track!("Memory/Physical",mem_usage,:scope => nil) if mem_usage
|
171
173
|
rescue => e
|
172
174
|
logger.info "Error reading ProcessMemory"
|
173
175
|
logger.debug e.message
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Used to run a given task every 60 seconds.
|
2
|
+
class ScoutRails::BackgroundWorker
|
3
|
+
# in seconds, time between when the worker thread wakes up and runs.
|
4
|
+
PERIOD = 60
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@keep_running = true
|
8
|
+
end
|
9
|
+
|
10
|
+
def stop
|
11
|
+
@keep_running = false
|
12
|
+
end
|
13
|
+
|
14
|
+
# Runs the task passed to +start+ once.
|
15
|
+
def run_once
|
16
|
+
@task.call if @task
|
17
|
+
end
|
18
|
+
|
19
|
+
# Starts running the passed block every 60 seconds (starting now).
|
20
|
+
def start(&block)
|
21
|
+
@task = block
|
22
|
+
begin
|
23
|
+
ScoutRails::Agent.instance.logger.debug "Starting Background Worker, running every #{PERIOD} seconds"
|
24
|
+
next_time = Time.now
|
25
|
+
while @keep_running do
|
26
|
+
now = Time.now
|
27
|
+
while now < next_time
|
28
|
+
sleep_time = next_time - now
|
29
|
+
sleep(sleep_time) if sleep_time > 0
|
30
|
+
now = Time.now
|
31
|
+
end
|
32
|
+
@task.call
|
33
|
+
while next_time <= now
|
34
|
+
next_time += PERIOD
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
ScoutRails::Agent.instance.logger.debug "Background Worker Exception!!!!!!!"
|
39
|
+
ScoutRails::Agent.instance.logger.debug $!.message
|
40
|
+
ScoutRails::Agent.instance.logger.debug $!.backtrace
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/scout_rails/version.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.8.pre.3
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Derek Haynes
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-11-
|
13
|
+
date: 2012-11-27 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: Monitors a Ruby on Rails application and reports detailed metrics on
|
16
16
|
performance to Scout, a hosted monitoring service.
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- lib/scout_rails/agent.rb
|
31
31
|
- lib/scout_rails/agent/logging.rb
|
32
32
|
- lib/scout_rails/agent/reporting.rb
|
33
|
+
- lib/scout_rails/background_worker.rb
|
33
34
|
- lib/scout_rails/config.rb
|
34
35
|
- lib/scout_rails/environment.rb
|
35
36
|
- lib/scout_rails/instruments/active_record_instruments.rb
|
@@ -66,9 +67,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
67
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
68
|
none: false
|
68
69
|
requirements:
|
69
|
-
- - ! '
|
70
|
+
- - ! '>'
|
70
71
|
- !ruby/object:Gem::Version
|
71
|
-
version:
|
72
|
+
version: 1.3.1
|
72
73
|
requirements: []
|
73
74
|
rubyforge_project: scout_rails
|
74
75
|
rubygems_version: 1.8.10
|