Skip to content
Browse files

Import SyslogLogger from rails_analyzer_tools from Robot Co-op

repository.

[git-p4: depot-paths = "//src/SyslogLogger/dev/": change = 3136]
  • Loading branch information...
0 parents commit 185070d11e75d3d4ae04d687db72cba349df2f76 @drbrain drbrain committed Apr 21, 2007
Showing with 662 additions and 0 deletions.
  1. +4 −0 History.txt
  2. +7 −0 Manifest.txt
  3. +17 −0 README.txt
  4. +16 −0 Rakefile
  5. +1 −0 lib/analyzer_tools/syslog_logger.rb
  6. +174 −0 lib/syslog_logger.rb
  7. +443 −0 test/test_syslog_logger.rb
4 History.txt
@@ -0,0 +1,4 @@
+== 1.4.0 / 2007-04-21
+
+* Split from rails_analyzer_tools
+
7 Manifest.txt
@@ -0,0 +1,7 @@
+History.txt
+Manifest.txt
+README.txt
+Rakefile
+lib/analyzer_tools/syslog_logger.rb
+lib/syslog_logger.rb
+test/test_syslog_logger.rb
17 README.txt
@@ -0,0 +1,17 @@
+= SyslogLogger
+
+SyslogLogger is a Logger replacement that logs to syslog. It is almost
+drop-in with a few caveats.
+
+http://seattlerb.rubyforge.org/SyslogLogger
+
+http://rubyforge.org/projects/seattlerb
+
+== About
+
+See SyslogLogger
+
+== Install
+
+ sudo gem install SyslogLogger
+
16 Rakefile
@@ -0,0 +1,16 @@
+# -*- ruby -*-
+
+require 'hoe'
+require './lib/syslog_logger.rb'
+
+Hoe.new('SyslogLogger', SyslogLogger::VERSION) do |p|
+ p.rubyforge_name = 'seattlerb'
+ p.author = 'Eric Hodel'
+ p.email = 'drbrain@segment7.net'
+ p.summary = p.paragraphs_of('README.txt', 1).first
+ p.description = p.summary
+ p.url = p.paragraphs_of('README.txt', 2).first
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
+end
+
+# vim: syntax=Ruby
1 lib/analyzer_tools/syslog_logger.rb
@@ -0,0 +1 @@
+require 'syslog_logger' # for compatibility
174 lib/syslog_logger.rb
@@ -0,0 +1,174 @@
+require 'syslog'
+require 'logger'
+
+##
+# SyslogLogger is a Logger work-alike that logs via syslog instead of to a
+# file. You can add SyslogLogger to your Rails production environment to
+# aggregate logs between multiple machines.
+#
+# By default, SyslogLogger uses the program name 'rails', but this can be
+# changed via the first argument to SyslogLogger.new.
+#
+# NOTE! You can only set the SyslogLogger program name when you initialize
+# SyslogLogger for the first time. This is a limitation of the way
+# SyslogLogger uses syslog (and in some ways, a the way syslog(3) works).
+# Attempts to change SyslogLogger's program name after the first
+# initialization will be ignored.
+#
+# = Sample usage with Rails
+#
+# == config/environment/production.rb
+#
+# Add the following lines:
+#
+# require 'production_log/syslog_logger'
+# RAILS_DEFAULT_LOGGER = SyslogLogger.new
+#
+# == config/environment.rb
+#
+# In 0.10.0, change this line:
+#
+# RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
+#
+# to:
+#
+# RAILS_DEFAULT_LOGGER ||= Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
+#
+# Other versions of Rails should have a similar change.
+#
+# == /etc/syslog.conf
+#
+# Add the following lines:
+#
+# !rails
+# *.* /var/log/production.log
+#
+# Then touch /var/log/production.log and signal syslogd with a HUP
+# (killall -HUP syslogd, on FreeBSD).
+#
+# == /etc/newsyslog.conf
+#
+# Add the following line:
+#
+# /var/log/production.log 640 7 * @T00 Z
+#
+# This creates a log file that is rotated every day at midnight, gzip'd, then
+# kept for 7 days. Consult newsyslog.conf(5) for more details.
+#
+# Now restart your Rails app. Your production logs should now be showing up
+# in /var/log/production.log. If you have mulitple machines, you can log them
+# all to a central machine with remote syslog logging for analysis. Consult
+# your syslogd(8) manpage for further details.
+
+class SyslogLogger
+
+ ##
+ # The version of SyslogLogger you are using.
+
+ VERSION = '1.4.0'
+
+ ##
+ # Maps Logger warning types to syslog(3) warning types.
+
+ LOGGER_MAP = {
+ :unknown => :alert,
+ :fatal => :err,
+ :error => :warning,
+ :warn => :notice,
+ :info => :info,
+ :debug => :debug,
+ }
+
+ ##
+ # Maps Logger log levels to their values so we can silence.
+
+ LOGGER_LEVEL_MAP = {}
+
+ LOGGER_MAP.each_key do |key|
+ LOGGER_LEVEL_MAP[key] = Logger.const_get key.to_s.upcase
+ end
+
+ ##
+ # Maps Logger log level values to syslog log levels.
+
+ LEVEL_LOGGER_MAP = {}
+
+ LOGGER_LEVEL_MAP.invert.each do |level, severity|
+ LEVEL_LOGGER_MAP[level] = LOGGER_MAP[severity]
+ end
+
+ ##
+ # Builds a logging method for level +meth+.
+
+ def self.log_method(meth)
+ eval <<-EOM, nil, __FILE__, __LINE__ + 1
+ def #{meth}(message = nil)
+ return true if #{LOGGER_LEVEL_MAP[meth]} < @level
+ SYSLOG.#{LOGGER_MAP[meth]} clean(message || yield)
+ return true
+ end
+ EOM
+ end
+
+ LOGGER_MAP.each_key do |level|
+ log_method level
+ end
+
+ ##
+ # Log level for Logger compatibility.
+
+ attr_accessor :level
+
+ ##
+ # Fills in variables for Logger compatibility. If this is the first
+ # instance of SyslogLogger, +program_name+ may be set to change the logged
+ # program name.
+ #
+ # Due to the way syslog works, only one program name may be chosen.
+
+ def initialize(program_name = 'rails')
+ @level = Logger::DEBUG
+
+ return if defined? SYSLOG
+ self.class.const_set :SYSLOG, Syslog.open(program_name)
+ end
+
+ ##
+ # Almost duplicates Logger#add. +progname+ is ignored.
+
+ def add(severity, message = nil, progname = nil, &block)
+ severity ||= Logger::UNKNOWN
+ return true if severity < @level
+ message = clean(message || block.call)
+ SYSLOG.send LEVEL_LOGGER_MAP[severity], clean(message)
+ return true
+ end
+
+ ##
+ # Allows messages of a particular log level to be ignored temporarily.
+ #
+ # Can you say "Broken Windows"?
+
+ def silence(temporary_level = Logger::ERROR)
+ old_logger_level = @level
+ @level = temporary_level
+ yield
+ ensure
+ @level = old_logger_level
+ end
+
+ private
+
+ ##
+ # Clean up messages so they're nice and pretty.
+
+ def clean(message)
+ message = message.to_s.dup
+ message.strip!
+ message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf)
+ message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes
+ return message
+ end
+
+end
+
443 test/test_syslog_logger.rb
@@ -0,0 +1,443 @@
+require 'test/unit'
+require 'tempfile'
+require 'syslog_logger'
+
+module MockSyslog; end
+
+class << MockSyslog
+
+ @line = nil
+
+ SyslogLogger::LOGGER_MAP.values.uniq.each do |level|
+ eval <<-EOM
+ def #{level}(message)
+ @line = "#{level.to_s.upcase} - \#{message}"
+ end
+ EOM
+ end
+
+ attr_reader :line
+ attr_reader :program_name
+
+ def open(program_name)
+ @program_name = program_name
+ end
+
+ def reset
+ @line = ''
+ end
+
+end
+
+SyslogLogger.const_set :SYSLOG, MockSyslog
+
+class TestLogger < Test::Unit::TestCase
+
+ LEVEL_LABEL_MAP = {
+ Logger::DEBUG => 'DEBUG',
+ Logger::INFO => 'INFO',
+ Logger::WARN => 'WARN',
+ Logger::ERROR => 'ERROR',
+ Logger::FATAL => 'FATAL',
+ Logger::UNKNOWN => 'ANY',
+ }
+
+ def setup
+ @logger = Logger.new(nil)
+ end
+
+ class Log
+ attr_reader :line, :label, :datetime, :pid, :severity, :progname, :msg
+ def initialize(line)
+ @line = line
+ /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ @line
+ @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
+ end
+ end
+
+ def log_add(severity, msg, progname = nil, &block)
+ log(:add, severity, msg, progname, &block)
+ end
+
+ def log(msg_id, *arg, &block)
+ Log.new(log_raw(msg_id, *arg, &block))
+ end
+
+ def log_raw(msg_id, *arg, &block)
+ logdev = Tempfile.new(File.basename(__FILE__) + '.log')
+ @logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
+ assert_equal true, @logger.__send__(msg_id, *arg, &block)
+ logdev.open
+ msg = logdev.read
+ logdev.close
+ msg
+ end
+
+ def test_initialize
+ assert_equal Logger::DEBUG, @logger.level
+ end
+
+ def test_add
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
+ end
+
+ def test_add_level_unknown
+ @logger.level = Logger::UNKNOWN
+
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal '', msg.line
+ end
+
+ def test_add_level_fatal
+ @logger.level = Logger::FATAL
+
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal '', msg.line
+ end
+
+ def test_add_level_error
+ @logger.level = Logger::ERROR
+
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal '', msg.line
+ end
+
+ def test_add_level_warn
+ @logger.level = Logger::WARN
+
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal '', msg.line
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal '', msg.line
+ end
+
+ def test_add_level_info
+ @logger.level = Logger::INFO
+
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal '', msg.line
+ end
+
+ def test_add_level_debug
+ @logger.level = Logger::DEBUG
+
+ msg = log_add nil, 'unknown level message' # nil == unknown
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ msg = log_add Logger::FATAL, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ msg = log_add Logger::ERROR, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ msg = log_add Logger::WARN, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ msg = log_add Logger::INFO, 'info level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
+
+ msg = log_add Logger::DEBUG, 'debug level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
+ end
+
+ def test_unknown
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ @logger.level = Logger::UNKNOWN
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ @logger.level = Logger::FATAL
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ @logger.level = Logger::ERROR
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ @logger.level = Logger::WARN
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ @logger.level = Logger::INFO
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+
+ @logger.level = Logger::DEBUG
+ msg = log :unknown, 'unknown level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
+ end
+
+ def test_fatal
+ msg = log :fatal, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ @logger.level = Logger::UNKNOWN
+ msg = log :fatal, 'fatal level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::FATAL
+ msg = log :fatal, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ @logger.level = Logger::ERROR
+ msg = log :fatal, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ @logger.level = Logger::WARN
+ msg = log :fatal, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ @logger.level = Logger::INFO
+ msg = log :fatal, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+
+ @logger.level = Logger::DEBUG
+ msg = log :fatal, 'fatal level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
+ end
+
+ def test_error
+ msg = log :error, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ @logger.level = Logger::UNKNOWN
+ msg = log :error, 'error level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::FATAL
+ msg = log :error, 'error level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::ERROR
+ msg = log :error, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ @logger.level = Logger::WARN
+ msg = log :error, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ @logger.level = Logger::INFO
+ msg = log :error, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+
+ @logger.level = Logger::DEBUG
+ msg = log :error, 'error level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
+ end
+
+ def test_warn
+ msg = log :warn, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ @logger.level = Logger::UNKNOWN
+ msg = log :warn, 'warn level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::FATAL
+ msg = log :warn, 'warn level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::ERROR
+ msg = log :warn, 'warn level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::WARN
+ msg = log :warn, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ @logger.level = Logger::INFO
+ msg = log :warn, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+
+ @logger.level = Logger::DEBUG
+ msg = log :warn, 'warn level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
+ end
+
+ def test_info
+ msg = log :info, 'info level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
+
+ @logger.level = Logger::UNKNOWN
+ msg = log :info, 'info level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::FATAL
+ msg = log :info, 'info level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::ERROR
+ msg = log :info, 'info level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::WARN
+ msg = log :info, 'info level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::INFO
+ msg = log :info, 'info level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
+
+ @logger.level = Logger::DEBUG
+ msg = log :info, 'info level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
+ end
+
+ def test_debug
+ msg = log :debug, 'debug level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
+
+ @logger.level = Logger::UNKNOWN
+ msg = log :debug, 'debug level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::FATAL
+ msg = log :debug, 'debug level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::ERROR
+ msg = log :debug, 'debug level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::WARN
+ msg = log :debug, 'debug level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::INFO
+ msg = log :debug, 'debug level message'
+ assert_equal '', msg.line
+
+ @logger.level = Logger::DEBUG
+ msg = log :debug, 'debug level message'
+ assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
+ end
+
+end
+
+class TestSyslogLogger < TestLogger
+
+ def setup
+ super
+ @logger = SyslogLogger.new
+ end
+
+ class Log
+ attr_reader :line, :label, :datetime, :pid, :severity, :progname, :msg
+ def initialize(line)
+ @line = line
+ return unless /\A(\w+) - (.*)\Z/ =~ @line
+ severity, @msg = $1, $2
+ severity = SyslogLogger::LOGGER_MAP.invert[severity.downcase.intern]
+ @severity = severity.to_s.upcase
+ @severity = 'ANY' if @severity == 'UNKNOWN'
+ end
+ end
+
+ def log_add(severity, msg, progname = nil, &block)
+ log(:add, severity, msg, progname, &block)
+ end
+
+ def log(msg_id, *arg, &block)
+ Log.new(log_raw(msg_id, *arg, &block))
+ end
+
+ def log_raw(msg_id, *arg, &block)
+ assert_equal true, @logger.__send__(msg_id, *arg, &block)
+ msg = MockSyslog.line
+ MockSyslog.reset
+ return msg
+ end
+
+end
+

0 comments on commit 185070d

Please sign in to comment.
Something went wrong with that request. Please try again.