Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an Asynchronous Logging Library for Ruby?

Synchronous logging incurs a large performance penalty as it may block. Is there a standalone Ruby library that does asynchronous logging (log4r doesn't seem to)? Can I modify the standard library logger to log asynchronously? I'm looking for something like log4j's AsyncAppender - but preferably an implementation that makes use of Ruby's code blocks to shift as much work to the background thread as possible.

like image 731
Nicholas White Avatar asked Jun 27 '11 22:06

Nicholas White


2 Answers

I know you shouldn't really answer your own question, but it seems everything is easy in ruby:

require 'thread'
require 'singleton'
require 'delegate'
require 'monitor'

class Async
  include Singleton

  def initialize
    @queue = Queue.new
    Thread.new { loop { @queue.pop.call } }
  end

  def run(&blk)
    @queue.push blk
  end
end

class Work < Delegator
  include MonitorMixin

  def initialize(&work)
    super work; @work, @done, @lock = work, false, new_cond
  end

  def calc
    synchronize {
      @result, @done = @work.call, true; 
      @lock.signal
    }
  end

  def __getobj__
    synchronize { @lock.wait_while { !@done } }
    @result
  end
end

Module.class.class_exec {
  def async(*method_names) 
    method_names.each do |method_name|
      original_method = instance_method(method_name)
      define_method(method_name) do |*args,&blk|
        work = Work.new { original_method.bind(self).call(*args,&blk) }
        Async.instance.run { work.calc }
        return work
      end
    end
  end
}

And for my logging example:

require 'Logger'
class Logger
  async :debug
end
log = Logger.new STDOUT
log.debug "heloo"

As return values work, you can use this for just about anything:

require "test/unit"
class ReturnValues < Test::Unit::TestCase
  def do_it
    5 + 7
  end
  async :do_it
  def test_simple
    assert_equal 10, do_it - 2
  end
end
like image 186
Nicholas White Avatar answered Nov 15 '22 17:11

Nicholas White


No personal experience with that:

  • https://github.com/dirs/analogger

The Swiftcore Analogger implements a fast asynchronous logging system for Ruby programs as well as client library for sending logging messages to the Analogger process.

Analogger will accept logs from multiple sources and can have multiple logging destinations. Currently, logging to a file, to STDOUT, or to STDERR is supported. A future revision may support logging to a database destination, as well.

Analogger depends on EventMachine (http://rubyforge.org/projects/eventmachine) to provide the framework for the network communications, though EM is not used for the client library.

like image 45
miku Avatar answered Nov 15 '22 17:11

miku