класс 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 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
-
SymbolилиString(регистр не учитывается)logger.level = :info logger.level = 'INFO' # :debug < :info < :warn < :error < :fatal < :unknown
-
Конструктор
Logger.new(logdev, level: Logger::INFO) Logger.new(logdev, level: :info) Logger.new(logdev, level: 'INFO')
Формат
Лог-сообщения по умолчанию отображаются в выходном потоке в определенном формате. Ниже показан стандартный формат и пример:
Формат лога:
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"
или через конструктор.
Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
Или вы можете изменить общий формат через метод formatter=.
logger.formatter = proc do |severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"
end
# e.g. "2005-09-22 08:51:08 +0900: hello world"
или через конструктор.
Logger.new(logdev, formatter: proc {|severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"
})
Константы
- ИмяПрограммы
- МеткаУровняСерьезности
-
Метка уровня серьезности для ведения журнала (максимум 5 символов).
Атрибуты
Форматировщик логов, как Proc, который принимает четыре аргумента и возвращает отформатированное сообщение. Аргументами являются:
-
severity -
Уровень серьезности лог-сообщения.
-
time -
Объект
Time, представляющий время регистрации сообщения. -
progname -
Настроенное
prognameили переданное в метод логгера. -
msg -
Объект, переданный пользователем в лог-сообщение; необязательно
String.
Блок должен возвращать Object, который может быть записан в устройство ведения журнала через write. По умолчанию используется форматировщик, если он не задан.
Порог серьезности ведения журнала (например, Logger::INFO).
Имя программы, которое следует включать в лог-сообщения.
Порог серьезности ведения журнала (например, Logger::INFO).
Методы открытого класса
# File lib/logger.rb, line 379
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 = LogDevice.new(logdev, shift_age: shift_age,
shift_size: shift_size,
shift_period_suffix: shift_period_suffix,
binmode: binmode)
end
end Аргументы
-
logdev -
Устройство ведения журнала. Это имя файла (
String) или объектIO(обычноSTDOUT,STDERR, или открытый файл). -
shift_age -
Количество старых лог-файлов для сохранения или частота ротации (
daily,weeklyилиmonthly). Значение по умолчанию — 0, что отключает ротацию лог-файлов. -
shift_size -
Максимальный размер лог-файла в байтах (применимо только когда
shift_age— положительноеInteger). Значение по умолчанию —1048576(1 МБ). -
level -
Порог серьезности ведения журнала. Значение по умолчанию — Logger::DEBUG.
-
progname -
Имя программы для включения в лог-сообщения. Значение по умолчанию — null.
-
formatter -
Форматировщик логов. Значение по умолчанию — экземпляр Logger::Formatter.
-
datetime_format -
Формат даты и времени
Date. Значение по умолчанию — '%Y-%m-%d %H:%M:%S'. -
binmode -
Использовать двоичный режим для устройства ведения журнала. Значение по умолчанию — false.
-
shift_period_suffix -
Формат суффикса лог-файла для ротации
daily,weeklyилиmonthly. Значение по умолчанию — '%Y%m%d'.
Описание
Создать экземпляр.
Публичные методы экземпляра
# File lib/logger.rb, line 484 def <<(msg) @logdev&.write(msg) end
Выгружает заданное сообщение в устройство регистрации без форматирования. Если устройство регистрации отсутствует, возвращает nil.
# File lib/logger.rb, line 458
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 Аргументы
-
severity -
Серьезность. Константы определены в пространстве имен
Logger:DEBUG,INFO,WARN,ERROR,FATAL, илиUNKNOWN. -
message -
progname -
Строка имени программы. Может быть опущена. Рассматривается как сообщение, если не заданы
messageиblock. -
block -
Может быть опущено. Вызывается для получения строки сообщения, если
messageимеет значение nil.
Возвращаемое значение
Когда заданная серьезность недостаточно высока (для этого конкретного регистратора), не регистрируется сообщение, и возвращается true.
Описание
Регистрирует сообщение, если заданная серьезность достаточно высока. Это универсальный метод регистрации. Пользователи будут чаще использовать debug, info, warn, error, и fatal.
Формат сообщения: message может быть любым объектом, но он должен быть преобразован в String, чтобы его можно было зарегистрировать. Как правило, используется inspect, если заданный объект не является String. Специальным случаем является объект Exception, который будет напечатан подробно, включая сообщение, класс и трассировку стека. См. msg2str для реализации, если необходимо.
Ошибки
-
Файл журнала не заблокирован.
-
Открытие в режиме добавления не требует блокировки файла.
-
Если ОС поддерживает многопоточный ввод-вывод, записи могут быть перемешаны.
# File lib/logger.rb, line 571 def close @logdev&.close end
Закрывает устройство регистрации.
# File lib/logger.rb, line 284 def datetime_format @default_formatter.datetime_format end
Возвращает используемый формат даты. См. datetime_format=
# File lib/logger.rb, line 279 def datetime_format=(datetime_format) @default_formatter.datetime_format = datetime_format end
Set формат даты и времени.
-
datetime_format -
Строка, подходящая для передачи в
strftime.
# File lib/logger.rb, line 493 def debug(progname = nil, &block) add(DEBUG, nil, progname, &block) end
Регистрирует сообщение DEBUG.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 310 def debug!; self.level = DEBUG; end
Устанавливает серьезность в DEBUG.
# File lib/logger.rb, line 307 def debug?; level <= DEBUG; end
Возвращает true, если текущий уровень серьезности позволяет печатать сообщения DEBUG.
# File lib/logger.rb, line 545 def error(progname = nil, &block) add(ERROR, nil, progname, &block) end
Регистрирует сообщение ERROR.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 331 def error!; self.level = ERROR; end
Устанавливает серьезность в ERROR.
# File lib/logger.rb, line 328 def error?; level <= ERROR; end
Возвращает true, если текущий уровень серьезности позволяет печатать сообщения ERROR.
# File lib/logger.rb, line 554 def fatal(progname = nil, &block) add(FATAL, nil, progname, &block) end
Регистрирует сообщение FATAL.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 338 def fatal!; self.level = FATAL; end
Устанавливает серьезность в FATAL.
# File lib/logger.rb, line 335 def fatal?; level <= FATAL; end
Возвращает true, если текущий уровень серьезности позволяет печатать сообщения FATAL.
# File lib/logger.rb, line 527 def info(progname = nil, &block) add(INFO, nil, progname, &block) end
Регистрирует сообщение INFO.
-
message -
Сообщение для регистрации; не обязательно должно быть
String. -
progname -
В форме блока это
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 317 def info!; self.level = INFO; end
Устанавливает серьезность в INFO.
# File lib/logger.rb, line 314 def info?; level <= INFO; end
Возвращает true, если текущий уровень серьезности позволяет печатать сообщения INFO.
# File lib/logger.rb, line 250
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 -
Уровень серьезности сообщения журнала.
# File lib/logger.rb, line 412 def reopen(logdev = nil) @logdev.reopen(logdev) self end
Аргументы
-
logdev -
Устройство протоколирования. Это имя файла (
String) или объектIO(обычноSTDOUT,STDERR, или открытый файл). Переоткрывает тот же файл, если онnil, ничего не делает дляIO. По умолчаниюnil.
Описание
Переоткрывает устройство протоколирования.
# File lib/logger.rb, line 564 def unknown(progname = nil, &block) add(UNKNOWN, nil, progname, &block) end
Протоколирует сообщение UNKNOWN. Это сообщение будет выведено независимо от уровня журнала.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 536 def warn(progname = nil, &block) add(WARN, nil, progname, &block) end
Протоколирует сообщение WARN.
См. info для получения дополнительной информации.
# File lib/logger.rb, line 324 def warn!; self.level = WARN; end
Устанавливает уровень серьезности в WARN.
# File lib/logger.rb, line 321 def warn?; level <= WARN; end
Возвращает true, если текущий уровень серьезности позволяет выводить сообщения WARN.
Приватные методы экземпляра
# File lib/logger.rb, line 584 def format_message(severity, datetime, progname, msg) (@formatter || @default_formatter).call(severity, datetime, progname, msg) end
# File lib/logger.rb, line 580 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.