Create a gist now

Instantly share code, notes, and snippets.

a really threadsafe! (buffered) logger
require 'thread'
# ActiveSupport::BufferedLogger is not completely thread-safe !
# well it is if You disable the silencer :
#
# ActiveSupport::BufferedLogger.silencer = false
#
# if You'd like to use `logger.silence { }` it might permanently
# change the level if 2 threads perform silencing at the same time
class ThreadSafeLogger < ActiveSupport::BufferedLogger
def initialize(log, level = DEBUG)
super
@level = { nil => level }
end
def silence(temporary_level = ERROR)
if silencer
begin
@level[Thread.current] = temporary_level
yield self
ensure
@level.delete Thread.current
end
else
yield self
end
end
def level
@level[Thread.current] || @level[nil]
end
def level=(level)
@level[nil] = level
end
# now override where ActiveSupport::BufferedLogger uses @level :
def add(severity, message = nil, progname = nil, &block)
return if level > severity
message = (message || (block && block.call) || progname).to_s
# If a newline is necessary then create a new message ending with a newline.
# Ensures that the original message is not mutated.
message = "#{message}\n" unless message[-1] == ?\n
buffer << message
auto_flush
message
end
for severity in Severity.constants
class_eval <<-EOT, __FILE__, __LINE__ + 1
def #{severity.downcase}? # def debug?
#{severity} >= level # DEBUG >= level
end # end
EOT
end
end
@slawosz
slawosz commented Apr 17, 2013

Should not

@thread_hash_level_key ||= :"ThreadSafeLogger##{object_id}@level"

be

@thread_hash_level_key ||= :"ThreadSafeLogger##{object_id}#{@level}"

?

@slawosz
slawosz commented Apr 18, 2013

Ok, my mistake, it wont work.

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