0Pricing
Java Academy · Урок

Фасад SLF4J и регистраторы

Регистрируйте сообщения на подходящем уровне

«Фасад SLF4J и регистраторы» — бесплатный урок Java Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Что такое SLF4J?

SLF4J (простой фасад журналирования для Java) — это абстракция. Вы пишете код для его API, а реализация вроде Logback или Log4j2 выполняет фактическое журналирование.

Благодаря этому библиотеки могут вести журнал, не навязывая приложению конкретную реализацию.

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

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("Application started");
    }
}

Получение регистратора

Создавайте один регистратор для каждого класса с помощью LoggerFactory.getLogger(MyClass.class).

По соглашению поле объявляют как private static final и называют log или logger. Класс становится именем регистратора, и это имя появляется в выводе.

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

public class OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);
    void placeOrder(String id) {
        log.info("Placing order {}", id);
    }
}

Пять уровней

Регистраторы SLF4J предоставляют по одному методу для каждого уровня:

  • log.trace(...)
  • log.debug(...)
  • log.info(...)
  • log.warn(...)
  • log.error(...)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.trace("entering main");
        log.debug("args length = {}", args.length);
        log.info("service is up");
        log.warn("cache miss");
        log.error("failed to connect");
    }
}

Выбор подходящего уровня

Рекомендации:

  • ERROR: настоящая ошибка, требующая внимания человека.
  • WARN: устранимое отклонение.
  • INFO: важные события жизненного цикла.
  • DEBUG: диагностическая информация для разработчиков, отключаемая в рабочей среде.
  • TRACE: чрезвычайно подробная трассировка.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PaymentService {
    private static final Logger log = LoggerFactory.getLogger(PaymentService.class);
    void charge(int cents) {
        if (cents <= 0) { log.warn("non-positive charge: {}", cents); return; }
        log.info("charged {} cents", cents);
    }
}

Имена и иерархия регистраторов

Имена регистраторов образуют иерархию на основе пакетов, разделённых точками. Регистратор с именем com.example.svc является дочерним для com.example.

Конфигурация родительского регистратора применяется к дочерним, если её не переопределить, поэтому для каждого пакета можно задать свой уровень.

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

public class Main {
    public static void main(String[] args) {
        Logger a = LoggerFactory.getLogger("com.example.app");
        Logger b = LoggerFactory.getLogger("com.example.app.db");
        a.info("parent logger");
        b.debug("child inherits parent's level unless overridden");
    }
}

Защита затратных вызовов

При затратном формировании сообщения используйте isDebugEnabled(), чтобы эта работа выполнялась только при включённом уровне.

При параметризованном журналировании (в следующем уроке) это требуется редко, но необходимо, если Вы создаёте строки самостоятельно.

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

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    static String heavyDump() { return "...large state..."; }
    public static void main(String[] args) {
        if (log.isDebugEnabled()) {
            log.debug("state: {}", heavyDump());
        }
    }
}

Журналирование исключений

Чтобы записать исключение вместе с полной трассировкой стека, передайте Throwable как последний аргумент.

Не помещайте исключение в заполнитель — передавайте его после сообщения.

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

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        try {
            throw new IllegalStateException("boom");
        } catch (Exception e) {
            log.error("Operation failed for id {}", 42, e);
        }
    }
}

Один регистратор на класс

Объявляйте регистратор один раз как статическое неизменяемое поле. Никогда не создавайте регистратор внутри метода: это приводит к лишним затратам и лишает Вас преимущества имени класса.

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

public class UserRepository {
    // Good: one shared logger named after the class
    private static final Logger log = LoggerFactory.getLogger(UserRepository.class);
    void save(String user) { log.debug("saving {}", user); }
}

SLF4J и реализация

SLF4J — это только API. Во время выполнения он связывается с той реализацией, которая находится в пути классов.

  • Добавьте logback-classic: SLF4J использует Logback.
  • Добавьте log4j-slf4j2-impl: SLF4J использует Log4j2.

Ваш код не изменяется.

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

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        // Same code, different backend depending on classpath
        log.info("backend-agnostic logging");
    }
}

Не записывайте конфиденциальные данные

Никогда не записывайте в журнал пароли, токены или полные номера банковских карт. Журналы часто передаются во множество систем и хранятся долгое время.

Маскируйте или исключайте конфиденциальные поля перед журналированием.

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

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    static String mask(String card) { return "****" + card.substring(card.length() - 4); }
    public static void main(String[] args) {
        log.info("charged card {}", mask("4111111111111234"));
    }
}

Практический сервис

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

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

public class EmailService {
    private static final Logger log = LoggerFactory.getLogger(EmailService.class);
    void send(String to) {
        log.debug("preparing email to {}", to);
        try {
            if (to == null) throw new IllegalArgumentException("null recipient");
            log.info("email sent to {}", to);
        } catch (Exception e) {
            log.error("failed to send email", e);
        }
    }
}

Быстрая проверка

Проверьте свои базовые знания о SLF4J.

Итоги

Вы изучили фасад SLF4J:

  • Получайте по одному private static final Logger для каждого класса.
  • Используйте пять методов уровней по назначению.
  • Имена регистраторов образуют иерархию, что позволяет управлять уровнями для отдельных пакетов.
  • Передавайте Throwable последним аргументом, чтобы записать трассировку стека; никогда не записывайте секреты.

Далее — эффективные параметризованные сообщения.

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

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("SLF4J facade recap complete");
    }
}

Часто задаваемые вопросы

Урок «Фасад SLF4J и регистраторы» бесплатный?

Да — полный текст урока «Фасад SLF4J и регистраторы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Фасад SLF4J и регистраторы»?

Регистрируйте сообщения на подходящем уровне Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Фасад SLF4J и регистраторы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Зачем нужна структурированная регистрация
  2. Фасад SLF4J и регистраторы
  3. Параметризованная регистрация
  4. Настройка Logback
← Назад к Java Academy