<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>OnRails.org: Monitoring Rails Performance with Munin and a Mongrel</title>
    <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby On Rails and related matters.</description>
    <item>
      <title>Monitoring Rails Performance with Munin and a Mongrel</title>
      <description>&lt;p&gt;Rails makes things easy on developers&amp;#8212;maybe &lt;strong&gt;too&lt;/strong&gt; easy.  It&amp;#8217;s not uncommon to reference an association while iterating over a collection of objects, resulting in a performance-devouring N+1 queries being executed.  Of course, this is easily fixed with eager loading of the association, but you get my point.  Rails can be a big gun, and it&amp;#8217;s easy to blow off your foot.&lt;/p&gt;


	&lt;p&gt;Once your application is moved into production, it becomes important to keep an eye on performance over time in order to get a feel for trends and plan capacity intelligently.  Numerous Rails &lt;a href="http://rails-analyzer.rubyforge.org/"&gt;performance&lt;/a&gt; &lt;a href="http://cfis.savagexi.com/articles/2007/07/10/how-to-profile-your-rails-application"&gt;measuring&lt;/a&gt; &lt;a href="http://railsbench.rubyforge.org/"&gt;tools&lt;/a&gt; exist, but I find that it helps to correlate performance of your application with simultaneous lower-level performance metrics of your system (CPU and Memory usage, Load Average, etc).  Besides that, hey!  Pretty Graphs!  Enter &lt;a href="http://munin.projects.linpro.no/"&gt;munin&lt;/a&gt;, an open-source, extensible monitoring tool with a number of out-of-the-box plugins that are useful to SysAdmin type folks.  There&amp;#8217;s a pretty decent (though brief) &lt;a href="http://www.howtoforge.com/server_monitoring_monit_munin"&gt;writeup on howtoforge&lt;/a&gt; that explains a bit more about how to go about getting your own munin.  Go ahead and check it out&amp;#8212;I&amp;#8217;ll chill here until you&amp;#8217;re back.&lt;/p&gt;


&lt;center&gt;...&lt;/center&gt;

	&lt;p&gt;That wasn&amp;#8217;t too bad, huh?  Okay, so at this point you should have a working munin instance.  It will take a few minutes of data collection before your graphs look like anything, but going forward, you&amp;#8217;ll have historical graphs of several key metrics for managing your server(s).  It&amp;#8217;s outside the scope of this article, but you can also set up munin to monitor multiple servers on your network, and/or alert you when critical threshold levels are passed.&lt;/p&gt;


	&lt;p&gt;Well, knowing &lt;span class="caps"&gt;CPU&lt;/span&gt; usage is great, but it would also be nice to have some idea what the average user experience is like on your site.  Does your Rails app perform differently at different times of day?  How long does it typically take for your app to render a page?  Is the majority of the time spent in the database, or rendering?  Is the response time about the same between production deployment versions?  I wanted answers to these questions too, so I came up with a small ruby program that watches your Rails log in realtime, and when munin asks, provides summary information about the performance of your application.  Below, I&amp;#8217;ll go over the code section by section; for those who want it now, scroll to the bottom of the article to find the download link.&lt;/p&gt;


	&lt;p&gt;The basis of the solution is a Ruby array:  we stuff values into it, then compute the average of all the values and clear the array each time munin pings us.  Every time a value is added, we also check it against the maximum already seen, so we can report the maximum response time in addition to the average.  We keep three of these objects around, one each for DB, Rendering, and Total response times.  There is also a mode that lets you look at the current value without consuming it&amp;#8212;useful for peeking inside without affecting the data that munin will ultimately see.  Here&amp;#8217;s the class that implements this functionality:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;accumulator&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Accumulator&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="attribute"&gt;@values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="attribute"&gt;@max&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;add&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@values&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
    &lt;span class="attribute"&gt;@max&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@max&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;average&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;read_only&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;return_value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="attribute"&gt;@values&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
      &lt;span class="constant"&gt;nil&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="attribute"&gt;@values&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;inject&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;sum&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;sum&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt; @values.length
    end
    @values = Array.new() unless read_only

    return_value
  end

  def max(read_only=false)
    return_value = @max
    @max = 0 unless read_only
    return_value
  end
end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;In the next section of the code, we build our accumulators, and begin tailing the logfile to extract performance numbers.  This requires the &lt;a href="http://file-tail.rubyforge.org/"&gt;file-tail gem&lt;/a&gt;, available from rubyforge.  Note that in my setup, this file resides in a subdirectory under &lt;code&gt;lib&lt;/code&gt; in &lt;code&gt;RAILS_ROOT&lt;/code&gt;.  If you choose to place this file elsewhere, you&amp;#8217;ll have to adjust the path to the logfile accordingly.  Another thing to note:  in our environment, the load balancer continually pings a &amp;#8220;heartbeat&amp;#8221; action on each node to make sure it is still responsive.  As we will be hitting this action repeatedly, it is engineered to be as lightweight as possible.  Therefore, any numbers from it are pretty meaningless to our overall statistics, so we don&amp;#8217;t want to include them.  To keep these numbers from skewing our results, we define an &lt;code&gt;IGNORE_PATTERNS&lt;/code&gt; regexp (earlier in the code).  If the request matches a pattern we want to ignore, its statistics are not collected.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;tail&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;LOGFILE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;..&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;..&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{RAILS_ENV}&lt;/span&gt;.log&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="global"&gt;$response_data&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:total&lt;/span&gt;     &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;Accumulator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(),&lt;/span&gt;
                   &lt;span class="symbol"&gt;:rendering&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;Accumulator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(),&lt;/span&gt;
                   &lt;span class="symbol"&gt;:db&lt;/span&gt;        &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;Accumulator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;abort_on_exception&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
&lt;span class="ident"&gt;logtail&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Thread&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Tail&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Logfile&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tail&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;LOGFILE&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;line&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;line&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^Completed in &lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;
      &lt;span class="ident"&gt;parts&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;line&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\s&lt;/span&gt;+&lt;span class="escape"&gt;\|\s&lt;/span&gt;+&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt;
      &lt;span class="ident"&gt;resp&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;parts&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pop&lt;/span&gt;
      &lt;span class="ident"&gt;requested_url&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;resp&lt;/span&gt;&lt;span class="punct"&gt;[/&lt;/span&gt;&lt;span class="regex"&gt;http:&lt;span class="escape"&gt;\/\/&lt;/span&gt;[^&lt;span class="escape"&gt;\]&lt;/span&gt;]*&lt;/span&gt;&lt;span class="punct"&gt;/]&lt;/span&gt;
      &lt;span class="keyword"&gt;next&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;requested_url&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="constant"&gt;IGNORE_PATTERNS&lt;/span&gt;

      &lt;span class="ident"&gt;parts&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;part&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="ident"&gt;part&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub!&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;Completed in&lt;/span&gt;&lt;span class="punct"&gt;/,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;total&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
        &lt;span class="ident"&gt;type&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;pct&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;part&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\s&lt;/span&gt;+&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt;
        &lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;:&lt;/span&gt;&lt;span class="punct"&gt;/,'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;').&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt;

        &lt;span class="global"&gt;$response_data&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;type&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;add&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_f&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;So now we have a thread busy gathering our data&amp;#8212;how can we expose the data to a munin plugin?  There are multiple ways to do this, but I chose to use a small &lt;span class="caps"&gt;HTTP&lt;/span&gt; server listening to requests from the local machine only.  We could build such a thing in Rails, but we really don&amp;#8217;t need about 90% of the features Rails has to offer.  Since we&amp;#8217;re running Rails as a Mongrel cluster, we already have a perfect tool at our disposal for writing small &lt;span class="caps"&gt;HTTP&lt;/span&gt; request handlers in Ruby:  Mongrel.  Here are a couple of pages about how to get started &lt;a href="http://www.urbanhonking.com/ideasfordozens/archives/2007/05/my_first_mongre.html"&gt;writing&lt;/a&gt; &lt;a href="http://adam.blogs.bitscribe.net/2007/05/06/howto-custom-mongrel-handlers/"&gt;Mongrel&lt;/a&gt; &lt;a href="http://errtheblog.com/post/8444"&gt;handlers&lt;/a&gt;&amp;#8212;it&amp;#8217;s pretty straightforward.  Here&amp;#8217;s our handler:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;mongrel handler&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ResponseTimeHandler&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Mongrel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HttpHandler&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;method&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@method&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;method&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;process&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;200&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;head&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;debug&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Mongrel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HttpRequest&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;query_parse&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;QUERY_STRING&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]).&lt;/span&gt;&lt;span class="ident"&gt;has_key?&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;debug&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;head&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Content-Type&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;text/plain&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;output&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$response_data&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;send&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@method&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;debug&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;formatted&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;U&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;sprintf&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;%.5f&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

        &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{k}&lt;/span&gt;.value &lt;span class="expr"&gt;#{formatted}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;output&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;write&lt;/span&gt; &lt;span class="ident"&gt;output&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;h&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Mongrel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HttpServer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;127.0.0.1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;PORT&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="ident"&gt;h&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;register&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/avg_response_time&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;ResponseTimeHandler&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:average&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
&lt;span class="ident"&gt;h&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;register&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/max_response_time&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;ResponseTimeHandler&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:max&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
&lt;span class="ident"&gt;h&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;run&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The handler is generic so that it can call an arbitrary method on our collection of data arrays, so we can set up one &lt;span class="caps"&gt;URI&lt;/span&gt; for the average, and one for the maximum.  With this in place, we can write a simple munin plugin script that uses &lt;code&gt;Net::HTTP&lt;/code&gt; to query our Mongrel to get at the performance data.&lt;/p&gt;


	&lt;p&gt;Basically, a munin plugin has two usage scenarios.  When called with the single argument &amp;#8220;config&amp;#8221;, it should output information about itself in a format that Munin understands.  This includes how to label the chart, scaling information, how many series will be included on the chart, etc.  When called with no arguments, the plugin should output the current values of each series.  For more information on writing your own munin plugin, start with the &lt;a href="http://munin.projects.linpro.no/wiki/HowToWritePlugins"&gt;HowToWritePlugins munin wiki page&lt;/a&gt;.  And now, our plugin script:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;rails_response_time&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="comment"&gt;# munin plugin to render rails response time graphs&lt;/span&gt;
&lt;span class="comment"&gt;# link to /etc/munin/plugins/avg_response_time and /etc/munin/plugins/max_response_time&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;open-uri&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="constant"&gt;PORT&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ENV&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;PORT&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;8888&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;config&lt;/span&gt;
  &lt;span class="ident"&gt;title&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;basename&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="global"&gt;$0&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;_&lt;/span&gt;&lt;span class="punct"&gt;').&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;capitalize&lt;/span&gt; &lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
  &lt;span class="ident"&gt;config&lt;/span&gt;&lt;span class="punct"&gt;=&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="constant"&gt;__END_CONFIG__&lt;/span&gt;&lt;span class="string"&gt;
graph_title &lt;span class="expr"&gt;#{title}&lt;/span&gt;
graph_vlabel response time
graph_category rails
total.label total
rendering.label rendering
db.label db
&lt;/span&gt;&lt;span class="constant"&gt;__END_CONFIG__&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;config&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;get_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;read_only&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;qs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;read_only&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;?debug&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;open&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;http://127.0.0.1:&lt;span class="expr"&gt;#{PORT}&lt;/span&gt;/&lt;span class="expr"&gt;#{File.basename($0)}#{qs}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;read&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;
&lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;config&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;config&lt;/span&gt;
&lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;debug&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;get_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt;
  &lt;span class="ident"&gt;get_data&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The script will examine the name with which you linked it in to the munin plugins directory to determine which &lt;span class="caps"&gt;URI&lt;/span&gt; to query.  I have also added a debug mode that will show you the current values, so you&amp;#8217;re not consuming any data that munin needs to see for an accurate graph.  The final piece is a small &lt;a href="http://daemons.rubyforge.org/"&gt;Daemons&lt;/a&gt; wrapper script to control the main log-tailing process, and you should be set.  Make sure to restart munin-node so it will notice the new plugins, and after a while, you&amp;#8217;ll see something like this:&lt;/p&gt;


	&lt;p&gt;&lt;img src="/files/avg_response_time.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;It is worth noting that the numbers from the Rails log might not be 100% accurate, and this won&amp;#8217;t replace the results that you can get from seriously profiling your application.  Also, the information you are getting is a bit generic&amp;#8212;all actions are lumped together, so there is not a lot of information about the cause of the performance problem.  But, for insight into your production application performance, this setup should at least give you some indications about how well your baby is playing in the interwebs.&lt;/p&gt;


	&lt;p&gt;Download &lt;a href="/files/rails_log_monitor.rb"&gt;rails_log_monitor.rb&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Download &lt;a href="/files/rails_response_time"&gt;rails_response_time&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 31 Aug 2007 18:29:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:e71c0dbd-1196-4b9f-8faf-ce5e92b1bee0</guid>
      <author>Solomon White</author>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel</link>
      <category>Ruby On Rails</category>
      <category>Rails Tips</category>
      <category>mongrel</category>
      <category>munin</category>
      <category>performance</category>
      <category>monitoring</category>
      <category>Rails</category>
      <enclosure url="http://onrails.org/files/rails_log_monitor.rb" length="2411" type="application/octet-stream"/>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Moses Hohman</title>
      <description>&lt;p&gt;Thanks for this neat idea. I&amp;#8217;ve wrapped this up into a rails plugin, split the script into a few classes and added some RSpec specs. If you&amp;#8217;re interested maybe we could combine efforts?&lt;/p&gt;


	&lt;p&gt;Also, do you just run in debug logging mode for ActiveRecord in your production environment? If not, how do you get DB times?&lt;/p&gt;</description>
      <pubDate>Sat, 31 May 2008 00:35:12 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:8632650b-ba42-48c5-93c3-cccf189557a9</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-3640</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by David Jones</title>
      <description>&lt;p&gt;One thing to add to Shawn Pyle&amp;#8217;s comment, is to make daemon.rb executable. Simply run chmod +x daemon.rb&lt;/p&gt;


	&lt;p&gt;Do that just before you run ./daemon.rb start&lt;/p&gt;</description>
      <pubDate>Fri, 07 Mar 2008 01:56:13 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:7ebb7e40-4b6c-41ea-8228-389d373a63f9</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-3363</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by David Jones</title>
      <description>&lt;p&gt;Thanks heaps! this rocks.&lt;/p&gt;</description>
      <pubDate>Thu, 06 Mar 2008 22:30:51 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:ff89db57-afcf-42f6-a059-b67bd6b90235</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-3362</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Ian Connor</title>
      <description>&lt;p&gt;The links all seem to work and I see a &amp;#8220;Rails&amp;#8221; link now in my /munin url. This works really well &amp;#8211; thanks. 
Has anyone got this working with monit in some way?&lt;/p&gt;</description>
      <pubDate>Sun, 17 Feb 2008 18:40:35 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:fa65886f-db06-4fbc-8a12-db11f0fe8c48</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-3264</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Rente</title>
      <description>&lt;p&gt;Same problem as Mario now, the download link don&amp;#8217;t work.&lt;/p&gt;


	&lt;p&gt;i will try ist again, at the moment there are a 404&lt;/p&gt;</description>
      <pubDate>Fri, 08 Feb 2008 00:29:19 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:d4beb167-0c54-43a0-ac99-43c29d50eae3</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-3253</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Solomon</title>
      <description>&lt;p&gt;@shawn:&lt;/p&gt;


	&lt;p&gt;Thanks for the update.  By the way, this is now a rubyforge project (&lt;a href="http://tail2munin.rubyforge.org"&gt;http://tail2munin.rubyforge.org&lt;/a&gt;).  One of the near-term goals is to make this pluggable, allowing for exposing non-rails logs and/or multiple rails logs to munin.  If anyone has any input on how this should look, let me know&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Fri, 16 Nov 2007 18:49:14 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:496e34a5-d7f8-418a-bfc4-d0e117b41c2f</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-2822</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Shawn Pyle</title>
      <description>&lt;p&gt;Thanks for posting this. Very helpful. It took me a bit to get this to work as I hadn&amp;#8217;t worked with Mongrel handlers or Daemons. Here&amp;#8217;s the process I went through on RHEL 4.&lt;/p&gt;


&lt;pre&gt;
#This setup runs on port 8888 which may need to change if there is other 

gem update --system #if system gives 'gem not found' error
gem install file-tail

#Install log monitor for the rails application
cd [RAILS_ROOT]/lib
mkdir log_monitor
cd log_monitor
wget &lt;a href="http://onrails.org/files/rails_log_monitor.rb"&gt;http://onrails.org/files/rails_log_monitor.rb&lt;/a&gt;
chmod +x rails_log_monitor.rb

#Create and run daemon for monitoring the log
emacs daemon.rb
    #!/usr/bin/env ruby
    require 'rubygems' # if you use RubyGems
    require 'daemons'
    Daemons.run('rails_log_monitor.rb')
./daemon.rb start

#Install munin plugin
cd /usr/share/munin/plugins
wget &lt;a href="http://onrails.org/files/rails_response_time"&gt;http://onrails.org/files/rails_response_time&lt;/a&gt;
ln -s /usr/share/munin/plugins/rails_response_time /etc/munin/plugins/avg_response_time
ln -s /usr/share/munin/plugins/rails_response_time /etc/munin/plugins/max_response_time

#At this point, you should be able check that data is being collected and no errors result
/etc/munin/plugins/avg_response_time config
/etc/munin/plugins/avg_response_time debug
/etc/munin/plugins/avg_response_time
/etc/munin/plugins/max_response_time config
/etc/munin/plugins/max_response_time debug
/etc/munin/plugins/max_response_time

#Restart munin
sudo /etc/init.d/munin-node restart
&lt;/pre&gt;

	&lt;p&gt;Does anyone have a solution for multiple rails apps on a single machine?&lt;/p&gt;</description>
      <pubDate>Fri, 16 Nov 2007 17:33:55 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:fb1bdcfc-822b-4bd8-b306-9456473681a4</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-2821</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Daniel Wanja</title>
      <description>&lt;p&gt;Hi Mario,
The downloads seem to work. Note the second doesn&amp;#8217;t have an extension so the browser may think it&amp;#8217;s binary. But after downloading you can open it in any text editor as it&amp;#8217;s just a shell script.&lt;/p&gt;</description>
      <pubDate>Tue, 06 Nov 2007 19:50:38 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:1a8976af-1e73-48c0-b194-55515a9f25e7</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-2703</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Mario</title>
      <description>&lt;p&gt;hmm, the downloadlink is broken, there are a mirror?&lt;/p&gt;</description>
      <pubDate>Tue, 06 Nov 2007 10:14:39 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:c459681c-4522-49b8-a9a9-8554ecf3f691</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-2700</link>
    </item>
    <item>
      <title>"Monitoring Rails Performance with Munin and a Mongrel" by Tom</title>
      <description>&lt;p&gt;Way cool.&lt;/p&gt;</description>
      <pubDate>Fri, 31 Aug 2007 19:36:19 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:f3e8a468-7ac8-4cf7-8994-d6b43244bd35</guid>
      <link>http://onrails.org/articles/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel#comment-2595</link>
    </item>
  </channel>
</rss>
