Spec-Zone.ru › Ruby 3.3

класс Logger

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

Класс 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 идентификатор.

  • Уровень важности (слово).

  • Имя программы.

  • Сообщение.

Вы можете использовать другой формат записи, выполнив:

  • Установка пользовательского формата (влияет на последующие записи); см. 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[RW]

Устанавливает или получает процедуру форматирования записи журнала.

Когда 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\\\""
progname[RW]

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

Методы публичного класса

new(logdev, shift_age = 0, shift_size = 1048576, **options) Показать исходный код
# File lib/logger.rb, line 578
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
  @level_override = {}
  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'. См. Периодическая ротация.

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

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

Записывает заданное msg в лог без форматирования; возвращает количество записанных символов или nil если устройство логирования отсутствует:

logger = Logger.new($stdout)
logger << 'My message.' # => 10

Вывод:

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

Эти вспомогательные методы имеют неявную серьезность:

  • debug.

  • info.

  • warn.

  • error.

  • fatal.

  • unknown.

Также является псевдонимом для: log
close() Показать исходный код
# File lib/logger.rb, line 731
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.

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

Возвращает формат даты и времени; см. datetime_format=.

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

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

Аргумент datetime_format должен быть одним из следующих:

  • Строка, подходящая для использования в качестве формата для метода Time#strftime.

  • nil: регистратор использует '%Y-%m-%dT%H:%M:%S.%6N'.

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

Эквивалентно вызову add с уровнем серьезности Logger::DEBUG.

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

Устанавливает уровень журнала на Logger::DEBUG. См. Уровень журнала.

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

Возвращает true если уровень журнала допускает запись записей с уровнем серьезности Logger::DEBUG, false в противном случае. См. Уровень журнала.

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

Эквивалентно вызову add с уровнем серьезности Logger::ERROR.

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

Устанавливает уровень журнала на Logger::ERROR. См. Уровень журнала.

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

Возвращает true если уровень журнала допускает запись записей с уровнем серьезности Logger::ERROR, false в противном случае. См. Уровень журнала.

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

Эквивалентно вызову add с уровнем серьезности Logger::FATAL.

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

Устанавливает уровень журнала на Logger::FATAL. См. Уровень журнала.

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

Возвращает true если уровень журнала допускает запись записей с уровнем серьезности Logger::FATAL, false в противном случае. См. Уровень журнала.

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

Эквивалентно вызову add с уровнем серьезности Logger::INFO.

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

Устанавливает уровень журнала на Logger::INFO. См. Уровень журнала.

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

Возвращает true если уровень журнала допускает запись записей с уровнем серьезности Logger::INFO, false в противном случае. См. Уровень журнала.

level() Показать исходный код
# File lib/logger.rb, line 383
def level
  @level_override[Fiber.current] || @level
end

Пороговое значение серьезности регистрации (например, Logger::INFO).

Также является псевдонимом для: sev_threshold
level=(severity) Показать исходный код
# File lib/logger.rb, line 399
def level=(severity)
  @level = Severity.coerce(severity)
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=.

Также является псевдонимом для: sev_threshold=
log(severity, message = nil, progname = nil)
Alias for: add
reopen(logdev = nil) Показать исходный код
# File lib/logger.rb, line 619
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"]
sev_threshold()
Alias for: level
sev_threshold=(severity)
Alias for: level=
unknown(progname = nil, &block) Показать исходный код
# File lib/logger.rb, line 720
def unknown(progname = nil, &block)
  add(UNKNOWN, nil, progname, &block)
end

Эквивалентно вызову add с уровнем серьезности Logger::UNKNOWN.

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

Эквивалентно вызову add с уровнем серьезности Logger::WARN.

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

Устанавливает уровень журнала на Logger::WARN. Смотрите Уровень журнала.

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

Возвращает true если уровень журнала позволяет записывать записи с уровнем серьезности Logger::WARN, false в противном случае. Смотрите Уровень журнала.

with_level(severity) { || ... } Показать исходный код
# File lib/logger.rb, line 408
def with_level(severity)
  prev, @level_override[Fiber.current] = level, Severity.coerce(severity)
  begin
    yield
  ensure
    if prev
      @level_override[Fiber.current] = prev
    else
      @level_override.delete(Fiber.current)
    end
  end
end

Изменяет уровень журнала во время выполнения блока только для текущего Fiber

logger.with_level(:debug) do
  logger.debug { "Hello" }
end

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

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

Spec-Zone.ru

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