Skip to content

Instantly share code, notes, and snippets.

@kristopolous
Created June 29, 2012 20:46
Show Gist options
  • Save kristopolous/3020544 to your computer and use it in GitHub Desktop.
Save kristopolous/3020544 to your computer and use it in GitHub Desktop.
OmniLogger
class OmniLog
attr_reader :available
def initialize(path)
@real = Logger.new(path)
@fake = Logger.new("/dev/null")
@available = Set.new
end
def add!(which)
unless respond_to? which
self.class.instance_eval do
define_method(which.to_sym) { @real }
end
@available << which
end
end
def remove!(which)
which = which.to_sym
self.class.instance_eval do
undef_method which if respond_to? which
end
end
def method_missing(meth, *args, &block)
@real.method(meth).call(*args) if @real.respond_to? meth
@available << meth unless @available.include? meth
@fake
end
end
@kristopolous
Copy link
Author

It's similar to Logger (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/…) but it has one extra big one:

namespaces.

The problem is that my application gets big and I want to be able to look at say, just the debug messages for a certain section, there was no good way of having a huge heap to catch them all, without it going by showing a bunch of stuff I don't want.

So I created OmniLog. Instead of doing something like

myLog = Logger.new("log.txt")

you do

myLog = OmniLog.new("log.txt")

myLog.[debug, warn, fatal, error, info] still work as before, but now you can do

myLog.connectionManager.debug "blah"

and then turn on "connectionManager" messages anywhere by doing

myLog.add! "connectionManager"

or removing them by doing

myLog.remove! "connectionManager"

You can also get all the available namespaces by doing

(Set) myLog.available

My usage scenario is near the top of my application I have something like

$log = OmniLog.new("log.txt")

%w(a b c d e).each { | which | $log.add which }

So then I can freely add and remove sections with a single line change, regardless of the severity of the thing being logged

@paneq
Copy link

paneq commented Jul 4, 2012

Could you provide some kind of benchmark. This vs Logger vs Syslog ?

@kristopolous
Copy link
Author

Hi paneq. It's certainly slower than Logger since it's a wrapper. It pivots on method_missing, which would probably be the biggest performance hit. I don't know the profiling of Logger vs. Syslog.

I understand what you are getting at though ... a free tracing/logging that you can simply disable and everything goes as if you didn't have the code there. Right ... that's a wonderful goal, but that's not this one.

This was more to address what can be the ridiculous verbosity of logs in a complex application. My programming style in ruby doesn't really involve a debugger, it involves just immense printing of information.

Having a single dimension of severity doesn't really help me isolate a problem. I could simply add and remove debug messages, but in the real world, things are stateful unfortunately so you often get problems from large scale cascaded parts interacting with each other (my big application for this right now is a peer-to-peer networking system). So simply being tidy about adding and then removing debug messages will add overhead once your application gets big.

No. It would be nice if I could tell large swaths to shutup or print as necessary. That's really the primary goal of this abstraction. Performance really wasn't a goal, and if it is yours, then I suggest you totally discard this solution and think from the ground up ... since I never had it as a conscious goal, your end result will probably look dramatically different from mine, whether you start with mine or not.

Best of luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment