класс Logger
Класс Logger предоставляет простую, но сложную утилиту для ведения журналов, которую можно использовать для создания одного или нескольких журналов событий для вашей программы. Каждый такой журнал содержит хронологическую последовательность записей, которые обеспечивают запись активности программы.
О примерах
Все примеры на этой странице предполагают, что Logger был загружен:
require 'logger'
Краткое описание
Создайте журнал с помощью 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)
Добавьте записи (уровень, сообщение) с помощью 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')
Закройте журнал с помощью Logger#close:
logger.close
Записи
Вы можете добавить записи с помощью метода 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')
Эти сокращенные методы также добавляют записи:
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')
Когда вы вызываете любой из этих методов, запись может или не может быть записана в журнал, в зависимости от уровня серьезности записи и уровня журнала; см. Уровень журнала
Запись всегда имеет:
-
Уровень серьезности (обязательный аргумент для
add). -
Автоматически созданную метку времени.
И также может иметь:
-
Сообщение.
-
Имя программы.
Пример:
logger = Logger.new($stdout) logger.add(Logger::INFO, 'My message.', 'mung') # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- mung: My message.
Формат записи по умолчанию:
"%s, [%s #%d] %5s -- %s: %s\n"
где значения для форматирования:
-
Уровень серьезности (одна буква).
-
Метка времени.
-
Processидентификатор. -
Уровень серьезности (слово).
-
Имя программы.
-
Сообщение.
Вы можете использовать другой формат записи, выполнив:
-
Установка пользовательского формата proc (сказывается на последующих записях); см. formatter=.
-
Вызов любого из вышеуказанных методов с блоком (сказывается только на одной записи). Это может иметь две выгоды:
-
Контекст: блок может оценить весь контекст программы и создать сообщение, зависящее от контекста.
-
Производительность: блок не оценивается, если уровень журнала не разрешает фактическое запись записи:
logger.error { my_slow_message_generator }Протипоставьте это строковой форме, где строка всегда оценивается, независимо от уровня журнала:
logger.error("#{my_slow_message_generator}")
-
Уровень серьезности
Уровень серьезности записи журнала имеет два эффекта:
-
Определяет, выбирается ли запись для включения в журнал; см. Уровень журнала.
-
Указывает любому читателю журнала (будь то человек или программа) относительную важность записи.
Метка времени
Метка времени записи журнала генерируется автоматически при создании записи.
Записанная метка времени форматируется методом Time#strftime с использованием следующего формата:
'%Y-%m-%dT%H:%M:%S.%6N'
Пример:
logger = Logger.new($stdout) logger.add(Logger::INFO) # => I, [2022-05-07T17:04:32.318331 #20536] INFO -- : nil
Вы можете установить другой формат, используя метод datetime_format=.
Сообщение
Сообщение является необязательным аргументом метода записи:
logger = Logger.new($stdout) logger.add(Logger::INFO, 'My message') # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message
Для формата записи по умолчанию, Logger::Formatter, объект сообщения может быть:
-
Строка: используется как есть.
-
Исключение:
message.messageиспользуется. -
Что-либо другое:
message.inspectиспользуется.
Примечание: Logger::Formatter не экранирует и не очищает сообщение, переданное ему. Разработчики должны знать, что в сообщении могут быть вредоносные данные (ввод пользователя), и должны явно экранировать недоверенные данные.
Вы можете использовать пользовательский форматер для экранирования данных сообщения; см. пример в formatter=.
Имя программы
Имя программы является необязательным аргументом метода записи:
logger = Logger.new($stdout) logger.add(Logger::INFO, 'My message', 'mung') # => I, [2022-05-07T18:17:38.084716 #20536] INFO -- mung: My message
Имя программы по умолчанию для нового логгера может быть установлено в вызове Logger.new через необязательный ключевой аргумент progname:
logger = Logger.new('t.log', progname: 'mung')
Имя программы по умолчанию для существующего логгера может быть установлено вызовом метода progname=:
logger.progname = 'mung'
Текущее имя программы можно получить с помощью метода progname:
logger.progname # => "mung"
Уровень журнала
Настройка уровня журнала определяет, записывается ли запись в журнал на основе уровня серьезности записи.
Определенные уровни серьезности (от наименее серьезного к наиболее серьезному):
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
Настройка уровня по умолчанию — Logger::DEBUG, наименьший уровень, что означает, что все записи должны быть записаны независимо от уровня серьезности:
logger = Logger.new($stdout) logger.level # => 0 logger.add(0, "My message") # => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message
Вы можете указать другую настройку в новом логгере, используя ключевой аргумент level с соответствующим значением:
logger = Logger.new($stdout, level: Logger::ERROR) logger = Logger.new($stdout, level: 'error') logger = Logger.new($stdout, level: :error) logger.level # => 3
С этим уровнем записи с уровнем серьезности Logger::ERROR и выше записываются, а те с более низкими уровнями серьезности не записываются:
logger = Logger.new($stdout, level: Logger::ERROR) logger.add(3) # => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil logger.add(2) # Silent.
Вы можете установить уровень журнала для существующего логгера с помощью метода level=:
logger.level = Logger::ERROR
Эти сокращенные методы также устанавливают уровень:
logger.debug! # => 0 logger.info! # => 1 logger.warn! # => 2 logger.error! # => 3 logger.fatal! # => 4
Вы можете получить уровень журнала с помощью метода level:
logger.level = Logger::ERROR logger.level # => 3
Эти методы возвращают, нужно ли писать данный уровень:
logger.level = Logger::ERROR logger.debug? # => false logger.info? # => false logger.warn? # => false logger.error? # => true logger.fatal? # => true
Вращение журнала File
По умолчанию файл журнала — это один файл, который неограниченно растет (пока не закрыт явно); вращения файлов нет.
Чтобы сохранить файлы журнала в управляемых размерах, можно использовать вращение файлов журнала, которое использует несколько файлов журнала:
-
Каждый файл журнала содержит записи за неперекрываемый временной интервал.
-
Только самый последний файл журнала открыт и активен; остальные закрыты и неактивны.
Вращение по размеру
Для вращения журнала по размеру вызовите Logger.new с:
-
Аргументом
logdevв качестве пути к файлу. -
Аргументом
shift_ageс положительным целым числом: количество файлов журнала для вращения. -
Аргументом
shift_sizeв качестве положительного целого числа: максимальный размер (в байтах) каждого файла журнала; по умолчанию 1048576 (1 мегабайт).
Примеры:
logger = Logger.new('t.log', 3) # Three 1-megabyte files.
logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files.
Для этих примеров предположим:
logger = Logger.new('t.log', 3)
Ведение журнала начинается в новом файле журнала, t.log; файл журнала «полный» и готов к вращению, когда новая запись приведет к превышению размера shift_size.
В первый раз, когда t.log заполнен:
-
t.logзакрывается и переименовывается вt.log.0. -
Открывается новый файл
t.log.
Во второй раз, когда t.log заполнен:
-
+t.log.0 переименовывается в
t.log.1. -
t.logзакрывается и переименовывается вt.log.0. -
Открывается новый файл
t.log.
Каждый последующий раз, когда t.log заполнен, файлы журнала вращаются:
-
t.log.1удаляется. -
+t.log.0 переименовывается в
t.log.1. -
t.logзакрывается и переименовывается вt.log.0. -
Открывается новый файл
t.log.
Периодическое вращение
Для периодического вращения вызовите Logger.new с:
-
Аргументом
logdevв качестве пути к файлу. -
Аргументом
shift_ageв качестве строки-индикатора периода.
Примеры:
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.
Пример:
logger = Logger.new('t.log', 'daily')
Когда истекает указанный период:
-
Базовый файл журнала,
t.logзакрывается и переименовывается с датой-базированным суффиксом, таким какt.log.20220509. -
Открывается новый файл журнала
t.log. -
Ничего не удаляется.
Формат суффикса по умолчанию — '%Y%m%d', который создаёт суффикс, аналогичный приведенному выше. Вы можете установить другой формат с помощью опции создания времени shift_period_suffix; см. детали и рекомендации в Time#strftime.
Константы
- ProgName
- SEV_LABEL
-
Метка уровня серьезности для логирования (макс. 5 символов).
- VERSION
Атрибуты
Устанавливает или извлекает процедуру форматирования записи логгера.
Когда formatter равно nil, логгер использует Logger::Formatter.
Когда formatter является процедурой, новая запись форматируется этой процедурой, которая вызывается с четырьмя аргументами:
-
severity: Уровень серьезности записи. -
time: ОбъектTime, представляющий временную метку записи. -
progname: Имя программы для записи. -
msg: Сообщение для записи (строка или объект, преобразуемый в строку).
Процедура должна вернуть строку, содержащую отформатированную запись.
Этот пользовательский форматировщик использует String#dump для экранирования строки сообщения:
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\\\"")
Вывод:
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\\\""
Пороговый уровень серьезности логирования (например, Logger::INFO).
Имя программы, которое нужно включить в сообщения журнала.
Пороговый уровень серьезности логирования (например, Logger::INFO).
Методы публичного класса
# File lib/logger.rb, line 577
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')
self.level = level
self.progname = progname
@default_formatter = Formatter.new
self.datetime_format = datetime_format
self.formatter = formatter
@logdev = nil
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)
end
end При использовании единственного аргумента logdev, возвращает новый логгер со всеми значениями по умолчанию:
Logger.new('t.log') # => #<Logger:0x000001e685dc6ac8>
Аргумент logdev должен быть одним из:
-
Путь к файлу в виде строки: записи будут записываться в файл по этому пути; если файл по этому пути существует, новые записи будут добавлены.
-
Поток
IO(обычно +$stdout+, +$stderr+ или открытый файл): записи будут записываться в указанный поток. -
nilилиFile::NULL: записи не будут записываться.
Примеры:
Logger.new('t.log')
Logger.new($stdout)
Ключевые параметры:
-
level: устанавливает уровень журнала; значение по умолчанию — Logger::DEBUG. См. Уровень журнала:Logger.new('t.log', level: Logger::ERROR) -
progname: устанавливает имя программы по умолчанию; значение по умолчанию —nil. См. Имя программы:Logger.new('t.log', progname: 'mung') -
formatter: устанавливает форматировщик записей; значение по умолчанию —nil. См. formatter=. -
datetime_format: устанавливает формат временной метки записи; значение по умолчанию —nil. См.datetime_format=. -
binmode: устанавливает, записывать ли логгер в двоичном режиме; значение по умолчанию —false. -
shift_period_suffix: устанавливает формат суффикса имени файла для периодической ротации файла журнала; значение по умолчанию —'%Y%m%d'. См. Периодическая ротация.
Публичные методы экземпляра
# File lib/logger.rb, line 682 def <<(msg) @logdev&.write(msg) end
Записывает заданный msg в лог без форматирования; возвращает количество записанных символов или nil если устройство логирования отсутствует:
logger = Logger.new($stdout) logger << 'My message.' # => 10
Вывод:
My message.
# File lib/logger.rb, line 649
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 Создает запись в журнале, которая может быть или не быть записана в журнал в зависимости от серьезности записи и уровня журнала. См. Уровень логирования и Записи для получения подробной информации.
Примеры:
logger = Logger.new($stdout, progname: 'mung') logger.add(Logger::INFO) logger.add(Logger::ERROR, 'No good') logger.add(Logger::ERROR, 'No good', 'gnum')
Вывод:
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
Эти вспомогательные методы имеют неявную серьезность:
# File lib/logger.rb, line 729 def close @logdev&.close end
Закрывает средство логирования; возвращает nil:
logger = Logger.new('t.log')
logger.close # => nil
logger.info('foo') # Prints "log writing failed. closed stream"
Связанный метод: Logger#reopen.
# File lib/logger.rb, line 437 def datetime_format @default_formatter.datetime_format end
Возвращает формат даты и времени; см. datetime_format=.
# File lib/logger.rb, line 431 def datetime_format=(datetime_format) @default_formatter.datetime_format = datetime_format end
Устанавливает формат даты и времени.
Аргумент datetime_format должен быть одним из следующих:
-
Строка, подходящая для использования в качестве формата для метода
Time#strftime. -
nil: средство логирования использует'%Y-%m-%dT%H:%M:%S.%6N'.
# File lib/logger.rb, line 688 def debug(progname = nil, &block) add(DEBUG, nil, progname, &block) end
Эквивалентно вызову add с серьезностью Logger::DEBUG.
# File lib/logger.rb, line 486 def debug!; self.level = DEBUG; end
Устанавливает уровень логирования на Logger::DEBUG. См. Уровень логирования.
# File lib/logger.rb, line 481 def debug?; level <= DEBUG; end
Возвращает true если уровень логирования позволяет записывать записи с серьезностью Logger::DEBUG, false в противном случае. См. Уровень логирования.
# File lib/logger.rb, line 706 def error(progname = nil, &block) add(ERROR, nil, progname, &block) end
Эквивалентно вызову add с серьезностью Logger::ERROR.
# File lib/logger.rb, line 519 def error!; self.level = ERROR; end
Устанавливает уровень логирования на Logger::ERROR. См. Уровень логирования.
# File lib/logger.rb, line 514 def error?; level <= ERROR; end
Возвращает true если уровень логирования позволяет записывать записи с серьезностью Logger::ERROR, false в противном случае. См. Уровень логирования.
# File lib/logger.rb, line 712 def fatal(progname = nil, &block) add(FATAL, nil, progname, &block) end
Эквивалентно вызову add с серьезностью Logger::FATAL.
# File lib/logger.rb, line 530 def fatal!; self.level = FATAL; end
Устанавливает уровень логирования на Logger::FATAL. См. Уровень логирования.
# File lib/logger.rb, line 525 def fatal?; level <= FATAL; end
Возвращает true если уровень логирования позволяет записывать записи с серьезностью Logger::FATAL, false в противном случае. См. Уровень логирования.
# File lib/logger.rb, line 694 def info(progname = nil, &block) add(INFO, nil, progname, &block) end
Эквивалентно вызову add с серьезностью Logger::INFO.
# File lib/logger.rb, line 497 def info!; self.level = INFO; end
Устанавливает уровень логирования на Logger::INFO. См. Уровень логирования.
# File lib/logger.rb, line 492 def info?; level <= INFO; end
Возвращает true если уровень логирования позволяет записывать записи с серьезностью Logger::INFO, false в противном случае. См. Уровень логирования.
# File lib/logger.rb, line 397
def level=(severity)
if severity.is_a?(Integer)
@level = severity
else
case severity.to_s.downcase
when 'debug'
@level = DEBUG
when 'info'
@level = INFO
when 'warn'
@level = WARN
when 'error'
@level = ERROR
when 'fatal'
@level = FATAL
when 'unknown'
@level = UNKNOWN
else
raise ArgumentError, "invalid log level: #{severity}"
end
end
end Устанавливает уровень логирования; возвращает severity. См. Уровень логирования.
Аргумент severity может быть целым числом, строкой или символом:
logger.level = Logger::ERROR # => 3 logger.level = 3 # => 3 logger.level = 'error' # => "error" logger.level = :error # => :error
Logger#sev_threshold= является псевдонимом для Logger#level=.
# File lib/logger.rb, line 617 def reopen(logdev = nil) @logdev&.reopen(logdev) self end
Устанавливает поток вывода для регистрации:
-
Если
logdevявляетсяnil, повторно открывает текущий поток вывода. -
Если
logdevявляется путем к файлу, открывает указанный файл для добавления. -
Если
logdevявляется потокомIO(обычно$stdout,$stderr, или открытый объектFile), открывает поток для добавления.
Пример:
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"]
# File lib/logger.rb, line 718 def unknown(progname = nil, &block) add(UNKNOWN, nil, progname, &block) end
Эквивалентно вызову add с уровнем серьезности Logger::UNKNOWN.
# File lib/logger.rb, line 700 def warn(progname = nil, &block) add(WARN, nil, progname, &block) end
Эквивалентно вызову add с уровнем серьезности Logger::WARN.
# File lib/logger.rb, line 508 def warn!; self.level = WARN; end
Устанавливает уровень регистрации в Logger::WARN. См. Уровень лога.
# File lib/logger.rb, line 503 def warn?; level <= WARN; end
Возвращает true, если уровень регистрации разрешает записи с уровнем серьезности Logger::WARN, false в противном случае. См. Уровень лога.
Приватные методы экземпляра
# File lib/logger.rb, line 742 def format_message(severity, datetime, progname, msg) (@formatter || @default_formatter).call(severity, datetime, progname, msg) end
# File lib/logger.rb, line 738 def format_severity(severity) SEV_LABEL[severity] || 'ANY' end
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.