# Logging object

**URL:** <https://www.ruby-forum.com/t/logging-object/112967>\
**Category:** Ruby\
**Created:** [August 25, 2007, 1:16am UTC](https://www.ruby-forum.com/t/logging-object/112967 "2007-08-25T01:16:05Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 1:16am UTC](https://www.ruby-forum.com/t/logging-object/112967/1 "2007-08-25T01:16:05Z")

</div>

Hi,

Can anyone suggest the best way to pass a Logger object around between  
all the classes in an application?

Currently I have it set in a constant in the top-level but I don’t  
feel that this is the best way to do it as it couples the code in each  
of my classes to the current implementation and makes it difficult for  
me to reuse the code elsewhere without first setting up a logger  
instance of the same name.

Thanks,  
Toby

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 3:56pm UTC](https://www.ruby-forum.com/t/logging-object/112967/2 "2007-08-25T15:56:29Z")

</div>

On Aug 25, 8:22 am, Jeremy W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 3:23pm UTC](https://www.ruby-forum.com/t/logging-object/112967/3 "2007-08-25T15:23:27Z")

</div>

removed\_email\_address@domain.invalid wrote:

> Thanks,  
> Toby

Surely any way you do this if a class writes to a logger you have to set  
up the logger first? But anyhow, I guess you could make a module that  
provides the logging and include that on all appropriate classes:

logging.rb:  
LOG = Logger.new(…)

module Logging  
def logger  
LOG || Logger.new(nil)  
end  
end

something.rb:  
require ‘logging’

class Something  
include Logging

def do\_something  
logger.info “something”  
end  
end

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 3:59pm UTC](https://www.ruby-forum.com/t/logging-object/112967/4 "2007-08-25T15:59:29Z")

</div>

On Sat, 25 Aug 2007, removed\_email\_address@domain.invalid wrote:

> Can anyone suggest the best way to pass a Logger object around between  
> all the classes in an application?
> 
> Currently I have it set in a constant in the top-level but I don’t  
> feel that this is the best way to do it as it couples the code in each  
> of my classes to the current implementation and makes it difficult for  
> me to reuse the code elsewhere without first setting up a logger  
> instance of the same name.

One approach is the way you are doing it. Just stuff your logger object  
into ::Logger or some other constant, and have all of your code access  
it.

If you only have a few specific methods that need logging, and your app  
structure allows it, you could have your app create a logger object that  
it explicitly passes to the classes that can do logging. If you aren’t  
going to be using the logging facilities when you reuse the code  
elsewhere, then you just pass a dummy logger to your methods.

You could create a more sophisticated union of those ideas, too. Create  
a  
MyApp::Logger class that, by default, just provides dummy logging  
facilities which just throw away the log messages. Provide a way that  
the  
dummy facilites can be overridden or initialized with a real logging  
destination, though.

Then write all of you code to require this class, and to use it for  
their  
logging.

Apps that use the code without needing the logging will work, because  
the  
default behavior is to just throw the logs away. Apps that need the  
logs  
can provide a real logging destination to your logger, though,  
preserving  
your logs.

This is essentially how I do it in the IOWA web development framework.  
There are a number of different logger classes which all adhere to the  
same API. The app developer can select the logger that they want to  
use,  
or provide their own, so long as it ahderes to the API, and all logging  
for the application will just work, regardless of what the actual  
logging  
destination is.

If you need _fast_ and flexible logging, you might also take a look at  
my  
Analogger package:

[http://analogger.swiftcore.org](http://analogger.swiftcore.org)

If provides a very fast, simple asynchronous logging service that might  
be  
useful to you.

Kirk H.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 4:35pm UTC](https://www.ruby-forum.com/t/logging-object/112967/5 "2007-08-25T16:35:31Z")

</div>

On Aug 25, 8:22 am, Jeremy W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > instance of the same name.  
> > I had a similar need, but I also needed a way to send emails from  
> > different classes as well, so the code started getting a lot of extra  
> > junk in it. I solved it by borrowing some code from zenspider’s  
> > autotest. I took his idea of hooks and plugins and extracted it into  
> > a mixin, so I can include it in all of my classes.

So in your toplevel file you might have:

require ‘hookable’  
require ‘foo’  
require ‘logging’  
require ‘email’  
require ‘other\_plugins’

foo.rb might look like this

class Foo  
include Hookable

def something  
hook :something\_happened  
end

end

then in logging.rb, you would have:

@log = Logger.new(…)

Foo.add\_hook(:something\_happened){|i| @log.info “something was  
called”}

Also, in the block, you have access to the object that called the  
hook.  
The hookable mixin code is here: [http://pastie.caboo.se/90899](http://pastie.caboo.se/90899)

regards,

Gordon

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 6:05pm UTC](https://www.ruby-forum.com/t/logging-object/112967/6 "2007-08-25T18:05:38Z")

</div>

On Aug 25, 3:34 pm, Gordon T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > of my classes to the current implementation and makes it difficult for
> 
> Foo.add\_hook(:something\_happened){|i| @log.info “something was  
> called”}
> 
> Also, in the block, you have access to the object that called the  
> hook.  
> The hookable mixin code is here:[http://pastie.caboo.se/90899](http://pastie.caboo.se/90899)
> 
> regards,
> 
> Gordon

Thanks for all of your help. I’m having a bit of trouble getting into  
the swing of OO properly - I mean I’ve read all the theory but in  
practice there’s still a lot to think about! I think it’s mostly the  
design patterns that I need to get used to as the actual  
technicalities of a language aren’t so difficult to pick up.

Anyhow, I think by picking bits from the methods suggested here I’ll  
be able to solve my problem. One other thing I was wondering about was  
my testing. How does one test that a log has actually been written to  
without writing to file but I was thinking if I have an object of a  
class that acts as a dummy logger that can also work as a real logger  
if required, I can query that object to see whether the log was  
actually written.

I like the idea of using hooks because then multiple actions can occur  
when a certain methods performs a certain task.

Another quick question, slightly off topic but something I’ve been  
thinking about with regard to this:

If I have a test that checks the status of a logger object to  
determine whether something is working correctly in the class under  
test, is this a functional test or a unit test?

Thanks,  
Toby

Again, thanks very much,  
Toby

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 25, 2007, 6:49pm UTC](https://www.ruby-forum.com/t/logging-object/112967/7 "2007-08-25T18:49:38Z")

</div>

removed\_email\_address@domain.invalid wrote:

> Hi,
> 
> Can anyone suggest the best way to pass a Logger object around between  
> all the classes in an application?
> 
> Currently I have it set in a constant in the top-level but I don’t  
> feel that this is the best way to do it as it couples the code in each  
> of my classes to the current implementation and makes it difficult for  
> me to reuse the code elsewhere without first setting up a logger  
> instance of the same name.
> 
> Thanks,  
> Toby

Actually I use a whole different approach. I do all logging with  
$stderr.puts(LogMessage.new(message, …)) (I actually have methods like  
info, error etc. in Kernel that make the task easier, but that’s what’s  
going on). LogMessage has a to\_s method, so if the lib is used in an  
environment that doesn’t make use of the LogMessage object, it will be  
IO#puts which calls to\_s on it.

Regards  
Stefan
