1 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns=
"http://www.w3.org/1999/xhtml">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=iso-8859-1" />
5 <title>Project.Mothership
</title>
6 <link href=
"styles.css" rel=
"stylesheet" type=
"text/css" />
7 <style type=
"text/css" media=
"screen">
14 font: normal
.8em/
1.5em
"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
16 background: #E6EAE9 url(images/bg_grey.gif);
21 text-decoration: none;
26 text-decoration: underline;
33 background: url(images/god_logo1.gif);
40 border:
1px solid #
444;
48 border:
1px solid #ddd;
51 background: url(images/banner.jpg);
59 background: url(images/red_dot.gif) repeat;
66 font-family:
"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
68 text-transform: uppercase;
73 margin-top:
0 !important;
85 text-decoration: none;
91 text-decoration: none;
94 #page_home #menu li.menu_home a {
115 font: bold
1.5em
"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
117 text-transform: uppercase;
118 margin:
1.5em
0 .5em
0;
128 margin-left:
1.5em !important;
133 list-style-position: outside;
134 list-style-type: circle;
135 list-style-image: url(images/bullet.jpg);
149 border:
1px solid #ccc;
151 background-color: #efefef;
180 <script type=
"text/javascript" src=
"javascripts/code_highlighter.js"></script>
181 <script type=
"text/javascript" src=
"javascripts/ruby.js"></script>
185 <body id=
"page_home">
187 <div id=
"mothership">
196 <div class="dots"></div>
198 <li class="menu_home"><a href="/">Home</a></li>
199 <li class="menu_contact"><a href="mailto:tom@projectmothership.com">Contact</a></li>
201 <div class="dots"></div>
204 <div class=
"columnleft">
205 <h1>A Better Way to Monitor
</h1>
206 <p>God is an easy to configure, easy to extend monitoring library written in Ruby.
</p>
210 <div class=
"columnright">
212 <ul class=
"features">
213 <li>Config file is written in Ruby
</li>
214 <li>Write your own conditions in Ruby
</li>
218 <h1>Simple is Better
</h1>
219 <p>Keeping your server processes and tasks running should be a simple part of your deployment process. God aims to be the simplest, most powerful monitoring application available.
</p>
221 <h1>Finally, a Config File that Makes Sense
</h1>
222 <p>The easiest way to understand how god will make your life better is by looking at a sample config file. The following configuration file is what I use at
<a href=
"http://site.gravatar.com/">gravatar.com
</a> to keep the mongrels running:
</p>
224 <pre><code class=
"ruby"># file: gravatar.god
226 # This is the actual config file used to keep the mongrels of
227 # gravatar.com running.
229 RAILS_ROOT =
"/var/www/gravatar2/current"
232 god.interval =
30 # seconds
234 %w{
8200 8201 8202}.each do |port|
236 w.name =
"gravatar2-mongrel-#{port}"
238 w.start =
"mongrel_rails cluster::start --only #{port}"
239 w.stop =
"mongrel_rails cluster::stop --only #{port}"
241 pid_file = File.join(RAILS_ROOT,
"log/mongrel.#{port}.pid")
243 w.start_if do |start|
244 start.condition(:process_not_running) do |c|
245 c.pid_file = pid_file
249 w.restart_if do |restart|
250 restart.condition(:memory_usage) do |c|
251 c.pid_file = pid_file
252 c.above = (
150 *
1024) #
150mb
253 c.times = [
3,
5] #
3 out of
5 intervals
256 restart.condition(:cpu_usage) do |c|
257 c.pid_file = pid_file
258 c.above =
50 # percent
266 <p>That's a lot to take in at once, so I'll break it down by section and explain what's going on in each.
</p>
268 <pre><code class=
"ruby">RAILS_ROOT =
"/var/www/gravatar2/current"</code></pre>
270 <p>Here I've set a constant that is used throughout the file. Keeping the
<code>RAILS_ROOT
</code> value in a constant makes it easy to adapt this script to other applications. Because the config file is Ruby code, I can set whatever variables or constants I want that make the configuration more concise and easier to work with.
</p>
272 <pre><code class=
"ruby">God.meddle do |god|
273 god.interval =
30 # seconds
278 <p>The meat of the config file is defined inside a
<code>God.meddle
</code> block. At this level, you set system wide settings like
<code>interval
</code>. In this case, we've specified that god should do a check every
30 seconds.
</p>
280 <pre><code class=
"ruby"> %w{
8200 8201 8202}.each do |port|
284 <p>Because the config file is written in actual Ruby code, we can construct loops and do other intelligent things that are impossible in your every day, run of the mill config file. I need to watch three mongrels, so I simply loop over their port numbers, eliminating duplication and making my life a whole lot easier.
</p>
286 <pre><code class=
"ruby"> god.watch do |w|
287 w.name =
"gravatar2-mongrel-#{port}"
289 w.start =
"mongrel_rails cluster::start --only #{port}"
290 w.stop =
"mongrel_rails cluster::stop --only #{port}"
295 <p>A
<code>watch
</code> represents a single process or task that has concrete start, stop, (and possibly restart) operations. You can define as many watches as you like inside the
<code>God.meddle
</code> block. In the example above, I've got a Rails instance running in a Mongrel that I need to keep alive. Every watch must have a unique
<code>name
</code> so that it can be identified later on. The optional
<code>cwd
</code> attribute tells god to switch to that directory before executing any commands. The
<code>start
</code> and
<code>stop
</code> attributes specify the commands to start and stop the process. If no
<code>restart
</code> attribute is set, restart will be represented by a call to stop followed by a call to start.
</p>
297 <pre><code class=
"ruby"> pid_file = File.join(RAILS_ROOT,
"log/mongrel.#{port}.pid")
</code></pre>
299 <p>Another variable to hold the location of the PID file.
</p>
301 <pre><code class=
"ruby"> w.start_if do |start|
302 start.condition(:process_not_running) do |c|
303 c.pid_file = pid_file
307 <p>Watches contain conditions grouped by the action to execute should they fail. I start with a
<code>start_if
</code> block that contains a single condition. Conditions are specified by calling
<code>condition
</code> with an identifier, in this case
308 <code>:process_not_running
</code>. This condition checks to see if the process corresponding to the PID found in the
<code>pid_file
</code> is currently running. If it's not, the condition will fail causing a start command to be issued. The
<code>process_not_running
</code> condition will take care of cleaning up orphaned PID files by default, so we don't have to worry about it. We could turn that behavior off by adding
<code>c.clean = false
</code>.
310 <pre><code class=
"ruby"> w.restart_if do |restart|
311 restart.condition(:memory_usage) do |c|
312 c.pid_file = pid_file
313 c.above = (
150 *
1024) #
150mb
314 c.times = [
3,
5] #
3 out of
5 intervals
320 <p>Similar to
<code>start_if
</code> there is a
<code>restart_if
</code> command that groups conditions that should trigger a restart. The
<code>memory_usage
</code> condition will fail if the specified process is using too much memory. Once again, the
<code>pid_file
</code> must be set. The maximum allowable amount of memory is specified with the
<code>above
</code> attribute in units of kilobytes. The number of times the test needs to fail in order to trigger a restart is set with
<code>times
</code>. This can be either an integer or an array. An integer means it must fail that many times in a row while an array [x, y] means it must fail x times out of the last y tests.
</p>
322 <pre><code class=
"ruby"> w.restart_if do |restart|
325 restart.condition(:cpu_usage) do |c|
326 c.pid_file = pid_file
327 c.above =
50 # percent
336 <p>Brought to you by
<a href=
"http://rubyisawesome.com/">Ruby is Awesome
</a></p>