lib/semantic_logger/logger.rb in semantic_logger-0.11.1 vs lib/semantic_logger/logger.rb in semantic_logger-0.11.2
- old
+ new
@@ -29,20 +29,14 @@
# # This will be logged to both the Ruby Logger and MongoDB
# logger.debug("Login time", :user => 'Mary', :duration => 230, :ip_address=>'192.168.0.1')
#
module SemanticLogger
class Logger < Base
- include SyncAttr
-
- # Add or remove logging appenders to the appenders Array
+ # Add or remove logging appenders to the thread-safe appenders Array
# Appenders will be written to in the order that they appear in this list
- sync_cattr_reader :appenders do
- # The logging thread is only started when an appender is added
- @@appender_thread = Thread.new { appender_thread }
-
- # Thread safe appenders array
- ThreadSafe::Array.new
+ def self.appenders
+ @@appenders
end
# Returns a Logger instance
#
# Return the logger for a specific class, supports class specific log levels
@@ -82,13 +76,13 @@
end
# Flush all queued log entries disk, database, etc.
# All queued log messages are written and then each appender is flushed in turn
def self.flush
- return false unless started? && @@appender_thread && @@appender_thread.alive?
+ return false unless appender_thread_active?
- logger.debug "SemanticLogger::Logger Flushing appenders with #{queue_size} log messages on the queue"
+ logger.debug "Flushing appenders with #{queue_size} log messages on the queue"
reply_queue = Queue.new
queue << { :command => :flush, :reply_queue => reply_queue }
reply_queue.pop
end
@@ -115,101 +109,123 @@
def self.time_threshold_s=(time_threshold_s)
@@lag_threshold_s = time_threshold_s
end
- # Returns whether the logging thread has been started
- def self.started?
- defined? :@@appenders
+ # Allow the internal logger to be overridden from its default to STDERR
+ # Can be replaced with another Ruby logger or Rails logger, but never to
+ # SemanticLogger::Logger itself since it is for reporting problems
+ # while trying to log to the various appenders
+ def self.logger=(logger)
+ @@logger = logger
end
+
############################################################################
protected
+ @@appenders = ThreadSafe::Array.new
@@appender_thread = nil
- @@queue = Queue.new
+ @@queue = Queue.new
# Queue to hold messages that need to be logged to the various appenders
def self.queue
@@queue
end
# Place log request on the queue for the Appender thread to write to each
# appender in the order that they were registered
def log(log)
- self.class.queue << log if self.class.started?
+ self.class.queue << log if @@appender_thread
end
# Internal logger for SemanticLogger
# For example when an appender is not working etc..
# By default logs to STDERR
- # Can be replaced with another Ruby logger or Rails logger, but never to
- # SemanticLogger::Logger itself
- #
- # Warning: Do not use this logger directly it is intended for internal logging
- # within Semantic Logger itself
- sync_cattr_accessor :logger do
- SemanticLogger::Appender::File.new(STDERR, :warn)
+ def self.logger
+ @@logger ||= begin
+ l = SemanticLogger::Appender::File.new(STDERR, :warn)
+ l.name = self.class.name
+ l
+ end
end
+ # Start the appender thread
+ def self.start_appender_thread
+ return false if appender_thread_active?
+ @@appender_thread = Thread.new { appender_thread }
+ raise "Failed to start Appender Thread" unless @@appender_thread
+ true
+ end
+
+ # Returns true if the appender_thread is active
+ def self.appender_thread_active?
+ @@appender_thread && @@appender_thread.alive?
+ end
+
# Separate appender thread responsible for reading log messages and
# calling the appenders in it's thread
def self.appender_thread
# This thread is designed to never go down unless the main thread terminates
# Before terminating at_exit is used to flush all the appenders
#
# Should any appender fail to log or flush, the exception is logged and
# other appenders will still be called
- logger.info "SemanticLogger::Logger V#{VERSION} Appender thread active"
+ logger.debug "V#{VERSION} Appender thread active"
begin
count = 0
while message = queue.pop
if message.is_a? Log
appenders.each do |appender|
begin
appender.log(message)
rescue Exception => exc
- logger.error "SemanticLogger::Logger Appender thread: Failed to log to appender: #{appender.inspect}", exc
+ logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
end
end
count += 1
# Check every few log messages whether this appender thread is falling behind
if count > lag_check_interval
if (diff = Time.now - message.time) > lag_threshold_s
- logger.warn "SemanticLogger::Logger Appender thread has fallen behind by #{diff} seconds with #{queue_size} messages queued up. Consider reducing the log level or changing the appenders"
+ logger.warn "Appender thread has fallen behind by #{diff} seconds with #{queue_size} messages queued up. Consider reducing the log level or changing the appenders"
end
count = 0
end
else
case message[:command]
when :flush
appenders.each do |appender|
begin
- logger.info "SemanticLogger::Logger Appender thread: Flushing appender: #{appender.name}"
+ logger.info "Appender thread: Flushing appender: #{appender.name}"
appender.flush
rescue Exception => exc
- logger.error "SemanticLogger::Logger Appender thread: Failed to flush appender: #{appender.inspect}", exc
+ logger.error "Appender thread: Failed to flush appender: #{appender.inspect}", exc
end
end
message[:reply_queue] << true if message[:reply_queue]
- logger.info "SemanticLogger::Logger Appender thread: All appenders flushed"
+ logger.info "Appender thread: All appenders flushed"
else
- logger.warn "SemanticLogger::Logger Appender thread: Ignoring unknown command: #{message[:command]}"
+ logger.warn "Appender thread: Ignoring unknown command: #{message[:command]}"
end
end
end
rescue Exception => exception
- logger.error "SemanticLogger::Logger Appender thread restarting due to exception", exception
+ logger.error "Appender thread restarting due to exception", exception
retry
ensure
- logger.debug "SemanticLogger::Logger Appender thread has stopped"
+ logger.debug "Appender thread has stopped"
+ @@appender_thread = nil
end
end
+ # Flush all appenders at exit, waiting for outstanding messages on the queue
+ # to be written first
+ at_exit do
+ flush
+ end
+
+ # Start appender thread on load to workaround intermittent startup issues
+ # with JRuby 1.8.6 under Trinidad in 1.9 mode
+ start_appender_thread
end
end
-
-at_exit do
- SemanticLogger::Logger.flush
-end
-