updated install and run docs
[god.git] / site / index.html
bloba5f233748819ff49b2c260fa399f346022b1881d
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">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5 <title>god - process and task monitoring done right</title>
6 <link href="styles.css" rel="stylesheet" type="text/css" />
7 <style type="text/css" media="screen">
8 * {
9 margin: 0;
10 font-size: 100%;
13 body {
14 font: normal .8em/1.5em "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
15 color: #484848;
16 background: #E6EAE9 url(images/bg_grey.gif);
19 a {
20 color: #c75f3e;
21 text-decoration: none;
24 a:hover,
25 a:active {
26 text-decoration: underline;
29 #mothership {
30 width: 307px;
31 height: 117px;
32 margin: 0 auto;
33 background: url(images/god_logo1.gif);
36 #content {
37 width: 700px;
38 margin: 3px auto;
39 background: white;
40 border: 1px solid #444;
41 padding: 0 24px;
42 background: #f8f8ff;
43 overflow: hidden;
46 .banner {
47 margin-top: 24px;
48 border: 1px solid #ddd;
49 width: 698px;
50 height: 150px;
51 background: url(images/banner.jpg);
54 #menu {
55 margin-top: 5px;
58 #menu div.dots {
59 background: url(images/red_dot.gif) repeat;
60 height: 5px;
61 width: 700px;
62 font-size: 0;
65 #menu ul {
66 font-family: "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
67 font-weight: bold;
68 text-transform: uppercase;
69 color: #4D4D4D;
70 font-size: 12px;
71 padding: 0;
72 margin: 0;
73 margin-top: 0 !important;
74 margin-top: -2px;
77 #menu li {
78 display: inline;
79 margin: 0 30px 0 0;
82 #menu a:link,
83 #menu a:visited {
84 color: #4D4D4D;
85 text-decoration: none;
88 #menu a:hover,
89 #menu a:active {
90 color: black;
91 text-decoration: none;
94 #page_home #menu li.menu_home a {
95 color: #A70000;
98 .columnleft {
99 float: left;
100 width: 325px;
101 margin-bottom: 20px;
104 .columnleft p {
105 text-align: justify;
108 .columnright {
109 float: right;
110 width: 325px;
111 margin-bottom: 20px;
114 h1 {
115 font: bold 1.5em "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
116 color: #f36e21;
117 text-transform: uppercase;
118 margin: 1.5em 0 .5em 0;
119 clear: both;
123 margin-bottom: 1em;
126 ul.features {
127 padding: 0;
128 margin-left: 1.5em !important;
129 margin-left: 1.3em;
132 ul.features li {
133 list-style-position: outside;
134 list-style-type: circle;
135 list-style-image: url(images/bullet.jpg);
136 line-height: 1.4em;
139 #footer {
140 text-align: center;
141 color: white;
142 margin-bottom: 50px;
147 pre {
148 line-height: 1.3;
149 border: 1px solid #ccc;
150 padding: 1em;
151 background-color: #efefef;
152 margin: 1em 0;
155 code {
156 font-size: 1.2em;
159 .ruby .keywords {
160 color: blue;
163 .ruby .comment {
164 color : green;
167 .ruby .string {
168 color : teal;
171 .ruby .keywords {
172 color : navy;
175 .ruby .brackets {
176 color : navy;
178 </style>
180 <script type="text/javascript" src="javascripts/code_highlighter.js"></script>
181 <script type="text/javascript" src="javascripts/ruby.js"></script>
183 </head>
185 <body id="page_home">
187 <div id="mothership">
189 </div>
190 <div id="content">
191 <div class="banner">
193 </div>
195 <!-- <div id="menu">
196 <div class="dots"></div>
197 <ul>
198 <li class="menu_home"><a href="/">Home</a></li>
199 <li class="menu_contact"><a href="mailto:tom@projectmothership.com">Contact</a></li>
200 </ul>
201 <div class="dots"></div>
202 </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 framework written in Ruby.</p>
207 <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>
208 </div>
210 <div class="columnright">
211 <h1>Features</h1>
212 <ul class="features">
213 <li>Config file is written in Ruby</li>
214 <li>Easily write your own custom conditions in Ruby</li>
215 <li>Supports both poll and event based conditions</li>
216 <li>Different poll conditions can have different intervals</li>
217 </ul>
218 </div>
220 <h1>Installation</h1>
221 <p>The best way to get god is via rubygems:</p>
222 <pre>$ sudo gem install god</pre>
223 <p>You can also peruse or clone the code from <a href="http://repo.or.cz/w/god.git">http://repo.or.cz/w/god.git</a></p>
225 <h1>Finally, a Config File that Makes Sense</h1>
226 <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>
228 <pre><code class="ruby"># file: gravatar.god
229 # run with: god start -c /path/to/gravatar.god
231 # This is the actual config file used to keep the mongrels of
232 # gravatar.com running.
234 RAILS_ROOT = "/var/www/gravatar2/current"
236 God.meddle do |god|
237 %w{8200 8201 8202}.each do |port|
238 god.watch do |w|
239 w.name = "gravatar2-mongrel-#{port}"
240 w.interval = 30 # seconds
241 w.start = "mongrel_rails cluster::start --only #{port} -c #{RAILS_ROOT}"
242 w.stop = "mongrel_rails cluster::stop --only #{port} -c #{RAILS_ROOT}"
243 w.grace = 10 # seconds
245 pid_file = File.join(RAILS_ROOT, "log/mongrel.#{port}.pid")
247 w.behavior(:clean_pid_file) do |b|
248 b.pid_file = pid_file
251 w.start_if do |start|
252 start.condition(:process_not_running) do |c|
253 c.interval = 5 # seconds
254 c.pid_file = pid_file
258 w.restart_if do |restart|
259 restart.condition(:memory_usage) do |c|
260 c.pid_file = pid_file
261 c.above = (150 * 1024) # 150mb
262 c.times = [3, 5] # 3 out of 5 intervals
265 restart.condition(:cpu_usage) do |c|
266 c.pid_file = pid_file
267 c.above = 50 # percent
268 c.times = 5
273 end</code></pre>
275 <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>
277 <pre><code class="ruby">RAILS_ROOT = "/var/www/gravatar2/current"</code></pre>
279 <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>
281 <pre><code class="ruby">God.meddle do |god|
283 end</code></pre>
285 <p>The meat of the config file is defined inside a <code>God.meddle</code> block.</p>
287 <pre><code class="ruby"> %w{8200 8201 8202}.each do |port|
289 end</code></pre>
291 <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>
293 <pre><code class="ruby"> god.watch do |w|
294 w.name = "gravatar2-mongrel-#{port}"
295 w.interval = 30 # seconds
296 w.start = "mongrel_rails cluster::start --only #{port} -c #{RAILS_ROOT}"
297 w.stop = "mongrel_rails cluster::stop --only #{port} -c #{RAILS_ROOT}"
298 w.grace = 10 # seconds
301 end</code></pre>
303 <p>A <code>watch</code> represents a single process or task that has concrete start, stop, and/or 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 <code>interval</code> option sets the default poll interval (this can be overridden in each condition). 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. The optional <code>grace</code> attribute sets the amount of time following a start/stop/restart command to wait before resuming normal monitoring operations.</p>
305 <pre><code class="ruby"> pid_file = File.join(RAILS_ROOT, "log/mongrel.#{port}.pid")</code></pre>
307 <p>A variable to hold the location of the PID file.</p>
309 <pre><code class="ruby"> w.behavior(:clean_pid_file) do |b|
310 b.pid_file = pid_file
311 end</code></pre>
313 <p>Behaviors allow you to execute additional commands around start/stop/restart commands. In our case, if the process dies it will leave a PID file behind. The next time a start command is issued, it will fail, complaining about the leftover PID file. We'd like the PID file cleaned up before a start command is issued. The built-in behavior <code>clean_pid_file</code> will do just that. All we have to do is specify the location of the PID file.</p>
315 <pre><code class="ruby"> w.start_if do |start|
316 start.condition(:process_not_running) do |c|
317 c.interval = 5 # seconds
318 c.pid_file = pid_file
320 end</code></pre>
322 <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
323 <code>:process_not_running</code>. Each condition can specify a poll interval that will override the default watch interval. In this case, I want to check that the process is still running every 5 seconds instead of the 30 second interval that other conditions will inherit. The ability to set condition specific poll intervals makes it possible to run costly tests less often then cheap tests.</p>
325 <pre><code class="ruby"> w.restart_if do |restart|
326 restart.condition(:memory_usage) do |c|
327 c.pid_file = pid_file
328 c.above = (150 * 1024) # 150mb
329 c.times = [3, 5] # 3 out of 5 intervals
333 end</code></pre>
335 <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>
337 <pre><code class="ruby"> w.restart_if do |restart|
340 restart.condition(:cpu_usage) do |c|
341 c.pid_file = pid_file
342 c.above = 50 # percent
343 c.times = 5
345 end</code></pre>
347 <p>To keep an eye on CPU usage, I've employed the <code>cpu_usage</code> condition. When CPU usage for a Mongrel process is over 50% for 5 consecutive intervals, it will be restarted.</p>
349 <h1>Starting God</h1>
351 <p>To start the god monitoring process simply run the <code>god</code> executable passing in the path to the config file:</p>
353 <pre>$ god start -c /path/to/config.god</pre>
355 <p>While you're writing your config file, it can be helpful to run god in the foreground so you can see the log messages. You can do that with:</p>
357 <pre>$ god run -c /path/to/config.god</pre>
359 <h1>Extend God with your own Conditions</h1>
361 <p>God was designed from the start to allow you to easily write your own custom conditions, making it simple to add tests that are application specific.</p>
363 <pre><code class="ruby">module God
364 module Conditions
366 class ProcessNotRunning < PollCondition
367 attr_accessor :pid_file
369 def valid?
370 valid = true
371 valid &= complain("You must specify the 'pid_file' attribute
372 for :process_not_running") if self.pid_file.nil?
373 valid
376 def test
377 return false unless File.exist?(self.pid_file)
379 pid = File.open(self.pid_file).read.strip
380 System::Process.new(pid).exists?
385 end</code></pre>
387 </div>
388 <div id="footer">
389 <p>Brought to you by <a href="http://rubyisawesome.com/">Ruby is Awesome</a></p>
390 </div>
392 <script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
393 </script>
394 <script type="text/javascript">
395 _uacct = "UA-2196727-1";
396 urchinTracker();
397 </script>
399 </body>
400 </html>