summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <[email protected]>2025-01-09 11:08:10 +0900
committerHiroshi SHIBATA <[email protected]>2025-01-10 10:19:39 +0900
commitcda268d8e99170f73c9c0c7dd2dbe9494ba89abb (patch)
treee4e08feb57f45f58008d4aa08a454f792a35f35c
parentb0d3771bce9dfcffb7467ea34971198cf4b4079e (diff)
Make logger as bundled gems
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/12537
-rw-r--r--gems/bundled_gems1
-rw-r--r--lib/logger.rb761
-rw-r--r--lib/logger/errors.rb9
-rw-r--r--lib/logger/formatter.rb36
-rw-r--r--lib/logger/log_device.rb236
-rw-r--r--lib/logger/logger.gemspec24
-rw-r--r--lib/logger/period.rb47
-rw-r--r--lib/logger/severity.rb38
-rw-r--r--lib/logger/version.rb5
-rw-r--r--test/logger/test_formatter.rb35
-rw-r--r--test/logger/test_logdevice.rb859
-rw-r--r--test/logger/test_logger.rb402
-rw-r--r--test/logger/test_logperiod.rb67
-rw-r--r--test/logger/test_severity.rb94
14 files changed, 1 insertions, 2613 deletions
diff --git a/gems/bundled_gems b/gems/bundled_gems
index 4d536c2ba0..6958be095d 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -38,3 +38,4 @@ repl_type_completor 0.1.9 https://github.com/ruby/repl_type_completor
ostruct 0.6.1 https://github.com/ruby/ostruct
pstore 0.1.4 https://github.com/ruby/pstore
benchmark 0.4.0 https://github.com/ruby/benchmark
+logger 1.6.4 https://github.com/ruby/logger
diff --git a/lib/logger.rb b/lib/logger.rb
deleted file mode 100644
index 3a7d407226..0000000000
--- a/lib/logger.rb
+++ /dev/null
@@ -1,761 +0,0 @@
-# frozen_string_literal: true
-# logger.rb - simple logging utility
-# Copyright (C) 2000-2003, 2005, 2008, 2011 NAKAMURA, Hiroshi <[email protected]>.
-#
-# Documentation:: NAKAMURA, Hiroshi and Gavin Sinclair
-# License::
-# 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.
-# Revision:: $Id$
-#
-# A simple system for logging messages. See Logger for more documentation.
-
-require 'fiber'
-require 'monitor'
-require 'rbconfig'
-
-require_relative 'logger/version'
-require_relative 'logger/formatter'
-require_relative 'logger/log_device'
-require_relative 'logger/severity'
-require_relative 'logger/errors'
-
-# \Class \Logger provides a simple but sophisticated logging utility that
-# you can use to create one or more
-# {event logs}[https://en.wikipedia.org/wiki/Logging_(software)#Event_logs]
-# for your program.
-# Each such log contains a chronological sequence of entries
-# that provides a record of the program's activities.
-#
-# == About the Examples
-#
-# All examples on this page assume that \Logger has been required:
-#
-# require 'logger'
-#
-# == Synopsis
-#
-# Create a log with Logger.new:
-#
-# # Single log file.
-# logger = Logger.new('t.log')
-# # Size-based rotated logging: 3 10-megabyte files.
-# logger = Logger.new('t.log', 3, 10485760)
-# # Period-based rotated logging: daily (also allowed: 'weekly', 'monthly').
-# logger = Logger.new('t.log', 'daily')
-# # Log to an IO stream.
-# logger = Logger.new($stdout)
-#
-# Add entries (level, message) with Logger#add:
-#
-# logger.add(Logger::DEBUG, 'Maximal debugging info')
-# logger.add(Logger::INFO, 'Non-error information')
-# logger.add(Logger::WARN, 'Non-error warning')
-# logger.add(Logger::ERROR, 'Non-fatal error')
-# logger.add(Logger::FATAL, 'Fatal error')
-# logger.add(Logger::UNKNOWN, 'Most severe')
-#
-# Close the log with Logger#close:
-#
-# logger.close
-#
-# == Entries
-#
-# You can add entries with method Logger#add:
-#
-# logger.add(Logger::DEBUG, 'Maximal debugging info')
-# logger.add(Logger::INFO, 'Non-error information')
-# logger.add(Logger::WARN, 'Non-error warning')
-# logger.add(Logger::ERROR, 'Non-fatal error')
-# logger.add(Logger::FATAL, 'Fatal error')
-# logger.add(Logger::UNKNOWN, 'Most severe')
-#
-# These shorthand methods also add entries:
-#
-# logger.debug('Maximal debugging info')
-# logger.info('Non-error information')
-# logger.warn('Non-error warning')
-# logger.error('Non-fatal error')
-# logger.fatal('Fatal error')
-# logger.unknown('Most severe')
-#
-# When you call any of these methods,
-# the entry may or may not be written to the log,
-# depending on the entry's severity and on the log level;
-# see {Log Level}[rdoc-ref:Logger@Log+Level]
-#
-# An entry always has:
-#
-# - A severity (the required argument to #add).
-# - An automatically created timestamp.
-#
-# And may also have:
-#
-# - A message.
-# - A program name.
-#
-# Example:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO, 'My message.', 'mung')
-# # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- mung: My message.
-#
-# The default format for an entry is:
-#
-# "%s, [%s #%d] %5s -- %s: %s\n"
-#
-# where the values to be formatted are:
-#
-# - \Severity (one letter).
-# - Timestamp.
-# - Process id.
-# - \Severity (word).
-# - Program name.
-# - Message.
-#
-# You can use a different entry format by:
-#
-# - Setting a custom format proc (affects following entries);
-# see {formatter=}[Logger.html#attribute-i-formatter].
-# - Calling any of the methods above with a block
-# (affects only the one entry).
-# Doing so can have two benefits:
-#
-# - Context: the block can evaluate the entire program context
-# and create a context-dependent message.
-# - Performance: the block is not evaluated unless the log level
-# permits the entry actually to be written:
-#
-# logger.error { my_slow_message_generator }
-#
-# Contrast this with the string form, where the string is
-# always evaluated, regardless of the log level:
-#
-# logger.error("#{my_slow_message_generator}")
-#
-# === \Severity
-#
-# The severity of a log entry has two effects:
-#
-# - Determines whether the entry is selected for inclusion in the log;
-# see {Log Level}[rdoc-ref:Logger@Log+Level].
-# - Indicates to any log reader (whether a person or a program)
-# the relative importance of the entry.
-#
-# === Timestamp
-#
-# The timestamp for a log entry is generated automatically
-# when the entry is created.
-#
-# The logged timestamp is formatted by method
-# {Time#strftime}[rdoc-ref:Time#strftime]
-# using this format string:
-#
-# '%Y-%m-%dT%H:%M:%S.%6N'
-#
-# Example:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO)
-# # => I, [2022-05-07T17:04:32.318331 #20536] INFO -- : nil
-#
-# You can set a different format using method #datetime_format=.
-#
-# === Message
-#
-# The message is an optional argument to an entry method:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO, 'My message')
-# # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message
-#
-# For the default entry formatter, <tt>Logger::Formatter</tt>,
-# the message object may be:
-#
-# - A string: used as-is.
-# - An Exception: <tt>message.message</tt> is used.
-# - Anything else: <tt>message.inspect</tt> is used.
-#
-# *Note*: Logger::Formatter does not escape or sanitize
-# the message passed to it.
-# Developers should be aware that malicious data (user input)
-# may be in the message, and should explicitly escape untrusted data.
-#
-# You can use a custom formatter to escape message data;
-# see the example at {formatter=}[Logger.html#attribute-i-formatter].
-#
-# === Program Name
-#
-# The program name is an optional argument to an entry method:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO, 'My message', 'mung')
-# # => I, [2022-05-07T18:17:38.084716 #20536] INFO -- mung: My message
-#
-# The default program name for a new logger may be set in the call to
-# Logger.new via optional keyword argument +progname+:
-#
-# logger = Logger.new('t.log', progname: 'mung')
-#
-# The default program name for an existing logger may be set
-# by a call to method #progname=:
-#
-# logger.progname = 'mung'
-#
-# The current program name may be retrieved with method
-# {progname}[Logger.html#attribute-i-progname]:
-#
-# logger.progname # => "mung"
-#
-# == Log Level
-#
-# The log level setting determines whether an entry is actually
-# written to the log, based on the entry's severity.
-#
-# These are the defined severities (least severe to most severe):
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::DEBUG, 'Maximal debugging info')
-# # => D, [2022-05-07T17:57:41.776220 #20536] DEBUG -- : Maximal debugging info
-# logger.add(Logger::INFO, 'Non-error information')
-# # => I, [2022-05-07T17:59:14.349167 #20536] INFO -- : Non-error information
-# logger.add(Logger::WARN, 'Non-error warning')
-# # => W, [2022-05-07T18:00:45.337538 #20536] WARN -- : Non-error warning
-# logger.add(Logger::ERROR, 'Non-fatal error')
-# # => E, [2022-05-07T18:02:41.592912 #20536] ERROR -- : Non-fatal error
-# logger.add(Logger::FATAL, 'Fatal error')
-# # => F, [2022-05-07T18:05:24.703931 #20536] FATAL -- : Fatal error
-# logger.add(Logger::UNKNOWN, 'Most severe')
-# # => A, [2022-05-07T18:07:54.657491 #20536] ANY -- : Most severe
-#
-# The default initial level setting is Logger::DEBUG, the lowest level,
-# which means that all entries are to be written, regardless of severity:
-#
-# logger = Logger.new($stdout)
-# logger.level # => 0
-# logger.add(0, "My message")
-# # => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message
-#
-# You can specify a different setting in a new logger
-# using keyword argument +level+ with an appropriate value:
-#
-# logger = Logger.new($stdout, level: Logger::ERROR)
-# logger = Logger.new($stdout, level: 'error')
-# logger = Logger.new($stdout, level: :error)
-# logger.level # => 3
-#
-# With this level, entries with severity Logger::ERROR and higher
-# are written, while those with lower severities are not written:
-#
-# logger = Logger.new($stdout, level: Logger::ERROR)
-# logger.add(3)
-# # => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil
-# logger.add(2) # Silent.
-#
-# You can set the log level for an existing logger
-# with method #level=:
-#
-# logger.level = Logger::ERROR
-#
-# These shorthand methods also set the level:
-#
-# logger.debug! # => 0
-# logger.info! # => 1
-# logger.warn! # => 2
-# logger.error! # => 3
-# logger.fatal! # => 4
-#
-# You can retrieve the log level with method #level.
-#
-# logger.level = Logger::ERROR
-# logger.level # => 3
-#
-# These methods return whether a given
-# level is to be written:
-#
-# logger.level = Logger::ERROR
-# logger.debug? # => false
-# logger.info? # => false
-# logger.warn? # => false
-# logger.error? # => true
-# logger.fatal? # => true
-#
-# == Log File Rotation
-#
-# By default, a log file is a single file that grows indefinitely
-# (until explicitly closed); there is no file rotation.
-#
-# To keep log files to a manageable size,
-# you can use _log_ _file_ _rotation_, which uses multiple log files:
-#
-# - Each log file has entries for a non-overlapping
-# time interval.
-# - Only the most recent log file is open and active;
-# the others are closed and inactive.
-#
-# === Size-Based Rotation
-#
-# For size-based log file rotation, call Logger.new with:
-#
-# - Argument +logdev+ as a file path.
-# - Argument +shift_age+ with a positive integer:
-# the number of log files to be in the rotation.
-# - Argument +shift_size+ as a positive integer:
-# the maximum size (in bytes) of each log file;
-# defaults to 1048576 (1 megabyte).
-#
-# Examples:
-#
-# logger = Logger.new('t.log', 3) # Three 1-megabyte files.
-# logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files.
-#
-# For these examples, suppose:
-#
-# logger = Logger.new('t.log', 3)
-#
-# Logging begins in the new log file, +t.log+;
-# the log file is "full" and ready for rotation
-# when a new entry would cause its size to exceed +shift_size+.
-#
-# The first time +t.log+ is full:
-#
-# - +t.log+ is closed and renamed to +t.log.0+.
-# - A new file +t.log+ is opened.
-#
-# The second time +t.log+ is full:
-#
-# - +t.log.0 is renamed as +t.log.1+.
-# - +t.log+ is closed and renamed to +t.log.0+.
-# - A new file +t.log+ is opened.
-#
-# Each subsequent time that +t.log+ is full,
-# the log files are rotated:
-#
-# - +t.log.1+ is removed.
-# - +t.log.0 is renamed as +t.log.1+.
-# - +t.log+ is closed and renamed to +t.log.0+.
-# - A new file +t.log+ is opened.
-#
-# === Periodic Rotation
-#
-# For periodic rotation, call Logger.new with:
-#
-# - Argument +logdev+ as a file path.
-# - Argument +shift_age+ as a string period indicator.
-#
-# Examples:
-#
-# logger = Logger.new('t.log', 'daily') # Rotate log files daily.
-# logger = Logger.new('t.log', 'weekly') # Rotate log files weekly.
-# logger = Logger.new('t.log', 'monthly') # Rotate log files monthly.
-#
-# Example:
-#
-# logger = Logger.new('t.log', 'daily')
-#
-# When the given period expires:
-#
-# - The base log file, +t.log+ is closed and renamed
-# with a date-based suffix such as +t.log.20220509+.
-# - A new log file +t.log+ is opened.
-# - Nothing is removed.
-#
-# The default format for the suffix is <tt>'%Y%m%d'</tt>,
-# which produces a suffix similar to the one above.
-# You can set a different format using create-time option
-# +shift_period_suffix+;
-# see details and suggestions at
-# {Time#strftime}[rdoc-ref:Time#strftime].
-#
-class Logger
- _, name, rev = %w$Id$
- if name
- name = name.chomp(",v")
- else
- name = File.basename(__FILE__)
- end
- rev ||= "v#{VERSION}"
- ProgName = "#{name}/#{rev}"
-
- include Severity
-
- # Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
- def level
- level_override[level_key] || @level
- end
-
- # Sets the log level; returns +severity+.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- # Argument +severity+ may be an integer, a string, or a symbol:
- #
- # logger.level = Logger::ERROR # => 3
- # logger.level = 3 # => 3
- # logger.level = 'error' # => "error"
- # logger.level = :error # => :error
- #
- # Logger#sev_threshold= is an alias for Logger#level=.
- #
- def level=(severity)
- @level = Severity.coerce(severity)
- end
-
- # Adjust the log level during the block execution for the current Fiber only
- #
- # logger.with_level(:debug) do
- # logger.debug { "Hello" }
- # end
- def with_level(severity)
- prev, level_override[level_key] = level, Severity.coerce(severity)
- begin
- yield
- ensure
- if prev
- level_override[level_key] = prev
- else
- level_override.delete(level_key)
- end
- end
- end
-
- # Program name to include in log messages.
- attr_accessor :progname
-
- # Sets the date-time format.
- #
- # Argument +datetime_format+ should be either of these:
- #
- # - A string suitable for use as a format for method
- # {Time#strftime}[rdoc-ref:Time#strftime].
- # - +nil+: the logger uses <tt>'%Y-%m-%dT%H:%M:%S.%6N'</tt>.
- #
- def datetime_format=(datetime_format)
- @default_formatter.datetime_format = datetime_format
- end
-
- # Returns the date-time format; see #datetime_format=.
- #
- def datetime_format
- @default_formatter.datetime_format
- end
-
- # Sets or retrieves the logger entry formatter proc.
- #
- # When +formatter+ is +nil+, the logger uses Logger::Formatter.
- #
- # When +formatter+ is a proc, a new entry is formatted by the proc,
- # which is called with four arguments:
- #
- # - +severity+: The severity of the entry.
- # - +time+: A Time object representing the entry's timestamp.
- # - +progname+: The program name for the entry.
- # - +msg+: The message for the entry (string or string-convertible object).
- #
- # The proc should return a string containing the formatted entry.
- #
- # This custom formatter uses
- # {String#dump}[rdoc-ref:String#dump]
- # to escape the message string:
- #
- # logger = Logger.new($stdout, progname: 'mung')
- # original_formatter = logger.formatter || Logger::Formatter.new
- # logger.formatter = proc { |severity, time, progname, msg|
- # original_formatter.call(severity, time, progname, msg.dump)
- # }
- # logger.add(Logger::INFO, "hello \n ''")
- # logger.add(Logger::INFO, "\f\x00\xff\\\"")
- #
- # Output:
- #
- # I, [2022-05-13T13:16:29.637488 #8492] INFO -- mung: "hello \n ''"
- # I, [2022-05-13T13:16:29.637610 #8492] INFO -- mung: "\f\x00\xFF\\\""
- #
- attr_accessor :formatter
-
- alias sev_threshold level
- alias sev_threshold= level=
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::DEBUG to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def debug?; level <= DEBUG; end
-
- # Sets the log level to Logger::DEBUG.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def debug!; self.level = DEBUG; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::INFO to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def info?; level <= INFO; end
-
- # Sets the log level to Logger::INFO.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def info!; self.level = INFO; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::WARN to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def warn?; level <= WARN; end
-
- # Sets the log level to Logger::WARN.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def warn!; self.level = WARN; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::ERROR to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def error?; level <= ERROR; end
-
- # Sets the log level to Logger::ERROR.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def error!; self.level = ERROR; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::FATAL to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def fatal?; level <= FATAL; end
-
- # Sets the log level to Logger::FATAL.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def fatal!; self.level = FATAL; end
-
- # :call-seq:
- # Logger.new(logdev, shift_age = 0, shift_size = 1048576, **options)
- #
- # With the single argument +logdev+,
- # returns a new logger with all default options:
- #
- # Logger.new('t.log') # => #<Logger:0x000001e685dc6ac8>
- #
- # Argument +logdev+ must be one of:
- #
- # - A string filepath: entries are to be written
- # to the file at that path; if the file at that path exists,
- # new entries are appended.
- # - An IO stream (typically +$stdout+, +$stderr+. or an open file):
- # entries are to be written to the given stream.
- # - +nil+ or +File::NULL+: no entries are to be written.
- #
- # Examples:
- #
- # Logger.new('t.log')
- # Logger.new($stdout)
- #
- # The keyword options are:
- #
- # - +level+: sets the log level; default value is Logger::DEBUG.
- # See {Log Level}[rdoc-ref:Logger@Log+Level]:
- #
- # Logger.new('t.log', level: Logger::ERROR)
- #
- # - +progname+: sets the default program name; default is +nil+.
- # See {Program Name}[rdoc-ref:Logger@Program+Name]:
- #
- # Logger.new('t.log', progname: 'mung')
- #
- # - +formatter+: sets the entry formatter; default is +nil+.
- # See {formatter=}[Logger.html#attribute-i-formatter].
- # - +datetime_format+: sets the format for entry timestamp;
- # default is +nil+.
- # See #datetime_format=.
- # - +binmode+: sets whether the logger writes in binary mode;
- # default is +false+.
- # - +shift_period_suffix+: sets the format for the filename suffix
- # for periodic log file rotation; default is <tt>'%Y%m%d'</tt>.
- # See {Periodic Rotation}[rdoc-ref:Logger@Periodic+Rotation].
- # - +reraise_write_errors+: An array of exception classes, which will
- # be reraised if there is an error when writing to the log device.
- # The default is to swallow all exceptions raised.
- #
- def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
- progname: nil, formatter: nil, datetime_format: nil,
- binmode: false, shift_period_suffix: '%Y%m%d',
- reraise_write_errors: [])
- self.level = level
- self.progname = progname
- @default_formatter = Formatter.new
- self.datetime_format = datetime_format
- self.formatter = formatter
- @logdev = nil
- @level_override = {}
- if logdev && logdev != File::NULL
- @logdev = LogDevice.new(logdev, shift_age: shift_age,
- shift_size: shift_size,
- shift_period_suffix: shift_period_suffix,
- binmode: binmode,
- reraise_write_errors: reraise_write_errors)
- end
- end
-
- # Sets the logger's output stream:
- #
- # - If +logdev+ is +nil+, reopens the current output stream.
- # - If +logdev+ is a filepath, opens the indicated file for append.
- # - If +logdev+ is an IO stream
- # (usually <tt>$stdout</tt>, <tt>$stderr</tt>, or an open File object),
- # opens the stream for append.
- #
- # Example:
- #
- # logger = Logger.new('t.log')
- # logger.add(Logger::ERROR, 'one')
- # logger.close
- # logger.add(Logger::ERROR, 'two') # Prints 'log writing failed. closed stream'
- # logger.reopen
- # logger.add(Logger::ERROR, 'three')
- # logger.close
- # File.readlines('t.log')
- # # =>
- # # ["# Logfile created on 2022-05-12 14:21:19 -0500 by logger.rb/v1.5.0\n",
- # # "E, [2022-05-12T14:21:27.596726 #22428] ERROR -- : one\n",
- # # "E, [2022-05-12T14:23:05.847241 #22428] ERROR -- : three\n"]
- #
- def reopen(logdev = nil)
- @logdev&.reopen(logdev)
- self
- end
-
- # Creates a log entry, which may or may not be written to the log,
- # depending on the entry's severity and on the log level.
- # See {Log Level}[rdoc-ref:Logger@Log+Level]
- # and {Entries}[rdoc-ref:Logger@Entries] for details.
- #
- # Examples:
- #
- # logger = Logger.new($stdout, progname: 'mung')
- # logger.add(Logger::INFO)
- # logger.add(Logger::ERROR, 'No good')
- # logger.add(Logger::ERROR, 'No good', 'gnum')
- #
- # Output:
- #
- # I, [2022-05-12T16:25:31.469726 #36328] INFO -- mung: mung
- # E, [2022-05-12T16:25:55.349414 #36328] ERROR -- mung: No good
- # E, [2022-05-12T16:26:35.841134 #36328] ERROR -- gnum: No good
- #
- # These convenience methods have implicit severity:
- #
- # - #debug.
- # - #info.
- # - #warn.
- # - #error.
- # - #fatal.
- # - #unknown.
- #
- def add(severity, message = nil, progname = nil)
- severity ||= UNKNOWN
- if @logdev.nil? or severity < level
- return true
- end
- if progname.nil?
- progname = @progname
- end
- if message.nil?
- if block_given?
- message = yield
- else
- message = progname
- progname = @progname
- end
- end
- @logdev.write(
- format_message(format_severity(severity), Time.now, progname, message))
- true
- end
- alias log add
-
- # Writes the given +msg+ to the log with no formatting;
- # returns the number of characters written,
- # or +nil+ if no log device exists:
- #
- # logger = Logger.new($stdout)
- # logger << 'My message.' # => 10
- #
- # Output:
- #
- # My message.
- #
- def <<(msg)
- @logdev&.write(msg)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::DEBUG</tt>.
- #
- def debug(progname = nil, &block)
- add(DEBUG, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::INFO</tt>.
- #
- def info(progname = nil, &block)
- add(INFO, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::WARN</tt>.
- #
- def warn(progname = nil, &block)
- add(WARN, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::ERROR</tt>.
- #
- def error(progname = nil, &block)
- add(ERROR, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::FATAL</tt>.
- #
- def fatal(progname = nil, &block)
- add(FATAL, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::UNKNOWN</tt>.
- #
- def unknown(progname = nil, &block)
- add(UNKNOWN, nil, progname, &block)
- end
-
- # Closes the logger; returns +nil+:
- #
- # logger = Logger.new('t.log')
- # logger.close # => nil
- # logger.info('foo') # Prints "log writing failed. closed stream"
- #
- # Related: Logger#reopen.
- def close
- @logdev&.close
- end
-
-private
-
- # \Severity label for logging (max 5 chars).
- SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).freeze
-
- def format_severity(severity)
- SEV_LABEL[severity] || 'ANY'
- end
-
- # Guarantee the existence of this ivar even when subclasses don't call the superclass constructor.
- def level_override
- @level_override ||= {}
- end
-
- def level_key
- Fiber.current
- end
-
- def format_message(severity, datetime, progname, msg)
- (@formatter || @default_formatter).call(severity, datetime, progname, msg)
- end
-end
diff --git a/lib/logger/errors.rb b/lib/logger/errors.rb
deleted file mode 100644
index 88581793f0..0000000000
--- a/lib/logger/errors.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- # not used after 1.2.7. just for compat.
- class Error < RuntimeError # :nodoc:
- end
- class ShiftingError < Error # :nodoc:
- end
-end
diff --git a/lib/logger/formatter.rb b/lib/logger/formatter.rb
deleted file mode 100644
index c634dbf34d..0000000000
--- a/lib/logger/formatter.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- # Default formatter for log messages.
- class Formatter
- Format = "%.1s, [%s #%d] %5s -- %s: %s\n"
- DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N"
-
- attr_accessor :datetime_format
-
- def initialize
- @datetime_format = nil
- end
-
- def call(severity, time, progname, msg)
- sprintf(Format, severity, format_datetime(time), Process.pid, severity, progname, msg2str(msg))
- end
-
- private
-
- def format_datetime(time)
- time.strftime(@datetime_format || DatetimeFormat)
- end
-
- def msg2str(msg)
- case msg
- when ::String
- msg
- when ::Exception
- "#{ msg.message } (#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
- else
- msg.inspect
- end
- end
- end
-end
diff --git a/lib/logger/log_device.rb b/lib/logger/log_device.rb
deleted file mode 100644
index b5b739065d..0000000000
--- a/lib/logger/log_device.rb
+++ /dev/null
@@ -1,236 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'period'
-
-class Logger
- # Device used for logging messages.
- class LogDevice
- include Period
-
- attr_reader :dev
- attr_reader :filename
- include MonitorMixin
-
- def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil, binmode: false, reraise_write_errors: [])
- @dev = @filename = @shift_age = @shift_size = @shift_period_suffix = nil
- @binmode = binmode
- @reraise_write_errors = reraise_write_errors
- mon_initialize
- set_dev(log)
- if @filename
- @shift_age = shift_age || 7
- @shift_size = shift_size || 1048576
- @shift_period_suffix = shift_period_suffix || '%Y%m%d'
-
- unless @shift_age.is_a?(Integer)
- base_time = @dev.respond_to?(:stat) ? @dev.stat.mtime : Time.now
- @next_rotate_time = next_rotate_time(base_time, @shift_age)
- end
- end
- end
-
- def write(message)
- handle_write_errors("writing") do
- synchronize do
- if @shift_age and @dev.respond_to?(:stat)
- handle_write_errors("shifting") {check_shift_log}
- end
- handle_write_errors("writing") {@dev.write(message)}
- end
- end
- end
-
- def close
- begin
- synchronize do
- @dev.close rescue nil
- end
- rescue Exception
- @dev.close rescue nil
- end
- end
-
- def reopen(log = nil)
- # reopen the same filename if no argument, do nothing for IO
- log ||= @filename if @filename
- if log
- synchronize do
- if @filename and @dev
- @dev.close rescue nil # close only file opened by Logger
- @filename = nil
- end
- set_dev(log)
- end
- end
- self
- end
-
- private
-
- # :stopdoc:
-
- MODE = File::WRONLY | File::APPEND
- MODE_TO_OPEN = MODE | File::SHARE_DELETE | File::BINARY
- MODE_TO_CREATE = MODE_TO_OPEN | File::CREAT | File::EXCL
-
- def set_dev(log)
- if log.respond_to?(:write) and log.respond_to?(:close)
- @dev = log
- if log.respond_to?(:path) and path = log.path
- if File.exist?(path)
- @filename = path
- end
- end
- else
- @dev = open_logfile(log)
- @filename = log
- end
- end
-
- if MODE_TO_OPEN == MODE
- def fixup_mode(dev, filename)
- dev
- end
- else
- def fixup_mode(dev, filename)
- return dev if @binmode
- dev.autoclose = false
- old_dev = dev
- dev = File.new(dev.fileno, mode: MODE, path: filename)
- old_dev.close
- PathAttr.set_path(dev, filename) if defined?(PathAttr)
- dev
- end
- end
-
- def open_logfile(filename)
- begin
- dev = File.open(filename, MODE_TO_OPEN)
- rescue Errno::ENOENT
- create_logfile(filename)
- else
- dev = fixup_mode(dev, filename)
- dev.sync = true
- dev.binmode if @binmode
- dev
- end
- end
-
- def create_logfile(filename)
- begin
- logdev = File.open(filename, MODE_TO_CREATE)
- logdev.flock(File::LOCK_EX)
- logdev = fixup_mode(logdev, filename)
- logdev.sync = true
- logdev.binmode if @binmode
- add_log_header(logdev)
- logdev.flock(File::LOCK_UN)
- logdev
- rescue Errno::EEXIST
- # file is created by another process
- open_logfile(filename)
- end
- end
-
- def handle_write_errors(mesg)
- yield
- rescue *@reraise_write_errors
- raise
- rescue
- warn("log #{mesg} failed. #{$!}")
- end
-
- def add_log_header(file)
- file.write(
- "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
- ) if file.size == 0
- end
-
- def check_shift_log
- if @shift_age.is_a?(Integer)
- # Note: always returns false if '0'.
- if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size)
- lock_shift_log { shift_log_age }
- end
- else
- now = Time.now
- if now >= @next_rotate_time
- @next_rotate_time = next_rotate_time(now, @shift_age)
- lock_shift_log { shift_log_period(previous_period_end(now, @shift_age)) }
- end
- end
- end
-
- def lock_shift_log
- retry_limit = 8
- retry_sleep = 0.1
- begin
- File.open(@filename, MODE_TO_OPEN) do |lock|
- lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file
- if File.identical?(@filename, lock) and File.identical?(lock, @dev)
- yield # log shifting
- else
- # log shifted by another process (i-node before locking and i-node after locking are different)
- @dev.close rescue nil
- @dev = open_logfile(@filename)
- end
- end
- rescue Errno::ENOENT
- # @filename file would not exist right after #rename and before #create_logfile
- if retry_limit <= 0
- warn("log rotation inter-process lock failed. #{$!}")
- else
- sleep retry_sleep
- retry_limit -= 1
- retry_sleep *= 2
- retry
- end
- end
- rescue
- warn("log rotation inter-process lock failed. #{$!}")
- end
-
- def shift_log_age
- (@shift_age-3).downto(0) do |i|
- if FileTest.exist?("#{@filename}.#{i}")
- File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
- end
- end
- @dev.close rescue nil
- File.rename("#{@filename}", "#{@filename}.0")
- @dev = create_logfile(@filename)
- return true
- end
-
- def shift_log_period(period_end)
- suffix = period_end.strftime(@shift_period_suffix)
- age_file = "#{@filename}.#{suffix}"
- if FileTest.exist?(age_file)
- # try to avoid filename crash caused by Timestamp change.
- idx = 0
- # .99 can be overridden; avoid too much file search with 'loop do'
- while idx < 100
- idx += 1
- age_file = "#{@filename}.#{suffix}.#{idx}"
- break unless FileTest.exist?(age_file)
- end
- end
- @dev.close rescue nil
- File.rename("#{@filename}", age_file)
- @dev = create_logfile(@filename)
- return true
- end
- end
-end
-
-File.open(__FILE__) do |f|
- File.new(f.fileno, autoclose: false, path: "").path
-rescue IOError
- module PathAttr # :nodoc:
- attr_reader :path
-
- def self.set_path(file, path)
- file.extend(self).instance_variable_set(:@path, path)
- end
- end
-end
diff --git a/lib/logger/logger.gemspec b/lib/logger/logger.gemspec
deleted file mode 100644
index d0b3e194fa..0000000000
--- a/lib/logger/logger.gemspec
+++ /dev/null
@@ -1,24 +0,0 @@
-begin
- require_relative "lib/logger/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "logger"
- spec.version = Logger::VERSION
- spec.authors = ["Naotoshi Seo", "SHIBATA Hiroshi"]
-
- spec.summary = %q{Provides a simple logging utility for outputting messages.}
- spec.description = %q{Provides a simple logging utility for outputting messages.}
- spec.homepage = "https://github.com/ruby/logger"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec", "BSDL", "COPYING"]
- spec.require_paths = ["lib"]
-
- spec.required_ruby_version = ">= 2.5.0"
-
- spec.metadata["changelog_uri"] = spec.homepage + "/releases"
-end
diff --git a/lib/logger/period.rb b/lib/logger/period.rb
deleted file mode 100644
index a0359defe3..0000000000
--- a/lib/logger/period.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- module Period
- module_function
-
- SiD = 24 * 60 * 60
-
- def next_rotate_time(now, shift_age)
- case shift_age
- when 'daily', :daily
- t = Time.mktime(now.year, now.month, now.mday) + SiD
- when 'weekly', :weekly
- t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday)
- when 'monthly', :monthly
- t = Time.mktime(now.year, now.month, 1) + SiD * 32
- return Time.mktime(t.year, t.month, 1)
- when 'now', 'everytime', :now, :everytime
- return now
- else
- raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
- end
- if t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero?
- hour = t.hour
- t = Time.mktime(t.year, t.month, t.mday)
- t += SiD if hour > 12
- end
- t
- end
-
- def previous_period_end(now, shift_age)
- case shift_age
- when 'daily', :daily
- t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
- when 'weekly', :weekly
- t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
- when 'monthly', :monthly
- t = Time.mktime(now.year, now.month, 1) - SiD / 2
- when 'now', 'everytime', :now, :everytime
- return now
- else
- raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
- end
- Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
- end
- end
-end
diff --git a/lib/logger/severity.rb b/lib/logger/severity.rb
deleted file mode 100644
index e96fb0d320..0000000000
--- a/lib/logger/severity.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- # Logging severity.
- module Severity
- # Low-level information, mostly for developers.
- DEBUG = 0
- # Generic (useful) information about system operation.
- INFO = 1
- # A warning.
- WARN = 2
- # A handleable error condition.
- ERROR = 3
- # An unhandleable error that results in a program crash.
- FATAL = 4
- # An unknown message that should always be logged.
- UNKNOWN = 5
-
- LEVELS = {
- "debug" => DEBUG,
- "info" => INFO,
- "warn" => WARN,
- "error" => ERROR,
- "fatal" => FATAL,
- "unknown" => UNKNOWN,
- }
- private_constant :LEVELS
-
- def self.coerce(severity)
- if severity.is_a?(Integer)
- severity
- else
- key = severity.to_s.downcase
- LEVELS[key] || raise(ArgumentError, "invalid log level: #{severity}")
- end
- end
- end
-end
diff --git a/lib/logger/version.rb b/lib/logger/version.rb
deleted file mode 100644
index e1e6b974ff..0000000000
--- a/lib/logger/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- VERSION = "1.6.4"
-end
diff --git a/test/logger/test_formatter.rb b/test/logger/test_formatter.rb
deleted file mode 100644
index 9465722991..0000000000
--- a/test/logger/test_formatter.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require 'logger'
-
-class TestFormatter < Test::Unit::TestCase
- def test_call
- severity = 'INFO'
- time = Time.now
- progname = 'ruby'
- msg = 'This is a test'
- formatter = Logger::Formatter.new
-
- result = formatter.call(severity, time, progname, msg)
- time_matcher = /\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}/
- matcher = /#{severity[0..0]}, \[#{time_matcher} #\d+\] #{severity} -- #{progname}: #{msg}\n/
-
- assert_match(matcher, result)
- end
-
- class CustomFormatter < Logger::Formatter
- def call(time)
- format_datetime(time)
- end
- end
-
- def test_format_datetime
- time = Time.now
- formatter = CustomFormatter.new
-
- result = formatter.call(time)
- matcher = /^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}$/
-
- assert_match(matcher, result)
- end
-end
diff --git a/test/logger/test_logdevice.rb b/test/logger/test_logdevice.rb
deleted file mode 100644
index 610905e542..0000000000
--- a/test/logger/test_logdevice.rb
+++ /dev/null
@@ -1,859 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require 'logger'
-require 'tempfile'
-require 'tmpdir'
-
-class TestLogDevice < Test::Unit::TestCase
- class LogExcnRaiser
- def write(*arg)
- raise 'disk is full'
- end
-
- def close
- end
-
- def stat
- Object.new
- end
- end
-
- def setup
- @tempfile = Tempfile.new("logger")
- @tempfile.close
- @filename = @tempfile.path
- File.unlink(@filename)
- end
-
- def teardown
- @tempfile.close(true)
- end
-
- def d(log, opt = {})
- Logger::LogDevice.new(log, **opt)
- end
-
- def test_initialize
- logdev = d(STDERR)
- assert_equal(STDERR, logdev.dev)
- assert_nil(logdev.filename)
- assert_raise(TypeError) do
- d(nil)
- end
- #
- logdev = d(@filename)
- begin
- assert_file.exist?(@filename)
- assert_predicate(logdev.dev, :sync)
- refute_predicate(logdev.dev, :binmode?)
- assert_equal(@filename, logdev.filename)
- logdev.write('hello')
- ensure
- logdev.close
- end
- # create logfile which is already exist.
- logdev = d(@filename)
- begin
- assert_predicate(logdev.dev, :sync)
- refute_predicate(logdev.dev, :binmode?)
- logdev.write('world')
- logfile = File.read(@filename)
- assert_equal(2, logfile.split(/\n/).size)
- assert_match(/^helloworld$/, logfile)
- ensure
- logdev.close
- end
- # logfile object with path
- tempfile = Tempfile.new("logger")
- tempfile.sync = true
- logdev = d(tempfile)
- begin
- logdev.write('world')
- logfile = File.read(tempfile.path)
- assert_equal(1, logfile.split(/\n/).size)
- assert_match(/^world$/, logfile)
- assert_equal(tempfile.path, logdev.filename)
- ensure
- logdev.close
- File.unlink(tempfile)
- tempfile.close(true)
- end
- end
-
- def test_write
- r, w = IO.pipe
- logdev = d(w)
- logdev.write("msg2\n\n")
- IO.select([r], nil, nil, 0.1)
- w.close
- msg = r.read
- r.close
- assert_equal("msg2\n\n", msg)
- #
- logdev = d(LogExcnRaiser.new)
- class << (stderr = '')
- alias write concat
- end
- $stderr, stderr = stderr, $stderr
- begin
- assert_nothing_raised do
- logdev.write('hello')
- end
- ensure
- logdev.close
- $stderr, stderr = stderr, $stderr
- end
- assert_equal "log writing failed. disk is full\n", stderr
- end
-
- def test_close
- r, w = IO.pipe
- logdev = d(w)
- logdev.write("msg2\n\n")
- IO.select([r], nil, nil, 0.1)
- assert_not_predicate(w, :closed?)
- logdev.close
- assert_predicate(w, :closed?)
- r.close
- end
-
- def test_reopen_io
- logdev = d(STDERR)
- old_dev = logdev.dev
- logdev.reopen
- assert_equal(STDERR, logdev.dev)
- assert_not_predicate(old_dev, :closed?)
- end
-
- def test_reopen_io_by_io
- logdev = d(STDERR)
- old_dev = logdev.dev
- logdev.reopen(STDOUT)
- assert_equal(STDOUT, logdev.dev)
- assert_not_predicate(old_dev, :closed?)
- end
-
- def test_reopen_io_by_file
- logdev = d(STDERR)
- old_dev = logdev.dev
- logdev.reopen(@filename)
- begin
- assert_file.exist?(@filename)
- assert_equal(@filename, logdev.filename)
- assert_not_predicate(old_dev, :closed?)
- ensure
- logdev.close
- end
- end
-
- def test_reopen_file
- logdev = d(@filename)
- old_dev = logdev.dev
-
- logdev.reopen
- begin
- assert_file.exist?(@filename)
- assert_equal(@filename, logdev.filename)
- assert_predicate(old_dev, :closed?)
- ensure
- logdev.close
- end
- end
-
- def test_reopen_file_by_io
- logdev = d(@filename)
- old_dev = logdev.dev
- logdev.reopen(STDOUT)
- assert_equal(STDOUT, logdev.dev)
- assert_nil(logdev.filename)
- assert_predicate(old_dev, :closed?)
- end
-
- def test_reopen_file_by_file
- logdev = d(@filename)
- old_dev = logdev.dev
-
- tempfile2 = Tempfile.new("logger")
- tempfile2.close
- filename2 = tempfile2.path
- File.unlink(filename2)
-
- logdev.reopen(filename2)
- begin
- assert_file.exist?(filename2)
- assert_equal(filename2, logdev.filename)
- assert_predicate(old_dev, :closed?)
- ensure
- logdev.close
- tempfile2.close(true)
- end
- end
-
- def test_shifting_size
- tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_1.log'])
- logfile = tmpfile.path
- logfile0 = logfile + '.0'
- logfile1 = logfile + '.1'
- logfile2 = logfile + '.2'
- logfile3 = logfile + '.3'
- tmpfile.close(true)
- File.unlink(logfile) if File.exist?(logfile)
- File.unlink(logfile0) if File.exist?(logfile0)
- File.unlink(logfile1) if File.exist?(logfile1)
- File.unlink(logfile2) if File.exist?(logfile2)
- logger = Logger.new(logfile, 4, 100)
- logger.error("0" * 15)
- assert_file.exist?(logfile)
- assert_file.not_exist?(logfile0)
- logger.error("0" * 15)
- assert_file.exist?(logfile0)
- assert_file.not_exist?(logfile1)
- logger.error("0" * 15)
- assert_file.exist?(logfile1)
- assert_file.not_exist?(logfile2)
- logger.error("0" * 15)
- assert_file.exist?(logfile2)
- assert_file.not_exist?(logfile3)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile3)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile3)
- logger.close
- File.unlink(logfile)
- File.unlink(logfile0)
- File.unlink(logfile1)
- File.unlink(logfile2)
-
- tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_2.log'])
- logfile = tmpfile.path
- logfile0 = logfile + '.0'
- logfile1 = logfile + '.1'
- logfile2 = logfile + '.2'
- logfile3 = logfile + '.3'
- tmpfile.close(true)
- logger = Logger.new(logfile, 4, 150)
- logger.error("0" * 15)
- assert_file.exist?(logfile)
- assert_file.not_exist?(logfile0)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile0)
- logger.error("0" * 15)
- assert_file.exist?(logfile0)
- assert_file.not_exist?(logfile1)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile1)
- logger.error("0" * 15)
- assert_file.exist?(logfile1)
- assert_file.not_exist?(logfile2)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile2)
- logger.error("0" * 15)
- assert_file.exist?(logfile2)
- assert_file.not_exist?(logfile3)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile3)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile3)
- logger.error("0" * 15)
- assert_file.not_exist?(logfile3)
- logger.close
- File.unlink(logfile)
- File.unlink(logfile0)
- 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_invalid_shifting_age
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(Time.now, 'invalid') }
- assert_raise(ArgumentError) { Logger::Period.previous_period_end(Time.now, 'invalid') }
- end
-
- def test_shifting_age
- 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.not_exist?(filename1)
- assert_file.not_exist?(filename2)
- assert_file.not_exist?(filename3)
- logger.info("0" * 15)
- assert_file.exist?(@filename)
- assert_file.exist?(filename1)
- assert_file.not_exist?(filename2)
- assert_file.not_exist?(filename3)
- logger.warn("0" * 15)
- assert_file.exist?(@filename)
- assert_file.exist?(filename1)
- assert_file.exist?(filename2)
- assert_file.not_exist?(filename3)
- logger.error("0" * 15)
- assert_file.exist?(@filename)
- assert_file.exist?(filename1)
- assert_file.exist?(filename2)
- assert_file.exist?(filename3)
- ensure
- logger.close if logger
- [filename1, filename2, filename3].each do |filename|
- File.unlink(filename) if File.exist?(filename)
- end
- end
- end
-
- def test_shifting_period_suffix
- ['%Y%m%d', '%Y-%m-%d', '%Y'].each do |format|
- if format == '%Y%m%d' # default
- logger = Logger.new(@filename, 'now', 1048576)
- else # config
- logger = Logger.new(@filename, 'now', 1048576, shift_period_suffix: format)
- end
- begin
- yyyymmdd = Time.now.strftime(format)
- filename1 = @filename + ".#{yyyymmdd}"
- filename2 = @filename + ".#{yyyymmdd}.1"
- filename3 = @filename + ".#{yyyymmdd}.2"
- logger.info("0" * 15)
- logger.info("0" * 15)
- logger.info("0" * 15)
- assert_file.exist?(@filename)
- assert_file.exist?(filename1)
- assert_file.exist?(filename2)
- assert_file.exist?(filename3)
- ensure
- logger.close if logger
- [filename1, filename2, filename3].each do |filename|
- File.unlink(filename) if File.exist?(filename)
- end
- end
- end
- end
-
- def test_shifting_size_in_multiprocess
- tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_1.log'])
- logfile = tmpfile.path
- logfile0 = logfile + '.0'
- logfile1 = logfile + '.1'
- logfile2 = logfile + '.2'
- tmpfile.close(true)
- File.unlink(logfile) if File.exist?(logfile)
- File.unlink(logfile0) if File.exist?(logfile0)
- File.unlink(logfile1) if File.exist?(logfile1)
- File.unlink(logfile2) if File.exist?(logfile2)
- begin
- stderr = run_children(2, [logfile], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- logger = Logger.new(ARGV[0], 4, 10)
- 10.times do
- logger.info '0' * 15
- end
- end;
- assert_no_match(/log shifting failed/, stderr)
- assert_no_match(/log writing failed/, stderr)
- assert_no_match(/log rotation inter-process lock failed/, stderr)
- ensure
- File.unlink(logfile) if File.exist?(logfile)
- File.unlink(logfile0) if File.exist?(logfile0)
- File.unlink(logfile1) if File.exist?(logfile1)
- File.unlink(logfile2) if File.exist?(logfile2)
- end
- end
-
- def test_shifting_age_in_multiprocess
- yyyymmdd = Time.now.strftime("%Y%m%d")
- begin
- stderr = run_children(2, [@filename], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- logger = Logger.new(ARGV[0], 'now')
- 10.times do
- logger.info '0' * 15
- end
- end;
- assert_no_match(/log shifting failed/, stderr)
- assert_no_match(/log writing failed/, stderr)
- assert_no_match(/log rotation inter-process lock failed/, stderr)
- ensure
- Dir.glob("#{@filename}.#{yyyymmdd}{,.[1-9]*}") do |filename|
- File.unlink(filename) if File.exist?(filename)
- end
- end
- end
-
- def test_open_logfile_in_multiprocess
- tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_1.log'])
- logfile = tmpfile.path
- tmpfile.close(true)
- begin
- 20.times do
- run_children(2, [logfile], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- logfile = ARGV[0]
- logdev = Logger::LogDevice.new(logfile)
- logdev.send(:open_logfile, logfile)
- end;
- assert_equal(1, File.readlines(logfile).grep(/# Logfile created on/).size)
- File.unlink(logfile)
- end
- ensure
- File.unlink(logfile) if File.exist?(logfile)
- end
- end
-
- def test_shifting_size_not_rotate_too_much
- logdev0 = d(@filename)
- logdev0.__send__(:add_log_header, @tempfile)
- header_size = @tempfile.size
- message = "*" * 99 + "\n"
- shift_size = header_size + message.size * 3 - 1
- opt = {shift_age: 1, shift_size: shift_size}
-
- Dir.mktmpdir do |tmpdir|
- begin
- log = File.join(tmpdir, "log")
- logdev1 = d(log, opt)
- logdev2 = d(log, opt)
-
- assert_file.identical?(log, logdev1.dev)
- assert_file.identical?(log, logdev2.dev)
-
- 3.times{logdev1.write(message)}
- assert_file.identical?(log, logdev1.dev)
- assert_file.identical?(log, logdev2.dev)
-
- logdev1.write(message)
- assert_file.identical?(log, logdev1.dev)
- # NOTE: below assertion fails in JRuby 9.3 and TruffleRuby
- assert_file.identical?(log + ".0", logdev2.dev)
-
- logdev2.write(message)
- assert_file.identical?(log, logdev1.dev)
- assert_file.identical?(log, logdev2.dev)
-
- logdev1.write(message)
- assert_file.identical?(log, logdev1.dev)
- assert_file.identical?(log, logdev2.dev)
- ensure
- logdev1.close if logdev1
- logdev2.close if logdev2
- end
- end
- ensure
- logdev0.close
- end
-
- def test_shifting_midnight
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([*%W"--disable=gems -rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- File.utime(*[Time.mktime(2014, 1, 2, 0, 0, 0)]*2, log)
-
- Time.now = Time.mktime(2014, 1, 2, 23, 59, 59, 999000)
- dev = Logger::LogDevice.new(log, shift_age: 'daily')
- dev.write("#{Time.now} hello-1\n")
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.mktime(2014, 1, 3, 1, 1, 1)
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close
- end
- end;
-
- bug = '[GH-539]'
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- assert_file.for(bug).exist?(log+".20140102")
- assert_match(/hello-1/, File.read(log+".20140102"), bug)
- end
- end
-
- env_tz_works = /linux|darwin|freebsd|openbsd/ =~ RUBY_PLATFORM # borrow from test/ruby/test_time_tz.rb
-
- def test_shifting_weekly
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([{"TZ"=>"UTC"}, *%W"-rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- Time.now = Time.utc(2015, 12, 14, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new("log", shift_age: 'weekly')
-
- Time.now = Time.utc(2015, 12, 19, 12, 34, 56)
- dev.write("#{Time.now} hello-1\n")
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.utc(2015, 12, 20, 0, 1, 1)
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close if dev
- end
- end;
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- log = Dir.glob(log+".*")
- assert_equal(1, log.size)
- log, = *log
- cont = File.read(log)
- assert_match(/hello-1/, cont)
- assert_equal("2015-12-19", cont[/^[-\d]+/])
- assert_equal("20151219", log[/\d+\z/])
- end
- end if env_tz_works
-
- def test_shifting_monthly
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([{"TZ"=>"UTC"}, *%W"-rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- Time.now = Time.utc(2015, 12, 14, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new("log", shift_age: 'monthly')
-
- Time.now = Time.utc(2015, 12, 31, 12, 34, 56)
- dev.write("#{Time.now} hello-1\n")
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.utc(2016, 1, 1, 0, 1, 1)
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close if dev
- end
- end;
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- log = Dir.glob(log+".*")
- assert_equal(1, log.size)
- log, = *log
- cont = File.read(log)
- assert_match(/hello-1/, cont)
- assert_equal("2015-12-31", cont[/^[-\d]+/])
- assert_equal("20151231", log[/\d+\z/])
- end
- end if env_tz_works
-
- def test_shifting_dst_change
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([{"TZ"=>"Europe/London"}, *%W"--disable=gems -rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
-
- Time.now = Time.mktime(2014, 3, 30, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new(log, shift_age: 'daily')
- dev.write("#{Time.now} hello-1\n")
- File.utime(*[Time.mktime(2014, 3, 30, 0, 2, 3)]*2, log)
-
- Time.now = Time.mktime(2014, 3, 31, 0, 1, 1)
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close
- end
- end;
-
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- assert_file.exist?(log+".20140330")
- end
- end if env_tz_works
-
- def test_shifting_weekly_dst_change
- Dir.mktmpdir do |tmpdir|
- assert_separately([{"TZ"=>"Europe/London"}, *%W"-rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- Time.now = Time.mktime(2015, 10, 25, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new("log", shift_age: 'weekly')
- dev.write("#{Time.now} hello-1\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close if dev
- end
- end;
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-1/, cont)
- end
- end if env_tz_works
-
- def test_shifting_monthly_dst_change
- Dir.mktmpdir do |tmpdir|
- assert_separately([{"TZ"=>"Europe/London"}, *%W"-rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- Time.now = Time.utc(2016, 9, 1, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new("log", shift_age: 'monthly')
-
- Time.now = Time.utc(2016, 9, 8, 7, 6, 5)
- dev.write("#{Time.now} hello-1\n")
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.utc(2016, 10, 9, 8, 7, 6)
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.utc(2016, 10, 9, 8, 7, 7)
- dev.write("#{Time.now} hello-3\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close if dev
- end
- end;
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- log = Dir.glob(log+".*")
- assert_equal(1, log.size)
- log, = *log
- cont = File.read(log)
- assert_match(/hello-1/, cont)
- assert_equal("2016-09-08", cont[/^[-\d]+/])
- assert_equal("20160930", log[/\d+\z/])
- end
- end if env_tz_works
-
- def test_shifting_midnight_exist_file
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([*%W"--disable=gems -rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- File.utime(*[Time.mktime(2014, 1, 2, 0, 0, 0)]*2, log)
-
- Time.now = Time.mktime(2014, 1, 2, 23, 59, 59, 999000)
- dev = Logger::LogDevice.new(log, shift_age: 'daily')
- dev.write("#{Time.now} hello-1\n")
- dev.close
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.mktime(2014, 1, 3, 1, 1, 1)
- dev = Logger::LogDevice.new(log, shift_age: 'daily')
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close
- end
- end;
-
- bug = '[GH-539]'
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- assert_file.for(bug).exist?(log+".20140102")
- assert_match(/hello-1/, File.read(log+".20140102"), bug)
- end
- end
-
- env_tz_works = /linux|darwin|freebsd/ =~ RUBY_PLATFORM # borrow from test/ruby/test_time_tz.rb
-
- def test_shifting_weekly_exist_file
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([{"TZ"=>"UTC"}, *%W"-rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- Time.now = Time.utc(2015, 12, 14, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new("log", shift_age: 'weekly')
-
- Time.now = Time.utc(2015, 12, 19, 12, 34, 56)
- dev.write("#{Time.now} hello-1\n")
- dev.close
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.utc(2015, 12, 20, 0, 1, 1)
- dev = Logger::LogDevice.new("log", shift_age: 'weekly')
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close if dev
- end
- end;
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- log = Dir.glob(log+".*")
- assert_equal(1, log.size)
- log, = *log
- cont = File.read(log)
- assert_match(/hello-1/, cont)
- assert_equal("2015-12-19", cont[/^[-\d]+/])
- assert_equal("20151219", log[/\d+\z/])
- end
- end if env_tz_works
-
- def test_shifting_monthly_exist_file
- Dir.mktmpdir do |tmpdir|
- assert_in_out_err([{"TZ"=>"UTC"}, *%W"-rlogger -C#{tmpdir} -"], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- begin
- module FakeTime
- attr_accessor :now
- end
-
- class << Time
- prepend FakeTime
- end
-
- log = "log"
- File.open(log, "w") {}
- Time.now = Time.utc(2015, 12, 14, 0, 1, 1)
- File.utime(Time.now, Time.now, log)
-
- dev = Logger::LogDevice.new("log", shift_age: 'monthly')
-
- Time.now = Time.utc(2015, 12, 31, 12, 34, 56)
- dev.write("#{Time.now} hello-1\n")
- dev.close
- File.utime(Time.now, Time.now, log)
-
- Time.now = Time.utc(2016, 1, 1, 0, 1, 1)
- dev = Logger::LogDevice.new("log", shift_age: 'monthly')
- dev.write("#{Time.now} hello-2\n")
- File.utime(Time.now, Time.now, log)
- ensure
- dev.close if dev
- end
- end;
- log = File.join(tmpdir, "log")
- cont = File.read(log)
- assert_match(/hello-2/, cont)
- assert_not_match(/hello-1/, cont)
- log = Dir.glob(log+".*")
- assert_equal(1, log.size)
- log, = *log
- cont = File.read(log)
- assert_match(/hello-1/, cont)
- assert_equal("2015-12-31", cont[/^[-\d]+/])
- assert_equal("20151231", log[/\d+\z/])
- end
- end if env_tz_works
-
- private
-
- def run_children(n, args, src)
- r, w = IO.pipe
- [w, *(1..n).map do
- f = IO.popen([EnvUtil.rubybin, *%w[--disable=gems -rlogger -], *args], "w", err: w)
- f.puts(src)
- f
- end].each(&:close)
- stderr = r.read
- r.close
- stderr
- end
-end
diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb
deleted file mode 100644
index 2023553a6c..0000000000
--- a/test/logger/test_logger.rb
+++ /dev/null
@@ -1,402 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require 'logger'
-require 'tempfile'
-
-class TestLogger < Test::Unit::TestCase
- include Logger::Severity
-
- def setup
- @logger = Logger.new(nil)
- end
-
- class Log
- attr_reader :label, :datetime, :pid, :severity, :progname, :msg
- def initialize(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(logger, severity, msg, progname = nil, &block)
- log(logger, :add, severity, msg, progname, &block)
- end
-
- 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)
- Tempfile.create(File.basename(__FILE__) + '.log') {|logdev|
- logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
- logger.__send__(msg_id, *arg, &block)
- logdev.rewind
- logdev.read
- }
- end
-
- def test_level
- @logger.level = UNKNOWN
- assert_equal(UNKNOWN, @logger.level)
- @logger.level = INFO
- assert_equal(INFO, @logger.level)
- @logger.sev_threshold = ERROR
- assert_equal(ERROR, @logger.sev_threshold)
- @logger.sev_threshold = WARN
- assert_equal(WARN, @logger.sev_threshold)
- assert_equal(WARN, @logger.level)
-
- @logger.level = DEBUG
- assert(@logger.debug?)
- assert(@logger.info?)
- @logger.level = INFO
- assert(@logger.info?)
- assert(@logger.warn?)
- @logger.level = WARN
- assert(@logger.warn?)
- assert(@logger.error?)
- @logger.level = ERROR
- assert(@logger.error?)
- assert(@logger.fatal?)
- @logger.level = FATAL
- assert(@logger.fatal?)
- @logger.level = UNKNOWN
- end
-
- def test_symbol_level
- logger_symbol_levels = {
- debug: DEBUG,
- info: INFO,
- warn: WARN,
- error: ERROR,
- fatal: FATAL,
- unknown: UNKNOWN,
- DEBUG: DEBUG,
- INFO: INFO,
- WARN: WARN,
- ERROR: ERROR,
- FATAL: FATAL,
- UNKNOWN: UNKNOWN,
- }
- logger_symbol_levels.each do |symbol, level|
- @logger.level = symbol
- assert(@logger.level == level)
- end
- assert_raise(ArgumentError) { @logger.level = :something_wrong }
- end
-
- def test_string_level
- logger_string_levels = {
- 'debug' => DEBUG,
- 'info' => INFO,
- 'warn' => WARN,
- 'error' => ERROR,
- 'fatal' => FATAL,
- 'unknown' => UNKNOWN,
- 'DEBUG' => DEBUG,
- 'INFO' => INFO,
- 'WARN' => WARN,
- 'ERROR' => ERROR,
- 'FATAL' => FATAL,
- 'UNKNOWN' => UNKNOWN,
- }
- logger_string_levels.each do |string, level|
- @logger.level = string
- assert(@logger.level == level)
- end
- assert_raise(ArgumentError) { @logger.level = 'something_wrong' }
- end
-
- def test_reraise_write_errors
- c = Object.new
- e = Class.new(StandardError)
- c.define_singleton_method(:write){|*| raise e}
- c.define_singleton_method(:close){}
- logger = Logger.new(c, :reraise_write_errors=>[e])
- assert_raise(e) { logger.warn('foo') }
- end
-
- def test_progname
- assert_nil(@logger.progname)
- @logger.progname = "name"
- assert_equal("name", @logger.progname)
- end
-
- def test_datetime_format
- verbose, $VERBOSE = $VERBOSE, false
- dummy = STDERR
- logger = Logger.new(dummy)
- log = log_add(logger, INFO, "foo")
- assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime)
- logger.datetime_format = "%d%b%Y@%H:%M:%S"
- log = log_add(logger, INFO, "foo")
- assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime)
- logger.datetime_format = ""
- log = log_add(logger, INFO, "foo")
- assert_match(/^$/, log.datetime)
- ensure
- $VERBOSE = verbose
- 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
- logger = Logger.new(STDERR)
- assert_nil(logger.progname)
- assert_equal(DEBUG, logger.level)
- assert_nil(logger.datetime_format)
- end
-
- def test_initialize_with_level
- # default
- logger = Logger.new(STDERR)
- assert_equal(Logger::DEBUG, logger.level)
- # config
- logger = Logger.new(STDERR, level: :info)
- assert_equal(Logger::INFO, logger.level)
- end
-
- def test_initialize_with_progname
- # default
- logger = Logger.new(STDERR)
- assert_equal(nil, logger.progname)
- # config
- logger = Logger.new(STDERR, progname: :progname)
- assert_equal(:progname, logger.progname)
- end
-
- def test_initialize_with_formatter
- # default
- logger = Logger.new(STDERR)
- log = log(logger, :info, "foo")
- assert_equal("foo\n", log.msg)
- # config
- logger = Logger.new(STDERR, formatter: proc { |severity, timestamp, progname, msg|
- "#{severity}:#{msg}\n\n"
- })
- line = log_raw(logger, :info, "foo")
- assert_equal("INFO:foo\n\n", line)
- end
-
- def test_initialize_with_datetime_format
- # default
- logger = Logger.new(STDERR)
- log = log_add(logger, INFO, "foo")
- assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime)
- # config
- logger = Logger.new(STDERR, datetime_format: "%d%b%Y@%H:%M:%S")
- log = log_add(logger, INFO, "foo")
- assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime)
- end
-
- def test_reopen
- logger = Logger.new(STDERR)
- logger.reopen(STDOUT)
- assert_equal(STDOUT, logger.instance_variable_get(:@logdev).dev)
- end
-
- def test_reopen_nil_logdevice
- logger = Logger.new(File::NULL)
- assert_nothing_raised do
- logger.reopen(STDOUT)
- end
- end
-
- def test_add
- logger = Logger.new(nil)
- logger.progname = "my_progname"
- assert(logger.add(INFO))
- log = log_add(logger, nil, "msg")
- assert_equal("ANY", log.severity)
- assert_equal("my_progname", log.progname)
- logger.level = WARN
- assert(logger.log(INFO))
- assert_nil(log_add(logger, INFO, "msg").msg)
- log = log_add(logger, WARN, nil) { "msg" }
- assert_equal("msg\n", log.msg)
- log = log_add(logger, WARN, "") { "msg" }
- assert_equal("\n", log.msg)
- assert_equal("my_progname", log.progname)
- log = log_add(logger, WARN, nil, "progname?")
- assert_equal("progname?\n", log.msg)
- assert_equal("my_progname", log.progname)
- #
- logger = Logger.new(nil)
- log = log_add(logger, INFO, nil, false)
- assert_equal("false\n", log.msg)
- end
-
- def test_add_binary_data_with_binmode_logdev
- EnvUtil.with_default_internal(Encoding::UTF_8) do
- begin
- tempfile = Tempfile.new("logger")
- tempfile.close
- filename = tempfile.path
- File.unlink(filename)
-
- logger = Logger.new filename, binmode: true
- logger.level = Logger::DEBUG
-
- str = +"\x80"
- str.force_encoding("ASCII-8BIT")
-
- logger.add Logger::DEBUG, str
- assert_equal(2, File.binread(filename).split(/\n/).size)
- ensure
- logger.close
- tempfile.unlink
- end
- end
- end
-
- def test_level_log
- logger = Logger.new(nil)
- logger.progname = "my_progname"
- log = log(logger, :debug, "custom_progname") { "msg" }
- assert_equal("msg\n", log.msg)
- assert_equal("custom_progname", log.progname)
- assert_equal("DEBUG", log.severity)
- assert_equal("D", log.label)
- #
- log = log(logger, :debug) { "msg_block" }
- assert_equal("msg_block\n", log.msg)
- assert_equal("my_progname", log.progname)
- log = log(logger, :debug, "msg_inline")
- assert_equal("msg_inline\n", log.msg)
- assert_equal("my_progname", log.progname)
- #
- log = log(logger, :info, "custom_progname") { "msg" }
- assert_equal("msg\n", log.msg)
- assert_equal("custom_progname", log.progname)
- assert_equal("INFO", log.severity)
- assert_equal("I", log.label)
- #
- log = log(logger, :warn, "custom_progname") { "msg" }
- assert_equal("msg\n", log.msg)
- assert_equal("custom_progname", log.progname)
- assert_equal("WARN", log.severity)
- assert_equal("W", log.label)
- #
- log = log(logger, :error, "custom_progname") { "msg" }
- assert_equal("msg\n", log.msg)
- assert_equal("custom_progname", log.progname)
- assert_equal("ERROR", log.severity)
- assert_equal("E", log.label)
- #
- log = log(logger, :fatal, "custom_progname") { "msg" }
- assert_equal("msg\n", log.msg)
- assert_equal("custom_progname", log.progname)
- assert_equal("FATAL", log.severity)
- assert_equal("F", log.label)
- #
- log = log(logger, :unknown, "custom_progname") { "msg" }
- assert_equal("msg\n", log.msg)
- assert_equal("custom_progname", log.progname)
- assert_equal("ANY", log.severity)
- assert_equal("A", log.label)
- end
-
- def test_close
- r, w = IO.pipe
- assert(!w.closed?)
- logger = Logger.new(w)
- logger.close
- assert(w.closed?)
- r.close
- end
-
- class MyError < StandardError
- end
-
- class MyMsg
- def inspect
- "my_msg"
- end
- end
-
- def test_format
- logger = Logger.new(nil)
- log = log_add(logger, INFO, "msg\n")
- assert_equal("msg\n\n", log.msg)
- begin
- raise MyError.new("excn")
- rescue MyError => e
- log = log_add(logger, INFO, e)
- assert_match(/^excn \(TestLogger::MyError\)/, log.msg)
- # expects backtrace is dumped across multi lines. 10 might be changed.
- assert(log.msg.split(/\n/).size >= 10)
- end
- log = log_add(logger, INFO, MyMsg.new)
- assert_equal("my_msg\n", log.msg)
- end
-
- def test_lshift
- r, w = IO.pipe
- logger = Logger.new(w)
- logger << "msg"
- IO.select([r], nil, nil, 0.1)
- w.close
- msg = r.read
- r.close
- assert_equal("msg", msg)
- #
- r, w = IO.pipe
- logger = Logger.new(w)
- logger << "msg2\n\n"
- IO.select([r], nil, nil, 0.1)
- w.close
- msg = r.read
- r.close
- assert_equal("msg2\n\n", msg)
- end
-
- class CustomLogger < Logger
- def level
- INFO
- end
- end
-
- def test_overriding_level
- logger = CustomLogger.new(nil)
- log = log(logger, :info) { "msg" }
- assert_equal "msg\n", log.msg
- #
- log = log(logger, :debug) { "msg" }
- assert_nil log.msg
- end
-
- def test_does_not_instantiate_log_device_for_File_NULL
- l = Logger.new(File::NULL)
- assert_nil(l.instance_variable_get(:@logdev))
- end
-end
diff --git a/test/logger/test_logperiod.rb b/test/logger/test_logperiod.rb
deleted file mode 100644
index ee38d877c6..0000000000
--- a/test/logger/test_logperiod.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require "logger"
-require "time"
-
-class TestLogPeriod < Test::Unit::TestCase
- def test_next_rotate_time
- time = Time.parse("2019-07-18 13:52:02")
-
- assert_next_rotate_time_words(time, "2019-07-19 00:00:00", ["daily", :daily])
- assert_next_rotate_time_words(time, "2019-07-21 00:00:00", ["weekly", :weekly])
- assert_next_rotate_time_words(time, "2019-08-01 00:00:00", ["monthly", :monthly])
-
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, "invalid") }
- end
-
- def test_next_rotate_time_extreme_cases
- # First day of Month and Saturday
- time = Time.parse("2018-07-01 00:00:00")
-
- assert_next_rotate_time_words(time, "2018-07-02 00:00:00", ["daily", :daily])
- assert_next_rotate_time_words(time, "2018-07-08 00:00:00", ["weekly", :weekly])
- assert_next_rotate_time_words(time, "2018-08-01 00:00:00", ["monthly", :monthly])
-
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, "invalid") }
- end
-
- def test_previous_period_end
- time = Time.parse("2019-07-18 13:52:02")
-
- assert_previous_period_end_words(time, "2019-07-17 23:59:59", ["daily", :daily])
- assert_previous_period_end_words(time, "2019-07-13 23:59:59", ["weekly", :weekly])
- assert_previous_period_end_words(time, "2019-06-30 23:59:59", ["monthly", :monthly])
-
- assert_raise(ArgumentError) { Logger::Period.previous_period_end(time, "invalid") }
- end
-
- def test_previous_period_end_extreme_cases
- # First day of Month and Saturday
- time = Time.parse("2018-07-01 00:00:00")
- previous_date = "2018-06-30 23:59:59"
-
- assert_previous_period_end_words(time, previous_date, ["daily", :daily])
- assert_previous_period_end_words(time, previous_date, ["weekly", :weekly])
- assert_previous_period_end_words(time, previous_date, ["monthly", :monthly])
-
- assert_raise(ArgumentError) { Logger::Period.previous_period_end(time, "invalid") }
- end
-
- private
-
- def assert_next_rotate_time_words(time, next_date, words)
- assert_time_words(:next_rotate_time, time, next_date, words)
- end
-
- def assert_previous_period_end_words(time, previous_date, words)
- assert_time_words(:previous_period_end, time, previous_date, words)
- end
-
- def assert_time_words(method, time, date, words)
- words.each do |word|
- daily_result = Logger::Period.public_send(method, time, word)
- expected_result = Time.parse(date)
- assert_equal(expected_result, daily_result)
- end
- end
-end
diff --git a/test/logger/test_severity.rb b/test/logger/test_severity.rb
deleted file mode 100644
index fb26939e9d..0000000000
--- a/test/logger/test_severity.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require 'logger'
-
-class TestLoggerSeverity < Test::Unit::TestCase
- include Logger::Severity
-
- def test_enum
- logger_levels = Logger.constants
- levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"]
- Logger::Severity.constants.each do |level|
- assert(levels.include?(level.to_s))
- assert(logger_levels.include?(level))
- end
- assert_equal(levels.size, Logger::Severity.constants.size)
- end
-
- def test_level_assignment
- logger = Logger.new(nil)
-
- Logger::Severity.constants.each do |level|
- next if level == :UNKNOWN
-
- logger.send("#{level.downcase}!")
- assert(logger.level) == Logger::Severity.const_get(level)
- end
- end
-
- def test_fiber_local_level
- logger = Logger.new(nil)
- logger.level = INFO # default level
- other = Logger.new(nil)
- other.level = ERROR # default level
-
- assert_equal(other.level, ERROR)
- logger.with_level(:WARN) do
- assert_equal(other.level, ERROR)
- assert_equal(logger.level, WARN)
-
- logger.with_level(DEBUG) do # verify reentrancy
- assert_equal(logger.level, DEBUG)
-
- Fiber.new do
- assert_equal(logger.level, INFO)
- logger.with_level(:WARN) do
- assert_equal(other.level, ERROR)
- assert_equal(logger.level, WARN)
- end
- assert_equal(logger.level, INFO)
- end.resume
-
- assert_equal(logger.level, DEBUG)
- end
- assert_equal(logger.level, WARN)
- end
- assert_equal(logger.level, INFO)
- end
-
- def test_thread_local_level
- subclass = Class.new(Logger) do
- def level_key
- Thread.current
- end
- end
-
- logger = subclass.new(nil)
- logger.level = INFO # default level
- other = subclass.new(nil)
- other.level = ERROR # default level
-
- assert_equal(other.level, ERROR)
- logger.with_level(:WARN) do
- assert_equal(other.level, ERROR)
- assert_equal(logger.level, WARN)
-
- logger.with_level(DEBUG) do # verify reentrancy
- assert_equal(logger.level, DEBUG)
-
- Fiber.new do
- assert_equal(logger.level, DEBUG)
- logger.with_level(:WARN) do
- assert_equal(other.level, ERROR)
- assert_equal(logger.level, WARN)
- end
- assert_equal(logger.level, DEBUG)
- end.resume
-
- assert_equal(logger.level, DEBUG)
- end
- assert_equal(logger.level, WARN)
- end
- assert_equal(logger.level, INFO)
- end
-end