Forum: Ruby log4r configuration: "/dev/null" outputter question

C667185722eaecf12461cb423dc8b410?d=identicon&s=25 Ronald Fischer (Guest)
on 2007-07-17 14:38
(Received via mailing list)
Well, my code does seem to work, but I have the feeling that I could
have
done it much simpler.... So here is my problem:

I would like to control log4r via an environment variable, which can
contain one of 4 types of values:

  stdout         : logging goes to stdout
  stderr         : logging goes to stderr
  file:FILENAME  : logging goes to FILENAME
  none           : logging not needed

The problem is what outputter to use to implement 'none'. My first idea
to simply use FileOutputter('none',:filename => '/dev/null') does not
work
because my code is also supposed to run onder Windows where we don't
have
/dev/null. So I came up with the solution to invent a "NullOutputter":

class NullOutputter <Outputter
  def initialize(name)
    super(name)
  end
end

....

$log = Logger.new('TestLog')
outputterspec=ENV['TFW_LOG'] || 'stdout'
$log.outputters = case outputterspec
  when 'stdout'
    Outputter.stdout
  when 'stderr'
    Outputter.stderr
  when /^file:(.+)$/
    FileOutputter.new 'tfw', :filename => $1, :trunc => true
  when 'none'
    NullOutputter.new 'tfwnull'
  end

Note that I did NOT use

  when 'none'
    Outputter.new 'tfwnull'

because Outputter is documented as abstract class.

My solution works, but I wonder whether I could make it simpler
(i.e. without creating the NullOutputter class).


Ronald
4d5b5dd4e263d780a5dfe7ac8b8ac98c?d=identicon&s=25 Tim Pease (Guest)
on 2007-07-17 16:57
(Received via mailing list)
On 7/17/07, Ronald Fischer <ronald.fischer@venyon.com> wrote:
>
> The problem is what outputter to use to implement 'none'. My first idea
> to simply use FileOutputter('none',:filename => '/dev/null') does not
> work
> because my code is also supposed to run onder Windows where we don't
> have
> /dev/null.

There is a /dev/null equivalent on Windows, NUL:  You can use it in
this fashion ...

fn = test(?e, '/dev/null') ? '/dev/null' : 'NUL:'
fd = File.open(fn, 'w')

You can now write to that file descriptor and everything will go to
the bit bucket.

>
> My solution works, but I wonder whether I could make it simpler
> (i.e. without creating the NullOutputter class).
>

Certainly. Just create an instance of Outputter and then define the
methods you need.

out = Outputter.new 'tfwnull'
class << out
  def canonical_log(logevent) nil end
end

The canonical_log method is used by the outputters to format the log
event and then write the formatted output to a file. By setting this
to have a nil body, you will save a few cycles each time a log
messages needs to be generated.

Another options is just to set the global log level to 'off'. That is
left as an exercise for the reader ;-)

Blessings,
TwP
C667185722eaecf12461cb423dc8b410?d=identicon&s=25 Ronald Fischer (Guest)
on 2007-07-18 10:03
(Received via mailing list)
> end
Now I wonder, since Outputter is documented as *abstract* class, why
I can instantiate it at all? Or is "abstract class" in Ruby not dealt
with the same strength as in, say, Java or C++?

But anyway, I tried your approach, but I don't see how I get the
instance
of the anonymous class into my outputters. When I do it like this:

#!/usr/bin/ruby
require 'log4r'
include Log4r
$log=Logger.new('testing')
out = Outputter.new 'tfwnull'
$log.outputters=class << out
     def canonical_log(logevent) nil end
   end

I get the error message

  "Expected kind of Outputter, got NilClass (TypeError)"

Ronald
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.