Spec-Zone.ru › Ruby 3.4

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

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

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

  • Сообщение.

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

  • Установите пользовательский формат 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 [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 581
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',
               reraise_write_errors: [])
  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,
      reraise_write_errors: reraise_write_errors)
  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'. См. Периодическая ротация.

  • reraise_write_errors: Массив классов исключений, которые будут повторно подняты, если при записи в устройство лога произойдет ошибка. По умолчанию все исключения игнорируются.

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

<< (msg)
Исходный код
# File lib/logger.rb, line 689
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 656
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 736
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 695
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 713
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 719
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 701
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[level_key] || @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)
Псевдоним для: add
reopen (logdev = nil)
Исходный код
# File lib/logger.rb, line 624
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 ()
Псевдоним для: level
sev_threshold= (severity)
Псевдоним для: level=
unknown (progname = nil, &block)
Исходный код
# File lib/logger.rb, line 725
def unknown(progname = nil, &block)
  add(UNKNOWN, nil, progname, &block)
end

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

warn (progname = nil, &block)
Исходный код
# File lib/logger.rb, line 707
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[level_key] = level, Severity.coerce(severity)
  begin
    yield
  ensure
    if prev
      level_override[level_key] = prev
    else
      level_override.delete(level_key)
    end
  end
end

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

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

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

format_message (severity, datetime, progname, msg)
Исходный код
# File lib/logger.rb, line 758
def format_message(severity, datetime, progname, msg)
  (@formatter || @default_formatter).call(severity, datetime, progname, msg)
end
format_severity (severity)
Исходный код
# File lib/logger.rb, line 745
def format_severity(severity)
  SEV_LABEL[severity] || 'ANY'
end
level_key ()
Исходный код
# File lib/logger.rb, line 754
def level_key
  Fiber.current
end
level_override ()
Исходный код
# File lib/logger.rb, line 750
def level_override
  @level_override ||= {}
end

Обеспечивает существование этого ivar даже когда подклассы не вызывают конструктор суперкласса.

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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