JavaRush /Курси /Модуль 5. Spring /Логування запитів і відповідей у REST API

Логування запитів і відповідей у REST API

Модуль 5. Spring
Рівень 10 , Лекція 9
Відкрита

Логування значно важливіше, ніж може видатися на перший погляд починаючому розробнику.

Логи — це ніби «чорна скринька» додатку, яка записує кожну його дію.

Вони допомагають:

  • Відслідковувати вхідні запити та їхні параметри.
  • Дізнаватися, що саме сталося всередині додатку.
  • Виявляти помилки і їхні причини.
  • Розуміти, як працює додаток під навантаженням.
  • Робити налагодження швидше і простіше.

На реальних проєктах 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 є кілька способів логувати запити й відповіді. Розглянемо три основні підходи:

  1. Логування через фільтри (Filters).
  2. Логування з використанням аспектів (AOP).
  3. Інтеграція з фреймворками для централізованого логування.

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());
    }
}

Розбираємо код:

  1. Цей фільтр перехоплює всі HTTP-запити й відповіді.
  2. Ми використовуємо метод logger.info для запису вхідних запитів (метод запиту і URI) і вихідної відповіді (HTTP-статус).
  3. За допомогою виклику 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.");
    }
}
  1. Анотація @Aspect вказує, що це аспект.
  2. За допомогою виразів всередині @Before і @AfterReturning ми визначаємо, яким методам буде застосовано логування. Наприклад, ми логируемо всі методи в пакеті com.example.demo.controller.
  3. У методах 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. Воно не тільки допомагає обробляти помилки, але й чудово показує всі «внутрішності» додатку. Логи — це твої очі і вуха.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ