Логирование (Java) - lanit-tercom-school/analyzeme GitHub Wiki

Logging for Java app

Оглавление

Инструменты логирования в нашем приложении

Logback

t.b.c.

SLF4J

t.b.c.

Syslog4j

t.b.c.

Guideline

Общее

Для использования логгера добавьте:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

За исключением особых случаев, создавайте один логгер на класс, например:

private static final Logger LOGGER;
static {
    LOGGER = LoggerFactory.getLogger(
             "com.analyzeme.controllers.IndexController");
}

Уровни логирования

Logback предоставляет шесть стандартных уровней логирования. Их трактовка зависит от конкретного приложения, в нашем случае принята следующая:

//Очень подробное описание происходящего (вплоть до записи каждой итерации цикла) 
//по умолчанию не отображается в общем логе
LOGGER.trace("message");

//Вход/выход нетривиального метода, важное событие/ветвление внутри метода
LOGGER.debug("message");

//Ошибки, связанные с неверным вводом или др. (обрабатываемые)
//сведения о жизненном цикле всей системы и обращении к внешним источникам
LOGGER.info("message");

//Для непредвиденных ошибок, которые не допускают завершения работы конкретного сценария
LOGGER.warn("message");

//Для ошибок, после которых приложение не сможет продолжать работу
LOGGER.error("message");

Отображение логов настраивается в файле logback.xml, соотношение отображаемые уровни/режим приведено в таблице ниже

displayed\level on TRACE DEBUG INFO WARN ERROR OFF
TRACE YES NO NO NO NO NO
DEBUG YES YES NO NO NO NO
INFO YES YES YES NO NO NO
WARN YES YES YES YES NO NO
ERROR YES YES YES YES YES NO

В нашем случае режим отображения - DEBUG, т.е. в списке вы увидите всё, кроме TRACE-уровня.

Культура ведения логов

  1. Используйте только английский язык
  2. Для каждого класса используйте один логгер с названием вида com.analyzeme.{package}.{className}. В исключительных ситуациях допустимо использование дополнительного логгера вида com.analyzeme.{package}.{className}.{methodName}
  3. Используйте верные уровни ведения логов
//так не надо
LOGGER.error("getName(): method started");
//так тоже
LOGGER.trace("veryImportantDatabase(): connection failed");
  1. Общая схема записи {имяМетода}(): {название объекта/операции} {суть сообщения}. Например:
LOGGER.debug("analyze(): analysis started");
  1. Пишите краткие сообщения
//плохая мысль
"doPut(): workflow was not able to start properly because of resource not being able to lock. Resource name: {0}."
//лучше
"doPut(): workflow cannot be started: resource '{0}' was not acquired."
  1. Используйте одни и те же названия/формулировки для одного и того же объекта/события
//не так
LOGGER.info("Prediction model {0} was loaded", pm.ID);
LOGGER.info("PredictionModel (ID={0}) decrypted successfully", pm.ID);
LOGGER.info("Cannot link PM: {0} to product (ID={1})", pm.ID, product.ID);
  1. Для логирования сведений об объекте реализуйте его метод toString(). Для крупных объектов есть смысл предусмотреть метод toShortString() с важными сведениями.
//не надо
LOGGER.debug(obj.getName());
LOGGER.debug(obj.getID());
LOGGER.debug(obj.get100500otherProperties());
  1. Для исключений также используйте метод toString(). Нежелательно использовать просто getMessage(), т.к. вы потеряете достаточное количество информации.
  2. Не программируйте в логах
//нет!
LOGGER.info("Processing replicate {0}." + (++replicateIndex));