ruby-changes:8809
From: nahi <ko1@a...>
Date: Mon, 24 Nov 2008 23:55:31 +0900 (JST)
Subject: [ruby-changes:8809] Ruby:r20345 (ruby_1_8): * lib/logger.rb: imported upstream version (logger/1.2.7)
nahi 2008-11-24 23:55:19 +0900 (Mon, 24 Nov 2008) New Revision: 20345 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=20345 Log: * 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. Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/NEWS branches/ruby_1_8/lib/logger.rb branches/ruby_1_8/test/logger/test_logger.rb Index: ruby_1_8/NEWS =================================================================== --- ruby_1_8/NEWS (revision 20344) +++ ruby_1_8/NEWS (revision 20345) @@ -84,6 +84,13 @@ 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 === Configuration changes Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 20344) +++ ruby_1_8/ChangeLog (revision 20345) @@ -1,3 +1,11 @@ +Mon Nov 24 23:53:44 2008 NAKAMURA, Hiroshi <nahi@r...> + + * 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@r...> * time.c: RDoc typo fixed. Index: ruby_1_8/lib/logger.rb =================================================================== --- ruby_1_8/lib/logger.rb (revision 20344) +++ ruby_1_8/lib/logger.rb (revision 20345) @@ -1,8 +1,12 @@ # logger.rb - simple logging utility -# Copyright (C) 2000-2003, 2005 NAKAMURA, Hiroshi <nakahiro@s...>. +# Copyright (C) 2000-2003, 2005, 2008 NAKAMURA, Hiroshi <nahi@r...>. + require 'monitor' + +# = logger.rb +# # Simple logging utility. # # Author:: NAKAMURA, Hiroshi <nakahiro@s...> @@ -12,6 +16,11 @@ # license; either the dual license version in 2003, or any later version. # Revision:: $Id$ # +# See Logger for documentation. +# + + +# # == Description # # The Logger class provides a simple but sophisticated logging utility that @@ -143,14 +152,14 @@ # 2. Log4r (somewhat) compatible interface. # # logger.level = Logger::INFO -# +# # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN # # # == Format # -# Log messages are rendered in the output stream in a certain format. The -# default format and a sample are shown below: +# Log messages are rendered in the output stream in a certain format by +# default. The default format and a sample are shown below: # # Log format: # SeverityID, [Date Time mSec #pid] SeverityLabel -- ProgName: message @@ -163,18 +172,22 @@ # logger.datetime_format = "%Y-%m-%d %H:%M:%S" # # e.g. "2004-01-03 00:54:26" # -# There is currently no supported way to change the overall format, but you may -# have some luck hacking the Format constant. +# You may change the overall format with Logger#formatter= method. # +# 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 - VERSION = "1.2.6" - id, name, rev = %w$Id$ - ProgName = "#{name.chomp(",v")}/#{rev}" + VERSION = "1.2.7" + /: (\S+) (\S+)/ =~ %q$Id$ + ProgName = "#{$1}/#{$2}" class Error < RuntimeError; end - class ShiftingError < Error; end + class ShiftingError < Error; end # not used after 1.2.7. just for compat. # Logging severity. module Severity @@ -494,20 +507,27 @@ def write(message) @mutex.synchronize do - if @shift_age and @dev.respond_to?(:stat) + begin + if @shift_age and @dev.respond_to?(:stat) + begin + check_shift_log + rescue + warn("log shifting failed. #{$!}") + end + end begin - check_shift_log + @dev.write(message) rescue - raise Logger::ShiftingError.new("Shifting failed. #{$!}") + warn("log writing failed. #{$!}") end + rescue Exception => ignored end - @dev.write(message) end end def close @mutex.synchronize do - @dev.close + @dev.close rescue nil end end @@ -530,8 +550,8 @@ def add_log_header(file) 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 SiD = 24 * 60 * 60 @@ -544,8 +564,9 @@ end else now = Time.now - if @dev.stat.mtime <= previous_period_end(now) - shift_log_period(now) + period_end = previous_period_end(now) + if @dev.stat.mtime <= period_end + shift_log_period(period_end) end end end @@ -556,19 +577,26 @@ File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}") end end - @dev.close + @dev.close rescue nil File.rename("#{@filename}", "#{@filename}.0") @dev = create_logfile(@filename) return true end - def shift_log_period(now) - postfix = previous_period_end(now).strftime("%Y%m%d") # YYYYMMDD + def shift_log_period(period_end) + postfix = period_end.strftime("%Y%m%d") # YYYYMMDD age_file = "#{@filename}.#{postfix}" 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 - @dev.close + @dev.close rescue nil File.rename("#{@filename}", age_file) @dev = create_logfile(@filename) return true @@ -625,8 +653,8 @@ class Application include Logger::Severity + # Name of the application given at initialize. attr_reader :appname - attr_reader :logdev # # == Synopsis @@ -665,10 +693,24 @@ status 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 - # explanation of the arguments. + # Sets the logger for this application. See the class Logger for an explanation. # + 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) @log = Logger.new(logdev, shift_age, shift_size) @log.progname = @appname @@ -697,6 +739,7 @@ private def run + # TODO: should be an NotImplementedError raise RuntimeError.new('Method run must be defined in the derived class.') end end Index: ruby_1_8/test/logger/test_logger.rb =================================================================== --- ruby_1_8/test/logger/test_logger.rb (revision 20344) +++ ruby_1_8/test/logger/test_logger.rb (revision 20345) @@ -21,10 +21,13 @@ def setup @logger = Logger.new(nil) + @filename = __FILE__ + ".#{$$}" end - def test_const_progname - assert %r!\Alogger\.rb/\S+\z! === Logger::ProgName + def teardown + unless $DEBUG + File.unlink(@filename) if File.exist?(@filename) + end end class Log @@ -262,10 +265,33 @@ end class TestLogDevice < Test::Unit::TestCase - def d(log) - Logger::LogDevice.new(log) + class LogExcnRaiser + 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 + def test_initialize logdev = d(STDERR) assert_equal(STDERR, logdev.dev) @@ -274,16 +300,21 @@ d(nil) end # - filename = __FILE__ + ".#{$$}" + logdev = d(@filename) begin - logdev = d(filename) - assert(File.exist?(filename)) + assert(File.exist?(@filename)) assert(logdev.dev.sync) - assert_equal(filename, logdev.filename) + assert_equal(@filename, logdev.filename) + logdev.write('hello') ensure logdev.close - File.unlink(filename) 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 def test_write @@ -295,6 +326,15 @@ msg = r.read r.close assert_equal("msg2\n\n", msg) + # + logdev = d(LogExcnRaiser.new) + begin + assert_nothing_raised do + logdev.write('hello') + end + ensure + logdev.close + end end def test_close @@ -377,4 +417,88 @@ File.unlink(logfile1) File.unlink(logfile2) 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/