класс Logger
Описание
Класс Logger предоставляет простую, но сложную утилиту для ведения журнала, которую вы можете использовать для вывода сообщений.
Сообщения имеют связанные уровни, такие как INFO или ERROR, которые указывают на их важность. Затем вы можете задать уровень Logger, и будут выводиться только сообщения на этом уровне или выше.
Уровни:
-
UNKNOWN -
Неизвестное сообщение, которое всегда должно быть записано в журнал.
-
FATAL -
Необрабатываемая ошибка, которая приводит к аварийному завершению программы.
-
ERROR -
Обрабатываемое условие ошибки.
-
WARN -
Предупреждение.
-
INFO -
Общая (полезная) информация об операциях системы.
-
DEBUG -
Информация низкого уровня для разработчиков.
Например, в производственной системе вы можете установить ваш Logger на INFO или даже WARN. Однако при разработке системы, вероятно, вы захотите знать о внутреннем состоянии программы и установите Logger на DEBUG.
Примечание: Logger не экранирует и не очищает любые сообщения, передаваемые ему. Разработчики должны быть осведомлены о том, когда потенциально вредоносные данные (ввод пользователя) передаются Logger, и вручную экранировать недоверенные данные:
logger.info("User-input: #{input.dump}")
logger.info("User-input: %p" % input)
Вы можете использовать formatter= для экранирования всех данных.
original_formatter = Logger::Formatter.new
logger.formatter = proc { |severity, datetime, progname, msg|
original_formatter.call(severity, datetime, progname, msg.dump)
}
logger.info(input)
Пример
Это создаёт Logger, который выводит данные в стандартный поток вывода со значением уровня WARN:
require 'logger'
logger = Logger.new(STDOUT)
logger.level = Logger::WARN
logger.debug("Created logger")
logger.info("Program started")
logger.warn("Nothing to do!")
path = "a_non_existent_file"
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
Поскольку уровень Logger установлен на WARN, записываются только предупреждения, ошибки и фатальные сообщения. Сообщения отладки и информационные сообщения игнорируются.
Функции
У Logger есть несколько интересных функций, таких как автоматическое переименование файлов журнала, установка формата сообщений журнала и указание имени программы в сочетании с сообщением. Следующий раздел покажет, как этого добиться.
Руководства
Как создать логгер
Нижеприведенные параметры предлагают различные варианты, в большей или меньшей степени возрастающей сложности.
-
Создайте логгер, который записывает сообщения в STDERR/STDOUT.
logger = Logger.new(STDERR) logger = Logger.new(STDOUT)
-
Создайте логгер для файла, у которого есть указанное имя.
logger = Logger.new('logfile.log') -
Создайте логгер для указанного файла.
file = File.open('foo.log', File::WRONLY | File::APPEND) # To create new (and to remove old) logfile, add File::CREAT like: # file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT) logger = Logger.new(file) -
Создайте логгер, который обновляет файл журнала, когда он достигает определенного размера. Оставьте 10 "старых" файлов журнала, где каждый файл составляет около 1 024 000 байт.
logger = Logger.new('foo.log', 10, 1024000) -
Создайте логгер, который обновляет файл журнала ежедневно/еженедельно/ежемесячно.
logger = Logger.new('foo.log', 'daily') logger = Logger.new('foo.log', 'weekly') logger = Logger.new('foo.log', 'monthly')
Как записать сообщение в журнал
Обратите внимание на разные методы (fatal, error, info ), используемые для записи сообщений различных уровней? Другими методами в этой группе являются warn и debug. add используется ниже для записи сообщения произвольного (возможно, динамического) уровня.
-
Сообщение в блоке.
logger.fatal { "Argument 'foo' not given." } -
Сообщение в виде строки.
logger.error "Argument #{@foo} mismatch." -
С именем программы.
logger.info('initialize') { "Initializing..." } -
С уровнем важности.
logger.add(Logger::FATAL) { 'Fatal error!' }
Формат с блоком позволяет создавать потенциально сложные сообщения журнала, но откладывать их оценку до тех пор, пока сообщение не будет записано. Например, если у нас есть следующее:
logger.debug { "This is a " + potentially + " expensive operation" }
Если уровень логгера INFO или выше, сообщения отладки не будут записываться, и весь блок даже не будет оцениваться. Сравните со следующим:
logger.debug("This is a " + potentially + " expensive operation")
Здесь конкатенация строк выполняется каждый раз, даже если уровень журнала не настроен на отображение сообщения отладки.
Как закрыть логгер
logger.close
Установка порогового значения уровня важности
-
Оригинальный интерфейс.
logger.sev_threshold = Logger::WARN
-
Интерфейс, совместимый с Log4r (в некоторой степени).
logger.level = Logger::INFO # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
-
Символ или строка (регистр не учитывается)
logger.level = :info logger.level = 'INFO' # :debug < :info < :warn < :error < :fatal < :unknown
Формат
Сообщения журнала отображаются в потоке вывода в определенном формате по умолчанию. Ниже приведен стандартный формат и пример:
Формат журнала:
SeverityID, [DateTime #pid] SeverityLabel -- ProgName: message
Пример журнала:
I, [1999-03-03T02:34:24.895701 #19074] INFO -- Main: info.
Вы можете изменить формат даты и времени с помощью datetime_format=.
logger.datetime_format = '%Y-%m-%d %H:%M:%S'
# e.g. "2004-01-03 00:54:26"
Или вы можете изменить общий формат с помощью метода formatter=.
logger.formatter = proc do |severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"
end
# e.g. "2005-09-22 08:51:08 +0900: hello world"
Константы
- ProgName
- SEV_LABEL
-
Метка Severity для ведения журнала (максимум 5 символов).
- VERSION
Атрибуты
Форматировщик журнала, как Proc , который примет четыре аргумента и вернёт отформатированное сообщение. Аргументы:
-
severity -
Severity сообщения журнала.
-
time -
Экземпляр Time, представляющий время записи сообщения.
-
progname -
Настроенное progname или переданное в метод логгера.
-
msg -
Объект, переданный пользователем в сообщение журнала; необязательно строка.
Блок должен возвращать Объект, который может быть записан в устройство ведения журнала с помощью write. Форматировщик по умолчанию используется, если форматировщик не задан.
Пороговое значение уровня важности для ведения журнала (например, Logger::INFO).
Имя программы для включения в сообщения журнала.
Пороговое значение уровня важности для ведения журнала (например, Logger::INFO).
Методы открытого класса
# File lib/logger.rb, line 346
def initialize(logdev, shift_age = 0, shift_size = 1048576)
@progname = nil
@level = DEBUG
@default_formatter = Formatter.new
@formatter = nil
@logdev = nil
if logdev
@logdev = LogDevice.new(logdev, :shift_age => shift_age,
:shift_size => shift_size)
end
end Аргументы
-
logdev -
Устройство журнала. Это имя файла (строка) или объект IO (обычно
STDOUT,STDERR, или открытый файл). -
shift_age -
Количество старых файлов журнала, которые нужно сохранить, или частота обновления (
daily,weeklyилиmonthly). -
shift_size -
Максимальный размер файла журнала (применимо только когда
shift_ageявляется числом).
Описание
Создать экземпляр.
Открытые методы экземпляров
# File lib/logger.rb, line 443
def <<(msg)
unless @logdev.nil?
@logdev.write(msg)
end
end Выводит заданное сообщение в устройство регистрации без форматирования. Если устройство регистрации не существует, возвращает nil.
# File lib/logger.rb, line 419
def add(severity, message = nil, progname = nil)
severity ||= UNKNOWN
if @logdev.nil? or severity < @level
return true
end
progname ||= @progname
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 Аргументы
-
severity -
Уровень важности. Константы определены в пространстве имён Logger:
DEBUG,INFO,WARN,ERROR,FATAL, илиUNKNOWN. -
message -
Сообщение регистрации. Строка или Исключение.
-
progname -
Имя программы. Может быть опущено. Будет обработано как сообщение, если не указаны
messageиblock. -
block -
Может быть опущено. Вызывается для получения строки сообщения, если
messageравно null.
Возвращаемое значение
Если заданный уровень важности недостаточно высок (для данного регистратора), сообщение не регистрируется, и возвращается true.
Описание
Записывает сообщение, если заданный уровень важности достаточно высок. Это общий метод регистрации. Пользователи скорее всего будут использовать debug, info, warn, error и fatal.
Формат сообщения: message может быть любым объектом, но должен быть преобразован в строку для записи. В общем случае, inspect используется, если заданный объект не является строкой. Специальный случай — объект Exception , который будет напечатан подробно, включая сообщение, класс и трассировку стека. Для реализации см. msg2str, если необходимо.
Ошибки
-
Файл регистрации не блокируется.
-
Открытие с дописыванием не требует блокировки файла.
-
Если ОС поддерживает многочисленные ввода-выводы, записи могут быть смешаны.
# File lib/logger.rb, line 532 def close @logdev.close if @logdev end
Закрывает устройство регистрации.
# File lib/logger.rb, line 285 def datetime_format @default_formatter.datetime_format end
Возвращает используемый формат даты. См. datetime_format=
# File lib/logger.rb, line 280 def datetime_format=(datetime_format) @default_formatter.datetime_format = datetime_format end
Устанавливает формат даты и времени.
-
datetime_format -
Строка, подходящая для передачи в
strftime.
# File lib/logger.rb, line 454 def debug(progname = nil, &block) add(DEBUG, nil, progname, &block) end
Записывает сообщение уровня отладки.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 308 def debug?; @level <= DEBUG; end
Возвращает true если текущий уровень важности позволяет отображать сообщения отладки.
# File lib/logger.rb, line 506 def error(progname = nil, &block) add(ERROR, nil, progname, &block) end
Записывает сообщение об ошибке.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 320 def error?; @level <= ERROR; end
Возвращает true если текущий уровень важности позволяет отображать сообщения об ошибках.
# File lib/logger.rb, line 515 def fatal(progname = nil, &block) add(FATAL, nil, progname, &block) end
Записывает сообщение о критической ошибке.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 324 def fatal?; @level <= FATAL; end
Возвращает true если текущий уровень важности позволяет отображать сообщения о критических ошибках.
# File lib/logger.rb, line 488 def info(progname = nil, &block) add(INFO, nil, progname, &block) end
Записывает информационное сообщение.
-
message -
Сообщение для регистрации; не обязательно строка.
-
progname -
В форме блока, это имя программы для использования в сообщении регистрации. Значение по умолчанию может быть установлено с помощью progname=.
-
block -
Вычисляется в сообщение для регистрации. Оно не вычисляется, если уровень регистратора недостаточен для записи сообщения. Это позволяет создавать потенциально дорогостоящие сообщения регистрации, которые вызываются только тогда, когда конфигурация регистратора настроена на их отображение.
Примеры
logger.info("MainApp") { "Received connection from #{ip}" }
# ...
logger.info "Waiting for input from user"
# ...
logger.info { "User typed #{input}" }
Скорее всего, вы будете придерживаться второй формы выше, если не хотите указывать имя программы (которое вы также можете сделать с помощью progname=).
Возвращаемое значение
См. add.
# File lib/logger.rb, line 312 def info?; @level <= INFO; end
Возвращает true если текущий уровень важности позволяет отображать информационные сообщения.
# File lib/logger.rb, line 250
def level=(severity)
if severity.is_a?(Integer)
@level = severity
else
_severity = severity.to_s.downcase
case _severity
when 'debug'.freeze
@level = DEBUG
when 'info'.freeze
@level = INFO
when 'warn'.freeze
@level = WARN
when 'error'.freeze
@level = ERROR
when 'fatal'.freeze
@level = FATAL
when 'unknown'.freeze
@level = UNKNOWN
else
raise ArgumentError, "invalid log level: #{severity}"
end
end
end Устанавливает порог уровня важности регистрации.
-
severity -
Уровень важности сообщения регистрации.
# File lib/logger.rb, line 373 def reopen(logdev = nil) @logdev.reopen(logdev) self end
Аргументы
-
logdev -
Устройство регистрации. Это имя файла (строка) или объект IO (обычно
STDOUT,STDERR, или открытый файл).
Описание
Переоткрывает устройство регистрации.
# File lib/logger.rb, line 525 def unknown(progname = nil, &block) add(UNKNOWN, nil, progname, &block) end
Записать UNKNOWN сообщение. Оно будет выведено независимо от уровня логирования.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 497 def warn(progname = nil, &block) add(WARN, nil, progname, &block) end
Записать сообщение WARN.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 316 def warn?; @level <= WARN; end
Возвращает true, если текущий уровень серьезности позволяет выводить сообщения WARN.
Приватные методы экземпляра
# File lib/logger.rb, line 545 def format_message(severity, datetime, progname, msg) (@formatter || @default_formatter).call(severity, datetime, progname, msg) end
# File lib/logger.rb, line 541 def format_severity(severity) SEV_LABEL[severity] || 'ANY' end
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.