mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/logger.rb (Logger): added formatter accessor to logger for
dictating the way in which the logger should format the messages it displays. Thanks to Nicholas Seckar (cf. [ruby-talk:153391]) and Daniel Berger. * lib/logger.rb (Logger): added VERSION constant. * lib/logger.rb: removed document for LogDevice. It is an implementation detail and is not a public interface. * test/logger/test_logger.rb: added tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9151 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
9a7b502846
commit
5d0bf56235
3 changed files with 111 additions and 83 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
Tue Sep 13 22:09:40 2005 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
|
||||||
|
|
||||||
|
* lib/logger.rb (Logger): added formatter accessor to logger for
|
||||||
|
dictating the way in which the logger should format the messages it
|
||||||
|
displays. Thanks to Nicholas Seckar (cf. [ruby-talk:153391]) and
|
||||||
|
Daniel Berger.
|
||||||
|
|
||||||
|
* lib/logger.rb (Logger): added VERSION constant.
|
||||||
|
|
||||||
|
* lib/logger.rb: removed document for LogDevice. It is an
|
||||||
|
implementation detail and is not a public interface.
|
||||||
|
|
||||||
|
* test/logger/test_logger.rb: added tests.
|
||||||
|
|
||||||
Tue Sep 13 21:47:17 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Tue Sep 13 21:47:17 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* eval.c (BEGIN_CALLARGS): pop halfly pushed status.
|
* eval.c (BEGIN_CALLARGS): pop halfly pushed status.
|
||||||
|
@ -96,10 +110,10 @@ Sat Sep 10 10:17:03 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
key = pkcs11.load_private_key
|
key = pkcs11.load_private_key
|
||||||
|
|
||||||
* ext/openssl/ossl_engine.c (ossl_engine_ctrl_cmd): new method
|
* ext/openssl/ossl_engine.c (ossl_engine_ctrl_cmd): new method
|
||||||
OpenSSL::Engine#ctrl_cmd. it wraps ENGINE_ctrl_cmd_string.
|
OpenSSL::Engine#ctrl_cmd. it wraps ENGINE_ctrl_cmd_string.
|
||||||
|
|
||||||
* ext/openssl/ossl_engine.c (ossl_engine_get_cmds): new method
|
* ext/openssl/ossl_engine.c (ossl_engine_get_cmds): new method
|
||||||
OpenSSL::Engine#cmds. it returms engine command definitions.
|
OpenSSL::Engine#cmds. it returms engine command definitions.
|
||||||
|
|
||||||
Sat Sep 10 10:09:47 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
Sat Sep 10 10:09:47 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
|
|
||||||
|
|
142
lib/logger.rb
142
lib/logger.rb
|
@ -178,6 +178,7 @@ require 'monitor'
|
||||||
|
|
||||||
|
|
||||||
class Logger
|
class Logger
|
||||||
|
VERSION = "1.2.6"
|
||||||
/: (\S+),v (\S+)/ =~ %q$Id$
|
/: (\S+),v (\S+)/ =~ %q$Id$
|
||||||
ProgName = "#{$1}/#{$2}"
|
ProgName = "#{$1}/#{$2}"
|
||||||
|
|
||||||
|
@ -202,7 +203,20 @@ class Logger
|
||||||
attr_accessor :progname
|
attr_accessor :progname
|
||||||
|
|
||||||
# Logging date-time format (string passed to +strftime+).
|
# Logging date-time format (string passed to +strftime+).
|
||||||
attr_accessor :datetime_format
|
def datetime_format=(datetime_format)
|
||||||
|
@default_formatter.datetime_format = datetime_format
|
||||||
|
end
|
||||||
|
|
||||||
|
def datetime_format
|
||||||
|
@default_formatter.datetime_format
|
||||||
|
end
|
||||||
|
|
||||||
|
# Logging formatter. formatter#call is invoked with 4 arguments; severity,
|
||||||
|
# time, progname and msg for each log. Bear in mind that time is a Time and
|
||||||
|
# msg is an Object that user passed and it could not be a String. It is
|
||||||
|
# expected to return a logdev#write-able Object. Default formatter is used
|
||||||
|
# when no formatter is set.
|
||||||
|
attr_accessor :formatter
|
||||||
|
|
||||||
alias sev_threshold level
|
alias sev_threshold level
|
||||||
alias sev_threshold= level=
|
alias sev_threshold= level=
|
||||||
|
@ -246,16 +260,17 @@ class Logger
|
||||||
#
|
#
|
||||||
# === Description
|
# === Description
|
||||||
#
|
#
|
||||||
# Create an instance. See Logger::LogDevice.new for more information if
|
# Create an instance.
|
||||||
# required.
|
|
||||||
#
|
#
|
||||||
def initialize(logdev, shift_age = 0, shift_size = 1048576)
|
def initialize(logdev, shift_age = 0, shift_size = 1048576)
|
||||||
@progname = nil
|
@progname = nil
|
||||||
@level = DEBUG
|
@level = DEBUG
|
||||||
@datetime_format = nil
|
@default_formatter = Formatter.new
|
||||||
|
@formatter = nil
|
||||||
@logdev = nil
|
@logdev = nil
|
||||||
if logdev
|
if logdev
|
||||||
@logdev = LogDevice.new(logdev, :shift_age => shift_age, :shift_size => shift_size)
|
@logdev = LogDevice.new(logdev, :shift_age => shift_age,
|
||||||
|
:shift_size => shift_size)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -318,13 +333,7 @@ class Logger
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@logdev.write(
|
@logdev.write(
|
||||||
format_message(
|
format_message(format_severity(severity), Time.now, progname, message))
|
||||||
format_severity(severity),
|
|
||||||
format_datetime(Time.now),
|
|
||||||
msg2str(message),
|
|
||||||
progname
|
|
||||||
)
|
|
||||||
)
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
alias log add
|
alias log add
|
||||||
|
@ -427,74 +436,60 @@ private
|
||||||
SEV_LABEL[severity] || 'ANY'
|
SEV_LABEL[severity] || 'ANY'
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_datetime(datetime)
|
def format_message(severity, datetime, progname, msg)
|
||||||
if @datetime_format.nil?
|
(@formatter || @default_formatter).call(severity, datetime, progname, msg)
|
||||||
datetime.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d " % datetime.usec
|
end
|
||||||
else
|
|
||||||
datetime.strftime(@datetime_format)
|
|
||||||
|
class Formatter
|
||||||
|
Format = "%s, [%s#%d] %5s -- %s: %s\n"
|
||||||
|
|
||||||
|
attr_accessor :datetime_format
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@datetime_format = nil
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
Format = "%s, [%s#%d] %5s -- %s: %s\n"
|
def call(severity, time, progname, msg)
|
||||||
def format_message(severity, timestamp, msg, progname)
|
Format % [severity[0..0], format_datetime(time), $$, severity, progname,
|
||||||
Format % [severity[0..0], timestamp, $$, severity, progname, msg]
|
msg2str(msg)]
|
||||||
end
|
end
|
||||||
|
|
||||||
def msg2str(msg)
|
private
|
||||||
case msg
|
|
||||||
when ::String
|
def format_datetime(time)
|
||||||
msg
|
if @datetime_format.nil?
|
||||||
when ::Exception
|
time.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d " % time.usec
|
||||||
"#{ msg.message } (#{ msg.class })\n" << (msg.backtrace || []).join("\n")
|
else
|
||||||
else
|
time.strftime(@datetime_format)
|
||||||
msg.inspect
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def msg2str(msg)
|
||||||
|
case msg
|
||||||
|
when ::String
|
||||||
|
msg
|
||||||
|
when ::Exception
|
||||||
|
"#{ msg.message } (#{ msg.class })\n" <<
|
||||||
|
(msg.backtrace || []).join("\n")
|
||||||
|
else
|
||||||
|
msg.inspect
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# LogDevice -- Logging device.
|
|
||||||
#
|
|
||||||
class LogDevice
|
class LogDevice
|
||||||
attr_reader :dev
|
attr_reader :dev
|
||||||
attr_reader :filename
|
attr_reader :filename
|
||||||
|
|
||||||
#
|
class LogDeviceMutex
|
||||||
# == Synopsis
|
include MonitorMixin
|
||||||
#
|
end
|
||||||
# Logger::LogDevice.new(name, :shift_age => 'daily|weekly|monthly')
|
|
||||||
# Logger::LogDevice.new(name, :shift_age => 10, :shift_size => 1024*1024)
|
|
||||||
#
|
|
||||||
# == Args
|
|
||||||
#
|
|
||||||
# +name+::
|
|
||||||
# A String (representing a filename) or an IO object (actually, anything
|
|
||||||
# that responds to +write+ and +close+). If a filename is given, then
|
|
||||||
# that file is opened for writing (and appending if it already exists),
|
|
||||||
# with +sync+ set to +true+.
|
|
||||||
# +opts+::
|
|
||||||
# Contains optional arguments for rolling ("shifting") the log file.
|
|
||||||
# <tt>:shift_age</tt> is either a description (e.g. 'daily'), or an
|
|
||||||
# integer number of log files to keep. <tt>shift_size</tt> is the maximum
|
|
||||||
# size of the log file, and is only significant is a number is given for
|
|
||||||
# <tt>shift_age</tt>.
|
|
||||||
#
|
|
||||||
# These arguments are only relevant if a filename is provided for the
|
|
||||||
# first argument.
|
|
||||||
#
|
|
||||||
# == Description
|
|
||||||
#
|
|
||||||
# Creates a LogDevice object, which is the target for log messages. Rolling
|
|
||||||
# of log files is supported (only if a filename is given; you can't roll an
|
|
||||||
# IO object). The beginning of each file created by this class is tagged
|
|
||||||
# with a header message.
|
|
||||||
#
|
|
||||||
# This class is unlikely to be used directly; it is a backend for Logger.
|
|
||||||
#
|
|
||||||
def initialize(log = nil, opt = {})
|
def initialize(log = nil, opt = {})
|
||||||
@dev = @filename = @shift_age = @shift_size = nil
|
@dev = @filename = @shift_age = @shift_size = nil
|
||||||
@mutex = Object.new
|
@mutex = LogDeviceMutex.new
|
||||||
@mutex.extend(MonitorMixin)
|
|
||||||
if log.respond_to?(:write) and log.respond_to?(:close)
|
if log.respond_to?(:write) and log.respond_to?(:close)
|
||||||
@dev = log
|
@dev = log
|
||||||
else
|
else
|
||||||
|
@ -506,12 +501,6 @@ private
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
|
||||||
# Log a message. If needed, the log file is rolled and the new file is
|
|
||||||
# prepared. Log device is not locked. Append open does not need to lock
|
|
||||||
# file but on an OS which supports multi I/O, records could possibly be
|
|
||||||
# mixed.
|
|
||||||
#
|
|
||||||
def write(message)
|
def write(message)
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
if @shift_age and @dev.respond_to?(:stat)
|
if @shift_age and @dev.respond_to?(:stat)
|
||||||
|
@ -525,9 +514,6 @@ private
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
|
||||||
# Close the logging device.
|
|
||||||
#
|
|
||||||
def close
|
def close
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
@dev.close
|
@dev.close
|
||||||
|
@ -689,8 +675,8 @@ private
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sets the log device for this application. See the classes Logger and
|
# Sets the log device for this application. See the class Logger for an
|
||||||
# Logger::LogDevice for an explanation of the arguments.
|
# explanation of the arguments.
|
||||||
#
|
#
|
||||||
def set_log(logdev, shift_age = 0, shift_size = 1024000)
|
def set_log(logdev, shift_age = 0, shift_size = 1024000)
|
||||||
@log = Logger.new(logdev, shift_age, shift_size)
|
@log = Logger.new(logdev, shift_age, shift_size)
|
||||||
|
|
|
@ -36,13 +36,17 @@ class TestLogger < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def log(logger, msg_id, *arg, &block)
|
def log(logger, msg_id, *arg, &block)
|
||||||
|
Log.new(log_raw(logger, msg_id, *arg, &block))
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_raw(logger, msg_id, *arg, &block)
|
||||||
logdev = Tempfile.new(File.basename(__FILE__) + '.log')
|
logdev = Tempfile.new(File.basename(__FILE__) + '.log')
|
||||||
logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
|
logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
|
||||||
logger.__send__(msg_id, *arg, &block)
|
logger.__send__(msg_id, *arg, &block)
|
||||||
logdev.open
|
logdev.open
|
||||||
msg = logdev.read
|
msg = logdev.read
|
||||||
logdev.close
|
logdev.close
|
||||||
Log.new(msg)
|
msg
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_level
|
def test_level
|
||||||
|
@ -98,6 +102,32 @@ class TestLogger < Test::Unit::TestCase
|
||||||
assert_match(/^$/, log.datetime)
|
assert_match(/^$/, log.datetime)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_formatter
|
||||||
|
dummy = STDERR
|
||||||
|
logger = Logger.new(dummy)
|
||||||
|
# default
|
||||||
|
log = log(logger, :info, "foo")
|
||||||
|
assert_equal("foo\n", log.msg)
|
||||||
|
# config
|
||||||
|
logger.formatter = proc { |severity, timestamp, progname, msg|
|
||||||
|
"#{severity}:#{msg}\n\n"
|
||||||
|
}
|
||||||
|
line = log_raw(logger, :info, "foo")
|
||||||
|
assert_equal("INFO:foo\n\n", line)
|
||||||
|
# recover
|
||||||
|
logger.formatter = nil
|
||||||
|
log = log(logger, :info, "foo")
|
||||||
|
assert_equal("foo\n", log.msg)
|
||||||
|
# again
|
||||||
|
o = Object.new
|
||||||
|
def o.call(severity, timestamp, progname, msg)
|
||||||
|
"<<#{severity}-#{msg}>>\n"
|
||||||
|
end
|
||||||
|
logger.formatter = o
|
||||||
|
line = log_raw(logger, :info, "foo")
|
||||||
|
assert_equal("<<INFO-foo>>\n", line)
|
||||||
|
end
|
||||||
|
|
||||||
def test_initialize
|
def test_initialize
|
||||||
logger = Logger.new(STDERR)
|
logger = Logger.new(STDERR)
|
||||||
assert_nil(logger.progname)
|
assert_nil(logger.progname)
|
||||||
|
@ -301,7 +331,6 @@ class TestLogDevice < Test::Unit::TestCase
|
||||||
assert(!File.exist?(logfile3))
|
assert(!File.exist?(logfile3))
|
||||||
logger.error("0" * 15)
|
logger.error("0" * 15)
|
||||||
assert(!File.exist?(logfile3))
|
assert(!File.exist?(logfile3))
|
||||||
logger.close
|
|
||||||
File.unlink(logfile)
|
File.unlink(logfile)
|
||||||
File.unlink(logfile0)
|
File.unlink(logfile0)
|
||||||
File.unlink(logfile1)
|
File.unlink(logfile1)
|
||||||
|
@ -337,7 +366,6 @@ class TestLogDevice < Test::Unit::TestCase
|
||||||
assert(!File.exist?(logfile3))
|
assert(!File.exist?(logfile3))
|
||||||
logger.error("0" * 15)
|
logger.error("0" * 15)
|
||||||
assert(!File.exist?(logfile3))
|
assert(!File.exist?(logfile3))
|
||||||
logger.close
|
|
||||||
File.unlink(logfile)
|
File.unlink(logfile)
|
||||||
File.unlink(logfile0)
|
File.unlink(logfile0)
|
||||||
File.unlink(logfile1)
|
File.unlink(logfile1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue