Сьогодні ми трішки глибше зануримося в логування. Перш ніж кидатися в код, задумайся: як би ти зрозумів, що додаток "зламався"? Звісно, користувачі можуть поскаржитися, що "сайт не працює", але цього замало для діагностики. Тут у гру вступає логування. Spring дає потужний і гнучкий механізм для логування, який легко інтегрується з популярними бібліотеками, такими як SLF4J, Logback і Log4j. А тепер уяви життя без логів. Єдиний спосіб відладки — розставляти System.out.println() по коду? Це не тільки неефективно, а й нагадує спробу знайти північ за допомогою кактуса.
Налаштування логування в Spring Boot
За замовчуванням Spring Boot постачається з підтримкою SLF4J (Simple Logging Facade for Java) і Logback. Це стандартне поєднання, яке покриває більшість задач.
Додавання залежності (якщо її ще немає)
Якщо ти ще не використовуєш Spring Boot Starter Logging, додай це в pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
Spring Boot автоматично підключить Logback, тож додаткових маніпуляцій з бібліотеками не знадобиться.
Логування в обробниках помилок
Логування помилок в обробниках — це ключова частина обробки виключень. Давай почнемо з простого прикладу використання @ExceptionHandler з додаванням логування.
Приклад
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
LOGGER.error("Виникла помилка: {}", ex.getMessage(), ex);
return new ResponseEntity<>("Некоректний запит: " + ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
Тут ми використовуємо Logger, щоб записати повідомлення про помилку разом зі стек-трейсом (ex в кінці). Це дає повне уявлення про помилку.
Розбираємося в рівнях логування
Перед тим як написати мегакрутий логгер, важливо зрозуміти, що таке рівні логування:
- TRACE: детальна інформація про роботу додатку (рідко використовується).
- DEBUG: інформація для налагодження. Наприклад, які значення були передані в метод.
- INFO: загальна інформація про нормальну роботу додатку.
- WARN: попередження, які не критичні, але потребують перевірки (наприклад, термін сесії закінчується).
- ERROR: помилки, які вимагають втручання.
Приклад використання різних рівнів:
LOGGER.trace("Детальна інформація для налагодження.");
LOGGER.debug("Дані для аналізу роботи: значення X = {}", x);
LOGGER.info("Користувач успішно авторизувався.");
LOGGER.warn("Термін дії пароля користувача скоро закінчиться.");
LOGGER.error("Помилка при обробці запиту.", exception);
На практиці логи з рівнів нижче INFO вимкнені в більшості production-систем.
Налаштування Logback через конфігураційний файл
Хочеш більше контролю над логами? Spring Boot дозволяє налаштувати Logback у файлі logback-spring.xml.
Приклад конфігурації
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logs/app.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.example" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</logger>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
Цей файл створює два апендери: один виводить логи в консоль, інший — у файл app.log. Зверни увагу на pattern: він визначає формат виведення логів (включаючи timestamp, рівень, ім'я логера і повідомлення).
Логування за допомогою SLF4J у контролерах і сервісах
Приклад
Давай додамо логи в контролер:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoController.class);
@GetMapping("/example")
public ResponseEntity<String> exampleMethod(@RequestParam String input) {
LOGGER.info("Отримано запит з параметром: {}", input);
if (input.isEmpty()) {
LOGGER.warn("Пустий параметр запиту!");
return new ResponseEntity<>("Параметр не повинен бути пустим", HttpStatus.BAD_REQUEST);
}
LOGGER.debug("Виконується обробка запиту...");
return new ResponseEntity<>("Успішна відповідь", HttpStatus.OK);
}
}
Практичне завдання: логування кастомних виключень
Створимо кастомне виключення й глобальний обробник з логуванням.
Крок 1. Створення кастомного виключення
public class CustomException extends RuntimeException {
public CustomException(String message) {
super(message);
}
}
Крок 2. Додавання обробки
@RestControllerAdvice
public class GlobalErrorHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalErrorHandler.class);
@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException ex) {
LOGGER.error("Кастомне виключення: {}", ex.getMessage(), ex);
return new ResponseEntity<>("Сталася помилка: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Крок 3. Використання виключення в коді
@RestController
public class CustomExceptionController {
@GetMapping("/trigger-error")
public ResponseEntity<String> triggerError() {
throw new CustomException("Щось пішло не так!");
}
}
Результат: якщо користувач відкриє /trigger-error, він побачить зрозуміле повідомлення про помилку, а в логах буде стек-трейс з деталями.
Логування і моніторинг
Інтеграція логів з системами моніторингу (наприклад, ELK: Elasticsearch, Logstash, Kibana) дозволяє стежити за логами в реальному часі. Spring Actuator також може логувати системні події. Іншими словами, твої логи будуть не просто текстом, а інструментом для прогнозування проблем.
Типові помилки при логуванні
- Намагаються логувати абсолютно все (мільйон
DEBUG-логів = кінець продуктивності). - Використання
System.out.println()замість нормального логера. - Забуття про рівні логування: все або
WARN, абоINFO. - Логування чутливих даних (наприклад, паролів).
Використовуй правильні рівні і уникай перевантаження логів непотрібною інформацією.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ