RDR3T > Логи и Уведомления в Rails 3, ч. 1: Логи

мая 22, 2011  |  Published in Ruby, Ruby on Rails, Ruby on Rails 3, Тестирование  |  5 Comments

Rails 3 снабжен очень мощной системой уведомлений о происходящем внутри приложения на основе которой строятся логи приложения. Не смотря на то, что уведомления первичны, мы начнем с лог файлов.

Логи — это журнал происшествий в вашем приложении, они основываются на уведомлениях, собственно уведомления и сообщают в подробностях о происшествиях в приложении. Происшествия — это цепочка действий в вашем приложении, которая следует за каким-либо действие пользователя: переходом на другую страницу, отправкой пользователем формы и так далее.

Все логи хранятся в папке ../log/ ваше приложения и записываются в файлы с именем окружения (development, test и production) и расширением *.log. Зачем логи нужны? По логам можно определить что делало приложение в определенный момент времени или увидить ошибки и попытки взлома приложения.

Rails, по умолчанию использует из Ruby StdLib. Давайте сначала расмотрим работу конкретно с этим логером вне контекста Rails.

Логи — это просто журнал о работе приложения, и каждая запись — это просто запись о том, что что-то было выполнено, а где-то возникла ошибка. Логер предоставляет несколько типов — уровней записей, ниже они приведены в порядке важности:

FATAL — фатальная ошибка, которая ведет к падению приложения;
ERROR — не критичная ошибка, которую можно обработать;
WARN — предупреждение;
INFO — какая-то информация о выполнении приложения
DEBUG — подробная (низкоуровневая) информация о работе приложения которая необходима разработчикам, в первую очередь в процессе разработки и тестирования.

Все эти уровни необходимы для того, чтобы записи можно было фильтровать, например если вам не интересна информация о работе приложения и вы находите важной информацией только информацию об ошибках. Ниже приведен пример из официальной документации:

log = Logger.new(STDOUT)
log.level = Logger::WARN

log.debug("Created logger")
log.info("Program started")
log.warn("Nothing to do!")

begin
  File.each_line(path) do |line|
    unless line =~ /^(\w+) = (.*)$/
      log.error("Line in wrong format: #{line}")
    end
  end
rescue => err
  log.fatal("Caught exception; exiting")
  log.fatal(err)
end

Поскольку уровень логера установлен в WARN, то в логи будут записываться только сообщения с уровнем WARN и выше, то есть WARN, ERROR и FATAL.

Логер это просто инструмент, который транслирует сообщения куда-либо. В данном случае, при создании логера обслуживающего приложение мы транслируем сообщения в STDOUT — стандартное устройство вывода, например в консоль. То есть, когда логер работает в Rails, он, по умолчанию, транслирует сообщения и в консоль, и в файлы логов.

Как создавать логеры?

Главным аргументом при создании логера является место, куда он будет передавать сообщения. Это может быть стандартное устройство вывода или вывода ошибок:

logger = Logger.new(STDERR)
logger = Logger.new(STDOUT)

Со специальным лог-файлом:

logger = Logger.new('logfile.log')

file = File.open('foo.log', File::WRONLY | File::APPEND)
# Для создания нового (и удаления старого) логфайл следует добавить File::CREAT:
file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT)
logger = Logger.new(file)

Создание логера, которые «старит» лог-файлы, то есть удаляет старые логи и ограничивает размер файлов логов. Пример ниже демонстрирует пример создания лога, который сохраняет 10 последних лог-файлов, при этом размер каждого не превышает мегабайта:

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, #warn, #info, #debug и #add, который в качестве аргумента принимает уровень сообщения. Примеры:

#Сообщение в блоке кода:
logger.fatal { "Argument 'foo' not given." }

#Сообщение в виде строки:
logger.error "Argument #{ @foo } mismatch."

#Название сообщение и текст сообщения:
logger.info('initialize') { "Initializing..." }

#Метод #add:
logger.add(Logger::FATAL) { 'Fatal error!' }

После того, как необходимость в записи логов отпадает, логер необходимо отключить:

logger.close

Установка порога важности сообщений
Установить порок важности сообщений можно двумя способами:

#Оригинальный способ:
logger.sev_threshold = Logger::WARN

#Log4r способ для совместимости

logger.level = Logger::INFO

Ниже приведен порядок приоритетности сообщений:

DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN

Формат логов
Записи логов имеют определенный формат, это необходимо для того, чтобы логи были более понятными и чтобы с ними можно было работать при помощи специальных программ. Ниже приведен пример форматирования сообщений логера:

SeverityID, [Date Time mSec #pid] SeverityLabel — ProgName: message

… и пример самого такого сообщения:

I, [Wed Mar 03 02:34:24 JST 1999 895701 #19074]  INFO — Main: info.

Вы можете легко менять формат даты и времени записи сообщения логера:

logger.datetime_format = "%Y-%m-%d %H:%M:%S"
#"2004-01-03 00:54:26"

Вы также можете меня формат всего сообщения логера при помщи метода #formatter=.

logger.formatter = proc { |severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"
}
#"Thu Sep 22 08:51:08 GMT+9:00 2005: hello world"

Перевод стандартной .

Когда вы работаете с логером в Rails, вы имеете дело с классом Rails.logger:

Rails.logger.info "Info Message"
Rails.logger.error "Error Message"

Для переопределения логера и его настроек вам следует использовать файлы environment.rb или другие файлы настройки окружений, или инициаторы.

Пример с environment.rb (или ../environments/<environment>.rb):

Rails.logger = Logger.new(STDOUT)

Пример с файлами инициации приложения (файлы из ../config/initializers):

config.logger = Logger.new(STDOUT)

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

config.log_level = Logger::ERROR
Rails.logger.level = 3 # можно использовать в любом месте вашего приложения
[/uby]
Сообщения в коде приложения на Rails записываются в лог также как и в примере выше:
[ruby]
logger.info "Info Message"
logger.error "Error MEssage"

Чтобы изменить стандартный адрес хранени логов, вы можете изменить его при определении собственного логера или в конфигах приложения:

paths.log = "/path/to/logs/#{Rails.env}.log"

 

Лучшая благодарность автору — ваши комментарии!

Tags: , , , , , ,

Responses

  1. says:

    мая 22, 2011 at 13:36 (#)

    Логгер скорее инструмент отладки, а не тестирования (я про рубрику статьи)

  2. admin says:

    мая 22, 2011 at 13:37 (#)

    UseRefle, я знаю, однако видел статьи, где в тестировании принимают участие конкретно логи, вместо самого кода. Не знаю на сколько эта практика оправдывает себя, тем не менее пускай будет рубрика тестирование, посколько об отладке буду писать не так много, чтобы создавать специальную рубрику под нее.

  3. нет says:

    мая 25, 2011 at 00:17 (#)

    разве рельс не использует BufferedLogger вместо Логгер ?

  4. anton says:

    декабря 8, 2011 at 07:17 (#)

    в случае с рельсами в какой файл этот код нужно писать?

  5. admin says:

    декабря 8, 2011 at 11:37 (#)

    anton, /config/environment.rb, например.

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.