mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/logger.rb: imported upstream version (logger/1.2.7)
* do not raise an exception even if log writing failed. * do not raise ShiftingError if an aged file already exists. (no ShiftingError will be raised from 1.2.7, just warn() instead) * test/logger/test_logger.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@20345 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c1221d04f0
commit
652b6f196a
4 changed files with 220 additions and 38 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
Mon Nov 24 23:53:44 2008 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
||||||
|
|
||||||
|
* lib/logger.rb: imported upstream version (logger/1.2.7)
|
||||||
|
* do not raise an exception even if log writing failed.
|
||||||
|
* do not raise ShiftingError if an aged file already exists.
|
||||||
|
(no ShiftingError will be raised from 1.2.7, just warn() instead)
|
||||||
|
* test/logger/test_logger.rb: ditto.
|
||||||
|
|
||||||
Mon Nov 24 23:47:22 2008 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
Mon Nov 24 23:47:22 2008 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
||||||
|
|
||||||
* time.c: RDoc typo fixed.
|
* time.c: RDoc typo fixed.
|
||||||
|
|
7
NEWS
7
NEWS
|
@ -84,6 +84,13 @@ with all sufficient information, see the ChangeLog file.
|
||||||
|
|
||||||
http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
|
http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
|
||||||
|
|
||||||
|
* logger
|
||||||
|
|
||||||
|
* imported upstream version (logger/1.2.7)
|
||||||
|
* do not raise an exception even if log writing failed.
|
||||||
|
* do not raise ShiftingError if an aged file already exists.
|
||||||
|
(no ShiftingError will be raised from 1.2.7, just warn() instead)
|
||||||
|
|
||||||
== Changes since the 1.8.6 release
|
== Changes since the 1.8.6 release
|
||||||
|
|
||||||
=== Configuration changes
|
=== Configuration changes
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
# logger.rb - simple logging utility
|
# logger.rb - simple logging utility
|
||||||
# Copyright (C) 2000-2003, 2005 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>.
|
# Copyright (C) 2000-2003, 2005, 2008 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||||
|
|
||||||
|
|
||||||
require 'monitor'
|
require 'monitor'
|
||||||
|
|
||||||
|
|
||||||
|
# = logger.rb
|
||||||
|
#
|
||||||
# Simple logging utility.
|
# Simple logging utility.
|
||||||
#
|
#
|
||||||
# Author:: NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
|
# Author:: NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
|
||||||
|
@ -11,6 +15,11 @@ require 'monitor'
|
||||||
# You can redistribute it and/or modify it under the same terms of Ruby's
|
# You can redistribute it and/or modify it under the same terms of Ruby's
|
||||||
# license; either the dual license version in 2003, or any later version.
|
# license; either the dual license version in 2003, or any later version.
|
||||||
# Revision:: $Id$
|
# Revision:: $Id$
|
||||||
|
#
|
||||||
|
# See Logger for documentation.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# == Description
|
# == Description
|
||||||
#
|
#
|
||||||
|
@ -149,8 +158,8 @@ require 'monitor'
|
||||||
#
|
#
|
||||||
# == Format
|
# == Format
|
||||||
#
|
#
|
||||||
# Log messages are rendered in the output stream in a certain format. The
|
# Log messages are rendered in the output stream in a certain format by
|
||||||
# default format and a sample are shown below:
|
# default. The default format and a sample are shown below:
|
||||||
#
|
#
|
||||||
# Log format:
|
# Log format:
|
||||||
# SeverityID, [Date Time mSec #pid] SeverityLabel -- ProgName: message
|
# SeverityID, [Date Time mSec #pid] SeverityLabel -- ProgName: message
|
||||||
|
@ -163,18 +172,22 @@ require 'monitor'
|
||||||
# logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
# logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
||||||
# # e.g. "2004-01-03 00:54:26"
|
# # e.g. "2004-01-03 00:54:26"
|
||||||
#
|
#
|
||||||
# There is currently no supported way to change the overall format, but you may
|
# You may change the overall format with Logger#formatter= method.
|
||||||
# have some luck hacking the Format constant.
|
#
|
||||||
|
# logger.formatter = proc { |severity, datetime, progname, msg|
|
||||||
|
# "#{datetime}: #{msg}\n"
|
||||||
|
# }
|
||||||
|
# # e.g. "Thu Sep 22 08:51:08 GMT+9:00 2005: hello world"
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
class Logger
|
class Logger
|
||||||
VERSION = "1.2.6"
|
VERSION = "1.2.7"
|
||||||
id, name, rev = %w$Id$
|
/: (\S+) (\S+)/ =~ %q$Id$
|
||||||
ProgName = "#{name.chomp(",v")}/#{rev}"
|
ProgName = "#{$1}/#{$2}"
|
||||||
|
|
||||||
class Error < RuntimeError; end
|
class Error < RuntimeError; end
|
||||||
class ShiftingError < Error; end
|
class ShiftingError < Error; end # not used after 1.2.7. just for compat.
|
||||||
|
|
||||||
# Logging severity.
|
# Logging severity.
|
||||||
module Severity
|
module Severity
|
||||||
|
@ -494,20 +507,27 @@ private
|
||||||
|
|
||||||
def write(message)
|
def write(message)
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
if @shift_age and @dev.respond_to?(:stat)
|
begin
|
||||||
begin
|
if @shift_age and @dev.respond_to?(:stat)
|
||||||
check_shift_log
|
begin
|
||||||
rescue
|
check_shift_log
|
||||||
raise Logger::ShiftingError.new("Shifting failed. #{$!}")
|
rescue
|
||||||
|
warn("log shifting failed. #{$!}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
begin
|
||||||
|
@dev.write(message)
|
||||||
|
rescue
|
||||||
|
warn("log writing failed. #{$!}")
|
||||||
|
end
|
||||||
|
rescue Exception => ignored
|
||||||
end
|
end
|
||||||
@dev.write(message)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def close
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
@dev.close
|
@dev.close rescue nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -530,8 +550,8 @@ private
|
||||||
|
|
||||||
def add_log_header(file)
|
def add_log_header(file)
|
||||||
file.write(
|
file.write(
|
||||||
"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
|
"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
SiD = 24 * 60 * 60
|
SiD = 24 * 60 * 60
|
||||||
|
@ -544,8 +564,9 @@ private
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
now = Time.now
|
now = Time.now
|
||||||
if @dev.stat.mtime <= previous_period_end(now)
|
period_end = previous_period_end(now)
|
||||||
shift_log_period(now)
|
if @dev.stat.mtime <= period_end
|
||||||
|
shift_log_period(period_end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -556,19 +577,26 @@ private
|
||||||
File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
|
File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@dev.close
|
@dev.close rescue nil
|
||||||
File.rename("#{@filename}", "#{@filename}.0")
|
File.rename("#{@filename}", "#{@filename}.0")
|
||||||
@dev = create_logfile(@filename)
|
@dev = create_logfile(@filename)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
def shift_log_period(now)
|
def shift_log_period(period_end)
|
||||||
postfix = previous_period_end(now).strftime("%Y%m%d") # YYYYMMDD
|
postfix = period_end.strftime("%Y%m%d") # YYYYMMDD
|
||||||
age_file = "#{@filename}.#{postfix}"
|
age_file = "#{@filename}.#{postfix}"
|
||||||
if FileTest.exist?(age_file)
|
if FileTest.exist?(age_file)
|
||||||
raise RuntimeError.new("'#{ age_file }' already exists.")
|
# try to avoid filename crash caused by Timestamp change.
|
||||||
|
idx = 0
|
||||||
|
# .99 can be overriden; avoid too much file search with 'loop do'
|
||||||
|
while idx < 100
|
||||||
|
idx += 1
|
||||||
|
age_file = "#{@filename}.#{postfix}.#{idx}"
|
||||||
|
break unless FileTest.exist?(age_file)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@dev.close
|
@dev.close rescue nil
|
||||||
File.rename("#{@filename}", age_file)
|
File.rename("#{@filename}", age_file)
|
||||||
@dev = create_logfile(@filename)
|
@dev = create_logfile(@filename)
|
||||||
return true
|
return true
|
||||||
|
@ -625,8 +653,8 @@ private
|
||||||
class Application
|
class Application
|
||||||
include Logger::Severity
|
include Logger::Severity
|
||||||
|
|
||||||
|
# Name of the application given at initialize.
|
||||||
attr_reader :appname
|
attr_reader :appname
|
||||||
attr_reader :logdev
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# == Synopsis
|
# == Synopsis
|
||||||
|
@ -665,9 +693,23 @@ private
|
||||||
status
|
status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Logger for this application. See the class Logger for an explanation.
|
||||||
|
def logger
|
||||||
|
@log
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sets the log device for this application. See the class Logger for an
|
# Sets the logger for this application. See the class Logger for an explanation.
|
||||||
# explanation of the arguments.
|
#
|
||||||
|
def logger=(logger)
|
||||||
|
@log = logger
|
||||||
|
@log.progname = @appname
|
||||||
|
@log.level = @level
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Sets the log device for this application. See <tt>Logger.new</tt> for an 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)
|
||||||
|
@ -697,6 +739,7 @@ private
|
||||||
private
|
private
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
# TODO: should be an NotImplementedError
|
||||||
raise RuntimeError.new('Method run must be defined in the derived class.')
|
raise RuntimeError.new('Method run must be defined in the derived class.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,10 +21,13 @@ class TestLogger < Test::Unit::TestCase
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@logger = Logger.new(nil)
|
@logger = Logger.new(nil)
|
||||||
|
@filename = __FILE__ + ".#{$$}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_const_progname
|
def teardown
|
||||||
assert %r!\Alogger\.rb/\S+\z! === Logger::ProgName
|
unless $DEBUG
|
||||||
|
File.unlink(@filename) if File.exist?(@filename)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Log
|
class Log
|
||||||
|
@ -262,8 +265,31 @@ class TestLogger < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
class TestLogDevice < Test::Unit::TestCase
|
class TestLogDevice < Test::Unit::TestCase
|
||||||
def d(log)
|
class LogExcnRaiser
|
||||||
Logger::LogDevice.new(log)
|
def write(*arg)
|
||||||
|
raise 'disk is full'
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
end
|
||||||
|
|
||||||
|
def stat
|
||||||
|
Object.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@filename = __FILE__ + ".#{$$}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
unless $DEBUG
|
||||||
|
File.unlink(@filename) if File.exist?(@filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def d(log, opt = {})
|
||||||
|
Logger::LogDevice.new(log, opt)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_initialize
|
def test_initialize
|
||||||
|
@ -274,16 +300,21 @@ class TestLogDevice < Test::Unit::TestCase
|
||||||
d(nil)
|
d(nil)
|
||||||
end
|
end
|
||||||
#
|
#
|
||||||
filename = __FILE__ + ".#{$$}"
|
logdev = d(@filename)
|
||||||
begin
|
begin
|
||||||
logdev = d(filename)
|
assert(File.exist?(@filename))
|
||||||
assert(File.exist?(filename))
|
|
||||||
assert(logdev.dev.sync)
|
assert(logdev.dev.sync)
|
||||||
assert_equal(filename, logdev.filename)
|
assert_equal(@filename, logdev.filename)
|
||||||
|
logdev.write('hello')
|
||||||
ensure
|
ensure
|
||||||
logdev.close
|
logdev.close
|
||||||
File.unlink(filename)
|
|
||||||
end
|
end
|
||||||
|
# create logfile whitch is already exist.
|
||||||
|
logdev = d(@filename)
|
||||||
|
logdev.write('world')
|
||||||
|
logfile = File.read(@filename)
|
||||||
|
assert_equal(2, logfile.split(/\n/).size)
|
||||||
|
assert_match(/^helloworld$/, logfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_write
|
def test_write
|
||||||
|
@ -295,6 +326,15 @@ class TestLogDevice < Test::Unit::TestCase
|
||||||
msg = r.read
|
msg = r.read
|
||||||
r.close
|
r.close
|
||||||
assert_equal("msg2\n\n", msg)
|
assert_equal("msg2\n\n", msg)
|
||||||
|
#
|
||||||
|
logdev = d(LogExcnRaiser.new)
|
||||||
|
begin
|
||||||
|
assert_nothing_raised do
|
||||||
|
logdev.write('hello')
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
logdev.close
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_close
|
def test_close
|
||||||
|
@ -377,4 +417,88 @@ class TestLogDevice < Test::Unit::TestCase
|
||||||
File.unlink(logfile1)
|
File.unlink(logfile1)
|
||||||
File.unlink(logfile2)
|
File.unlink(logfile2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_shifting_age_variants
|
||||||
|
logger = Logger.new(@filename, 'daily')
|
||||||
|
logger.info('daily')
|
||||||
|
logger.close
|
||||||
|
logger = Logger.new(@filename, 'weekly')
|
||||||
|
logger.info('weekly')
|
||||||
|
logger.close
|
||||||
|
logger = Logger.new(@filename, 'monthly')
|
||||||
|
logger.info('monthly')
|
||||||
|
logger.close
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_shifting_age
|
||||||
|
# shift_age other than 'daily', 'weekly', and 'monthly' means 'everytime'
|
||||||
|
yyyymmdd = Time.now.strftime("%Y%m%d")
|
||||||
|
filename1 = @filename + ".#{yyyymmdd}"
|
||||||
|
filename2 = @filename + ".#{yyyymmdd}.1"
|
||||||
|
filename3 = @filename + ".#{yyyymmdd}.2"
|
||||||
|
begin
|
||||||
|
logger = Logger.new(@filename, 'now')
|
||||||
|
assert(File.exist?(@filename))
|
||||||
|
assert(!File.exist?(filename1))
|
||||||
|
assert(!File.exist?(filename2))
|
||||||
|
assert(!File.exist?(filename3))
|
||||||
|
logger.info("0" * 15)
|
||||||
|
assert(File.exist?(@filename))
|
||||||
|
assert(File.exist?(filename1))
|
||||||
|
assert(!File.exist?(filename2))
|
||||||
|
assert(!File.exist?(filename3))
|
||||||
|
logger.warn("0" * 15)
|
||||||
|
assert(File.exist?(@filename))
|
||||||
|
assert(File.exist?(filename1))
|
||||||
|
assert(File.exist?(filename2))
|
||||||
|
assert(!File.exist?(filename3))
|
||||||
|
logger.error("0" * 15)
|
||||||
|
assert(File.exist?(@filename))
|
||||||
|
assert(File.exist?(filename1))
|
||||||
|
assert(File.exist?(filename2))
|
||||||
|
assert(File.exist?(filename3))
|
||||||
|
ensure
|
||||||
|
[filename1, filename2, filename3].each do |filename|
|
||||||
|
File.unlink(filename) if File.exist?(filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoggerApplication < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
@app = Logger::Application.new('appname')
|
||||||
|
@filename = __FILE__ + ".#{$$}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
unless $DEBUG
|
||||||
|
File.unlink(@filename) if File.exist?(@filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_initialize
|
||||||
|
app = Logger::Application.new('appname')
|
||||||
|
assert_equal('appname', app.appname)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_start
|
||||||
|
@app.set_log(@filename)
|
||||||
|
@app.level = Logger::UNKNOWN
|
||||||
|
@app.start # logs FATAL log
|
||||||
|
assert_equal(1, File.read(@filename).split(/\n/).size)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_logger
|
||||||
|
@app.level = Logger::WARN
|
||||||
|
@app.set_log(@filename)
|
||||||
|
assert_equal(Logger::WARN, @app.logger.level)
|
||||||
|
@app.logger = logger = Logger.new(STDOUT)
|
||||||
|
assert_equal(logger, @app.logger)
|
||||||
|
assert_equal(Logger::WARN, @app.logger.level)
|
||||||
|
@app.log = @filename
|
||||||
|
assert(logger != @app.logger)
|
||||||
|
assert_equal(Logger::WARN, @app.logger.level)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue