Логування значно важливіше, ніж може видатися на перший погляд починаючому розробнику.
Логи — це ніби «чорна скринька» додатку, яка записує кожну його дію.
Вони допомагають:
- Відслідковувати вхідні запити та їхні параметри.
- Дізнаватися, що саме сталося всередині додатку.
- Виявляти помилки і їхні причини.
- Розуміти, як працює додаток під навантаженням.
- Робити налагодження швидше і простіше.
На реальних проєктах REST API часто взаємодіють з купою клієнтських додатків. Логи допомагають не тільки розробникам, але й DevOps-інженерам та системним адміністраторам розібратися, де й що пішло не так.
Логування в Spring Boot
У Spring Boot за логування відповідає Logback (за замовчуванням). Це потужний і гнучкий фреймворк для ведення логів. Він підтримує різні рівні логування, форматування і навіть відправку логів у віддалені системи.
Рівні логування
Кожне повідомлення в логах має свій рівень важливості, як у новин — бувають термінові випуски й звичайні зведення. Давай розберемо цю ієрархію:
TRACE— найдетальніший рівень. Це як мікроскоп для коду, показує кожну дрібницю. У продакшені зазвичай вимкнений, щоб не засмічувати логи.DEBUG— твій вірний помічник під час розробки. Записує всі цікаві моменти, які допомагають зрозуміти, що відбувається всередині додатку.INFO— основний робочий рівень. Фіксує важливі події в житті додатку: "Сервер запустився", "База даних підключена", "Отримано важливий запит".WARN— попередження про потенційні проблеми. Як жовтий сигнал світлофора — поки не критично, але варто звернути увагу.ERROR— червоний сигнал тривоги. Щось пішло зовсім не так і потрібно термінове втручання. Логує серйозні помилки, які заважають нормальній роботі.
Конфігурація логування в Spring Boot
Spring Boot надає автоматичну інтеграцію з Logback, і налаштування логування можна задати через файл application.properties або application.yml. Наприклад, щоб увімкнути докладний режим відладки (DEBUG), достатньо додати рядок:
logging.level.root=DEBUG
Основні інструменти для логування запитів і відповідей
У Spring Boot є кілька способів логувати запити й відповіді. Розглянемо три основні підходи:
- Логування через фільтри (Filters).
- Логування з використанням аспектів (AOP).
- Інтеграція з фреймворками для централізованого логування.
1. Логування через фільтри
Фільтри (Filters) дозволяють перехоплювати HTTP-запити й відповіді на найнижчому рівні перед їхньою обробкою в контролерах. Це простий спосіб логувати вхідні запити й відповіді в одному місці.
Створимо свій фільтр для логування:
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class RequestResponseLoggingFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(RequestResponseLoggingFilter.class);
@Override
public void doFilter(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// Логуємо вхідний запит
logger.info("Incoming request: method = {}, URI = {}", httpRequest.getMethod(), httpRequest.getRequestURI());
// Продовжуємо виконання ланцюга фільтрів
chain.doFilter(request, response);
// Логуємо вихідну відповідь
logger.info("Outgoing response: status = {}", httpResponse.getStatus());
}
}
Розбираємо код:
- Цей фільтр перехоплює всі HTTP-запити й відповіді.
- Ми використовуємо метод
logger.infoдля запису вхідних запитів (метод запиту і URI) і вихідної відповіді (HTTP-статус). - За допомогою виклику
chain.doFilterми передаємо управління далі по ланцюгу.
2. Логування з використанням AOP
AOP (Aspect-Oriented Programming) робить логування по-справжньому розумним і гнучким. Це як поставити автоматичну систему спостереження, яка вмикається тільки в потрібних місцях і в потрібний час.
Замість того щоб засмічувати код логами, ми створюємо спеціальні «контрольні точки». Вони автоматично відслідковують тільки ті методи, за якими ми хочемо приглядати. Решта коду залишається чистою і сфокусованою на своїй основній задачі.
Ось приклад аспекту:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
// Логуємо до виконання методу контролера
@Before("execution(* com.example.demo.controller.*.*(..))")
public void logBeforeEachRequest() {
logger.info("A method in controller is about to be called...");
}
// Логуємо після успішного виконання методу контролера
@AfterReturning("execution(* com.example.demo.controller.*.*(..))")
public void logAfterEachRequest() {
logger.info("A method in controller has been completed successfully.");
}
}
- Анотація
@Aspectвказує, що це аспект. - За допомогою виразів всередині
@Beforeі@AfterReturningми визначаємо, яким методам буде застосовано логування. Наприклад, ми логируемо всі методи в пакетіcom.example.demo.controller. - У методах
logBeforeEachRequestіlogAfterEachRequestми використовуємо логуванняINFO, щоб записати повідомлення до і після виклику методу.
3. Централізоване логування (опційно)
Якщо твій додаток працює в розподіленій системі, класичне локальне логування може бути важкоаналізованим. У таких випадках використовують системи централізованого логування (наприклад, ELK Stack: Elasticsearch, Logstash і Kibana).
Приклад конфігурації для відправки логів в Elasticsearch через Logback:
logback-spring.xml
<configuration>
<appender name="ELASTICSEARCH-APPENDER" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:5044</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="info">
<appender-ref ref="ELASTICSEARCH-APPENDER"/>
</root>
</configuration>
Цей фрагмент відправляє всі логи рівня INFO і вище в Logstash, який потім передає їх в Elasticsearch. Таким чином логи можна візуалізувати в Kibana.
Практичне застосування
1. Який метод обрати?
- Фільтри, якщо треба логувати всі запити й відповіді в одному місці.
- AOP, якщо потрібно логувати тільки специфічні методи (наприклад, методи контролерів).
- Централізоване логування актуальне для продакшн-середовища, особливо якщо маєш кілька мікросервісів.
2. Типові помилки
- Надмірне логування: писати все підряд — не завжди хороша ідея. Логи можуть стати шумом. Логуй тільки ту інформацію, яка реально потрібна.
- Логування конфіденційних даних: ніколи не логуй паролі, токени або інші чутливі дані.
- Неправильний рівень логування: наприклад, використання
ERRORдля звичайної бізнес-логіки — це анти-патерн.
3. Що може знадобитися на співбесіді?
Вміння логувати запити й відповіді покаже інтерв'юеру, що ти знаєш, як забезпечити observability у додатку. Розуміння роботи з рівнями логування та централізованими системами на кшталт ELK додасть тобі бонусних балів.
Тепер ти знаєш, як впровадити логування в REST API. Воно не тільки допомагає обробляти помилки, але й чудово показує всі «внутрішності» додатку. Логи — це твої очі і вуха.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ