ruby-changes:71819
From: BurdetteLamar <ko1@a...>
Date: Fri, 13 May 2022 22:53:14 +0900 (JST)
Subject: [ruby-changes:71819] 90d8b7219e (master): [ruby/logger] Enhanced RDoc for Logger
https://git.ruby-lang.org/ruby.git/commit/?id=90d8b7219e From 90d8b7219e26135cb1003ebfc5884f132ba39867 Mon Sep 17 00:00:00 2001 From: BurdetteLamar <BurdetteLamar@Y...> Date: Thu, 12 May 2022 07:27:52 -0500 Subject: [ruby/logger] Enhanced RDoc for Logger https://github.com/ruby/logger/commit/16556d06d1 --- lib/logger.rb | 431 ++++++++++++++++++++++++++++++++++----------------- lib/logger/errors.rb | 2 +- 2 files changed, 289 insertions(+), 144 deletions(-) diff --git a/lib/logger.rb b/lib/logger.rb index 7d55f62f30..e66ec2ee21 100644 --- a/lib/logger.rb +++ b/lib/logger.rb @@ -19,216 +19,352 @@ require_relative 'logger/log_device' https://github.com/ruby/ruby/blob/trunk/lib/logger.rb#L19 require_relative 'logger/severity' require_relative 'logger/errors' -# == Description +# \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. # -# The Logger class provides a simple but sophisticated logging utility that -# you can use to output messages. +# == About the Examples # -# The messages have associated levels, such as +INFO+ or +ERROR+ that indicate -# their importance. You can then give the Logger a level, and only messages -# at that level or higher will be printed. +# All examples on this page assume that \Logger has been required: # -# The levels are: +# require 'logger' # -# +UNKNOWN+:: An unknown message that should always be logged. -# +FATAL+:: An unhandleable error that results in a program crash. -# +ERROR+:: A handleable error condition. -# +WARN+:: A warning. -# +INFO+:: Generic (useful) information about system operation. -# +DEBUG+:: Low-level information for developers. +# == Synopsis # -# For instance, in a production system, you may have your Logger set to -# +INFO+ or even +WARN+. -# When you are developing the system, however, you probably -# want to know about the program's internal state, and would set the Logger to -# +DEBUG+. +# Create a log with Logger.new: # -# *Note*: Logger does not escape or sanitize any messages passed to it. -# Developers should be aware of when potentially malicious data (user-input) -# is passed to Logger, and manually escape the untrusted data: +# # Single log file. +# logger = Logger.new('t.log') +# # Size-based rotated log: 3 10-megabyte files. +# logger = Logger.new('t.log', 3, 10485760) +# # Period-based rotated log: daily (also allowed: 'weekly', 'monthly'). +# logger = Logger.new('t.log', 'daily') # -# logger.info("User-input: #{input.dump}") -# logger.info("User-input: %p" % input) +# Add entries (level, message) with Logger#add: # -# You can use #formatter= for escaping all data. +# 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') # -# original_formatter = Logger::Formatter.new -# logger.formatter = proc { |severity, datetime, progname, msg| -# original_formatter.call(severity, datetime, progname, msg.dump) -# } -# logger.info(input) +# There are also these shorthand methods: # -# === Example +# 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') # -# This creates a Logger that outputs to the standard output stream, with a -# level of +WARN+: +# For each method in the two groups immediately above, +# you can omit the string message and provide a block instead. +# Doing so can have two benefits: # -# require 'logger' +# - 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}") +# +# Close the log with Logger#close: +# +# logger.close +# +# == Log Stream +# +# When you create a \Logger instance, you specify an IO stream +# for the logger's output, usually either an open File object +# or an IO object such as <tt>$stdout</tt> or <tt>$stderr</tt>. # -# logger = Logger.new(STDOUT) -# logger.level = Logger::WARN +# == Entries # -# logger.debug("Created logger") -# logger.info("Program started") -# logger.warn("Nothing to do!") +# When you call instance method #add (or its alias #log), +# an entry may (or may not) be written to the log; +# see {Log Level}[rdoc-ref:Logger@Log+Level] # -# path = "a_non_existent_file" +# An entry always has: # -# begin -# File.foreach(path) do |line| -# unless line =~ /^(\w+) = (.*)$/ -# logger.error("Line in wrong format: #{line.chomp}") -# end -# end -# rescue => err -# logger.fatal("Caught exception; exiting") -# logger.fatal(err) -# end +# - A severity (the required argument to #add). +# - An automatically created timestamp. # -# Because the Logger's level is set to +WARN+, only the warning, error, and -# fatal messages are recorded. The debug and info messages are silently -# discarded. +# And may also have: # -# === Features +# - A message. +# - A program name. # -# There are several interesting features that Logger provides, like -# auto-rolling of log files, setting the format of log messages, and -# specifying a program name in conjunction with the message. The next section -# shows you how to achieve these things. +# Example: # +# logger = Logger.new($stdout) +# logger.add(Logger::INFO, 'msg', 'progname') +# # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- progname: msg # -# == HOWTOs +# The default format for an entry is: # -# === How to create a logger +# "%s, [%s #%d] %5s -- %s: %s\n" # -# The options below give you various choices, in more or less increasing -# complexity. +# where the values to be formatted are: # -# 1. Create a logger which logs messages to STDERR/STDOUT. +# - \Severity (one letter). +# - Timestamp. +# - Timezone. +# - \Severity (word). +# - Program name. +# - Message. # -# logger = Logger.new(STDERR) -# logger = Logger.new(STDOUT) +# You can use a different entry format by: # -# 2. Create a logger for the file which has the specified name. +# - Calling #add with a block (affects only the one entry). +# - Setting a format proc with method +# {formatter=}[Logger.html#attribute-i-formatter] +# (affects following entries). # -# logger = Logger.new('logfile.log') +# === \Severity # -# 3. Create a logger for the specified file. +# The severity of a log entry, which is specified in the call to #add, +# does two things: # -# file = File.open('foo.log', File::WRONLY | File::APPEND) -# # To create new logfile, add File::CREAT like: -# # file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT) -# logger = Logger.new(file) +# - 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. # -# 4. Create a logger which ages the logfile once it reaches a certain size. -# Leave 10 "old" log files where each file is about 1,024,000 bytes. +# === Timestamp # -# logger = Logger.new('foo.log', 10, 1024000) +# The timestamp for a log entry is generated automatically +# when the entry is created (by a call to #add). # -# 5. Create a logger which ages the logfile daily/weekly/monthly. +# The logged timestamp is formatted by method +# {Time#strftime}[https://docs.ruby-lang.org/en/master/Time.html#method-i-strftime] +# using this format string: # -# logger = Logger.new('foo.log', 'daily') -# logger = Logger.new('foo.log', 'weekly') -# logger = Logger.new('foo.log', 'monthly') +# '%Y-%m-%dT%H:%M:%S.%6N' # -# === How to log a message +# Example: # -# Notice the different methods (+fatal+, +error+, +info+) being used to log -# messages of various levels? Other methods in this family are +warn+ and -# +debug+. +add+ is used below to log a message of an arbitrary (perhaps -# dynamic) level. +# 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 method #add: +# +# logger = Logger.new($stdout) +# logger.add(Logger::INFO, 'My message') +# # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message +# +# The message object may be a string, or an object that can be converted +# to a string. +# +# *Note*: \Logger does not escape or sanitize any messages passed to it. +# Developers should be aware that malicious data (user input) +# may be passed to \Logger, and should explicitly escape untrusted data. +# +# You can use a custom formatter to escape message data; +# this formatter uses +# {String#dump}[https://ruby-doc.org/core-3.1.2/String.html#method-i-dump] +# to escape the message string: +# +# original_formatter = logger.formatter || Logger::Formatter.new +# logger.formatter = proc { |sev, time, progname, msg| +# original_formatter.call(sev, time, progname, msg.dump) +# } +# logger.info(input) # -# 1. Message in a block. +# === Program Name # -# logger.fatal { "Argument 'foo' not given." } +# The program name is an optional argument to method #add: # -# 2. Message as a string. +# logger = Lo (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/