<?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>The Dev Blog: Improving the Rails Logger</title>
    <link>http://devblog.famundo.com/articles/2006/09/22/improving-the-rails-logger</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Putting Family Management on Rails!</description>
    <item>
      <title>Improving the Rails Logger</title>
      <description>&lt;p&gt;The rails logger is &lt;em&gt;VERY&lt;/em&gt; useful. It amazes me that I don't really feel I need a debugger in rails (after using one for years in Visual C++) and a lot of it is the console and the logger.&lt;/p&gt;

&lt;p&gt;One thing missing from the logger, is the process id of the rails instance that is logging. This is important when you have more than one instance of your app serving requests through fcgi or mongrel or whatever. It's needed in order to enable us to see how the request was handled, as we can extract only logs that pertain to this specific request, even when it's mixed with other requests.&lt;/p&gt;

&lt;p&gt;Using the fact that all classes in Ruby are open, we modify the logger to do what we need. Either create a file in your lib directory, or anywhere else you prefer, and in your config/environment.rb add the line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'pid_logger'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The file should include the following (most of it extracted from the default rails logger):&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Logger&lt;/span&gt;
  &lt;span class="ident"&gt;private&lt;/span&gt;
    &lt;span class="comment"&gt;# Ruby 1.8.3 transposed the msg and progname arguments to format_message.&lt;/span&gt;
    &lt;span class="comment"&gt;# We can't test RUBY_VERSION because some distributions don't keep Ruby&lt;/span&gt;
    &lt;span class="comment"&gt;# and its standard library in sync, leading to installations of Ruby 1.8.2&lt;/span&gt;
    &lt;span class="comment"&gt;# with Logger from 1.8.3 and vice versa.&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;method_defined?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:formatter=&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;log_str&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&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;format_message&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;severity&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;timestamp&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;progname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;log_str&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;#{$$}&lt;/span&gt;][&lt;span class="expr"&gt;#{severity[0...1]}&lt;/span&gt;] msg&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="comment"&gt;# This is the only real change... Added a pid&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;format_message&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;severity&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;timestamp&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;progname&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;log_str&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;#{$$}&lt;/span&gt;][&lt;span class="expr"&gt;#{severity[0...1]}&lt;/span&gt;] msg&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="comment"&gt;# This is the only real change... Added a pid&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;One more possible change that I use in some applications, is to color the background of debug messages I sent to the logger. The change here is also very slight. Here is the same file, but with the added coloring of the output with a green or red background depending on severity, when a line start with 4 or more &gt; + - = characters (e.g: "&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; This is a test" will have the &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; part with a red backround if error, and green otherwize). It makes finding the log messages very eash.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Logger&lt;/span&gt;
  &lt;span class="ident"&gt;private&lt;/span&gt;
    &lt;span class="comment"&gt;# Ruby 1.8.3 transposed the msg and progname arguments to format_message.&lt;/span&gt;
    &lt;span class="comment"&gt;# We can't test RUBY_VERSION because some distributions don't keep Ruby&lt;/span&gt;
    &lt;span class="comment"&gt;# and its standard library in sync, leading to installations of Ruby 1.8.2&lt;/span&gt;
    &lt;span class="comment"&gt;# with Logger from 1.8.3 and vice versa.&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;method_defined?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:formatter=&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;log_str&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&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;format_message&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;severity&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;timestamp&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;progname&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;log_str&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;#{$$}&lt;/span&gt;][&lt;span class="expr"&gt;#{severity[0...1]}&lt;/span&gt;] &lt;span class="expr"&gt;#{color_special_msg(msg, severity)}&lt;/span&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="comment"&gt;# This is the only real change... Added a pid&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;format_message&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;severity&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;timestamp&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;progname&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;log_str&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;#{$$}&lt;/span&gt;][&lt;span class="expr"&gt;#{severity[0...1]}&lt;/span&gt;] &lt;span class="expr"&gt;#{color_special_msg(msg, severity)}&lt;/span&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="comment"&gt;# This is the only real change... Added a pid&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;def &lt;/span&gt;&lt;span class="method"&gt;color_special_msg&lt;/span&gt; &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;severity&lt;/span&gt;  
      &lt;span class="comment"&gt;# A small trick to get highlighting of the messages if they are our logged messages&lt;/span&gt;
      &lt;span class="comment"&gt;# that start with a long sequence of &amp;gt;&amp;gt;&amp;gt; or *****&lt;/span&gt;
      &lt;span class="ident"&gt;sub_color&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;severity&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="number"&gt;1&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;E&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;41&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;42&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;# Red for errors, green otherwize&lt;/span&gt;
      &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;^((&lt;span class="escape"&gt;\*&lt;/span&gt;|&amp;gt;|&lt;span class="escape"&gt;\+&lt;/span&gt;|-|=){4,})&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="escape"&gt;\033&lt;/span&gt;[1;&lt;span class="expr"&gt;#{sub_color}&lt;/span&gt;m&lt;span class="escape"&gt;\\&lt;/span&gt;1&lt;span class="escape"&gt;\033&lt;/span&gt;[0m&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="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And as you can see, adding whatever changes you want to the logger is easy. So go ahead and make it work the way &lt;em&gt;YOU&lt;/em&gt; want it to.&lt;/p&gt;</description>
      <pubDate>Fri, 22 Sep 2006 16:02:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4fa7a39f-639e-4d0c-a6e8-51653f099f5a</guid>
      <author>guy.naor@famundo.com (Guy Naor)</author>
      <link>http://devblog.famundo.com/articles/2006/09/22/improving-the-rails-logger</link>
      <category>Rails</category>
      <category>Ruby</category>
      <trackback:ping>http://devblog.famundo.com/articles/trackback/42</trackback:ping>
    </item>
  </channel>
</rss>
