Spec-Zone.ru › Ruby 2.2

класс Logger

Родитель:
Объект
Включенные модули:
Logger::Severity

Описание

Класс 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 есть несколько интересных функций, таких как автоматическое переключение файлов журнала, установка формата сообщений журнала и указание имени программы в сочетании с сообщением. Следующий раздел покажет, как этого добиться.

Руководства

Как создать Logger

Ниже приведены варианты, от менее сложных к более сложным.

  1. Создайте Logger, который записывает сообщения в STDERR/STDOUT.

    logger = Logger.new(STDERR)
    logger = Logger.new(STDOUT)
    
  2. Создайте Logger для файла с указанным именем.

    logger = Logger.new('logfile.log')
    
  3. Создайте Logger для указанного файла.

    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)
    
  4. Создайте Logger, который переключает файл журнала после достижения определенного размера. Оставьте 10 «старых» файлов журнала, где каждый файл примерно 1 024 000 байтов.

    logger = Logger.new('foo.log', 10, 1024000)
    
  5. Создайте Logger, который переключает файл журнала ежедневно/еженедельно/ежемесячно.

    logger = Logger.new('foo.log', 'daily')
    logger = Logger.new('foo.log', 'weekly')
    logger = Logger.new('foo.log', 'monthly')
    

Как записать сообщение в журнал

Обратите внимание на различные методы (fatal, error, info) которые используются для записи сообщений разных уровней? Другие методы этой семьи - warn и debug. add используется ниже для записи сообщения произвольного (возможно, динамического) уровня.

  1. Сообщение в блоке.

    logger.fatal { "Argument 'foo' not given." }
    
  2. Сообщение в виде строки.

    logger.error "Argument #{@foo} mismatch."
    
  3. С progname.

    logger.info('initialize') { "Initializing..." }
    
  4. С severity.

    logger.add(Logger::FATAL) { 'Fatal error!' }
    

Форма блока позволяет создавать потенциально сложные сообщения журнала, но откладывать их оценку до тех пор, пока сообщение не будет записано. Например, если у нас есть следующее:

logger.debug { "This is a " + potentially + " expensive operation" }

Если уровень Logger установлен на INFO или выше, сообщения отладки не будут записаны, и весь блок даже не будет оценен. Сравните с этим:

logger.debug("This is a " + potentially + " expensive operation")

Здесь конкатенация строк выполняется каждый раз, даже если уровень журнала не настроен на отображение сообщения отладки.

Как закрыть Logger

logger.close

Установка порога серьезности

  1. Оригинальный интерфейс.

    logger.sev_threshold = Logger::WARN
    
  2. Интерфейс, совместимый с Log4r (частично).

    logger.level = Logger::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

Атрибуты

formatter[RW]

Форматировщик журнала, как Proc который принимает четыре аргумента и возвращает отформатированное сообщение. Аргументы:

severity

Severity сообщения журнала.

time

Экземпляр Time, представляющий время записи сообщения.

progname

Настроенное имя программы progname, или переданное в метод Logger.

msg

Объект, переданный пользователем в сообщение журнала; не обязательно строка.

Блок должен возвращать Объект, который может быть записан в устройство ведения журнала с помощью write. Используется форматировщик по умолчанию, если форматировщик не задан.

level[RW]

Пороговый уровень серьезности ведения журнала (например, Logger::INFO).

progname[RW]

Имя программы, которое следует включить в сообщения журнала.

sev_threshold[RW]

Пороговый уровень серьезности ведения журнала (например, Logger::INFO).

sev_threshold=[RW]

Пороговый уровень серьезности ведения журнала (например, Logger::INFO).

Публичные методы класса

new(logdev, shift_age = 7, shift_size = 1048576) Показать исходный код
new(logdev, shift_age = 'weekly')
# File lib/logger.rb, line 311
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 — число).

Описание

Создать экземпляр.

Открытые методы экземпляра

<<(msg) Показать исходный код
# File lib/logger.rb, line 388
def <<(msg)
  unless @logdev.nil?
    @logdev.write(msg)
  end
end

Выгрузить заданное сообщение в лог-устройство без форматирования. Если лог-устройство не существует, вернуть nil.

Logger#add(severity, message = nil, progname = nil) { ... } Показать исходный код
# File lib/logger.rb, line 364
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

Severity. Константы определены в пространстве имен Logger: DEBUG, INFO, WARN, ERROR, FATAL, или UNKNOWN.

message

Сообщение для лога. Строка или Exception.

progname

Строка с именем программы. Может быть опущена. Рассматривается как сообщение, если не заданы message и block.

block

Может быть опущена. Вызывается для получения строки сообщения, если message равно nil.

Возвращаемое значение

Если заданный уровень серьезности недостаточно высок (для этого конкретного логгера), сообщение не записывается в лог, и возвращается true.

Описание

Записать сообщение в лог, если заданный уровень серьезности достаточно высок. Это универсальный метод ведения журнала. Пользователи будут чаще использовать debug, info, warn, error, и fatal.

Формат сообщения: message может быть любым объектом, но он должен быть преобразован в строку для записи в лог. Как правило, используется inspect, если заданный объект не является строкой. Специальный случай — объект Exception, который будет напечатан подробно, включая сообщение, класс и трассировку стека. См. msg2str для реализации, если необходимо.

Ошибки

  • Файл журнала не заблокирован.

  • Добавление открытого файла не требует блокировки файла.

  • Если ОС поддерживает многопоточный ввод/вывод, записи могут быть перемешаны.

Также известен как: log
close() Показать исходный код
# File lib/logger.rb, line 477
def close
  @logdev.close if @logdev
end

Закрыть устройство ведения журнала.

datetime_format() Показать исходный код
# File lib/logger.rb, line 250
def datetime_format
  @default_formatter.datetime_format
end

Возвращает используемый формат даты. См. datetime_format=

datetime_format=(datetime_format) Показать исходный код
# File lib/logger.rb, line 245
def datetime_format=(datetime_format)
  @default_formatter.datetime_format = datetime_format
end

Установить формат даты и времени.

datetime_format

Строка, подходящая для передачи в strftime.

debug(progname = nil, &block) Показать исходный код
# File lib/logger.rb, line 399
def debug(progname = nil, &block)
  add(DEBUG, nil, progname, &block)
end

Записать DEBUG сообщение.

См. info для получения дополнительной информации.

debug?() Показать исходный код
# File lib/logger.rb, line 273
def debug?; @level <= DEBUG; end

Возвращает true, если текущий уровень серьезности позволяет печатать DEBUG сообщения.

error(progname = nil, &block) Показать исходный код
# File lib/logger.rb, line 451
def error(progname = nil, &block)
  add(ERROR, nil, progname, &block)
end

Записать ERROR сообщение.

См. info для получения дополнительной информации.

error?() Показать исходный код
# File lib/logger.rb, line 285
def error?; @level <= ERROR; end

Возвращает true, если текущий уровень серьезности позволяет печатать ERROR сообщения.

fatal(progname = nil, &block) Показать исходный код
# File lib/logger.rb, line 460
def fatal(progname = nil, &block)
  add(FATAL, nil, progname, &block)
end

Записать FATAL сообщение.

См. info для получения дополнительной информации.

fatal?() Показать исходный код
# File lib/logger.rb, line 289
def fatal?; @level <= FATAL; end

Возвращает true, если текущий уровень серьезности позволяет печатать FATAL сообщения.

info(message) Показать исходный код
info(progname, &block)
# File lib/logger.rb, line 433
def info(progname = nil, &block)
  add(INFO, nil, progname, &block)
end

Записать INFO сообщение.

message

Сообщение для лога; не обязательно должно быть строкой.

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.

info?() Показать исходный код
# File lib/logger.rb, line 277
def info?; @level <= INFO; end

Возвращает true, если текущий уровень серьезности позволяет печатать INFO сообщения.

log(severity, message = nil, progname = nil)
Псевдоним для: add
unknown(progname = nil, &block) Показать исходный код
# File lib/logger.rb, line 470
def unknown(progname = nil, &block)
  add(UNKNOWN, nil, progname, &block)
end

Записать UNKNOWN сообщение. Оно будет напечатано независимо от уровня логгера.

См. info для получения дополнительной информации.

warn(progname = nil, &block) Показать исходный код
# File lib/logger.rb, line 442
def warn(progname = nil, &block)
  add(WARN, nil, progname, &block)
end

Записать WARN сообщение.

См. info для получения дополнительной информации.

warn?() Показать исходный код
# File lib/logger.rb, line 281
def warn?; @level <= WARN; end

Возвращает true, если текущий уровень серьезности позволяет печатать WARN сообщения.

Приватные методы экземпляра

format_message(severity, datetime, progname, msg) Показать исходный код
# File lib/logger.rb, line 490
def format_message(severity, datetime, progname, msg)
  (@formatter || @default_formatter).call(severity, datetime, progname, msg)
end
format_severity(severity) Показать исходный код
# File lib/logger.rb, line 486
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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API