← Назад к вопросам

Как реализовать логирование сервиса на Spring Boot?

1.6 Junior🔥 211 комментариев
#Spring Boot и Spring Data

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как реализовать логирование сервиса на Spring Boot?

Логирование — это критическая часть любого production приложения. Оно помогает отслеживать события, ошибки и процессы выполнения. В Spring Boot используется SLF4J с Logback.

1. Встроенная конфигурация Spring Boot

Spring Boot автоматически настраивает Logback при добавлении зависимости.

// spring-boot-starter включает logging автоматически

2. Основные уровни логирования

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    
    public void processUser(String userId) {
        logger.debug("Processing user: {}", userId);
        try {
            logger.info("User started processing", userId);
            if (userId == null || userId.isEmpty()) {
                logger.warn("User ID is empty");
            }
        } catch (Exception e) {
            logger.error("Error processing user: {}", e.getMessage(), e);
        }
    }
}

Уровни (от менее к более серьезным):

  • TRACE — наиболее детальная информация
  • DEBUG — информация для отладки
  • INFO — информационные сообщения
  • WARN — предупреждения
  • ERROR — ошибки

3. Конфигурация через application.yml

spring:
  application:
    name: myapp

logging:
  level:
    root: INFO
    com.mycompany: DEBUG
    org.springframework: WARN
  pattern:
    console: %d{yyyy-MM-dd HH:mm:ss} - %msg%n
    file: %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
  file:
    name: logs/application.log
  logback:
    rollingpolicy:
      max-file-size: 10MB
      max-history: 30

4. Кастомная конфигурация logback-spring.xml

Создайте файл src/main/resources/logback-spring.xml для гибкой конфигурации:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" />
    <property name="LOG_PATH" value="logs" />
    <property name="LOG_FILE" value="${LOG_PATH}/application.log" />
    
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/archived/application-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
    </appender>
    
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/error.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/archived/error-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    
    <logger name="com.mycompany" level="DEBUG" />
    <logger name="org.springframework" level="INFO" />
    
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>
</configuration>

5. Логирование с контекстом (MDC)

import org.springframework.stereotype.Component;
import org.slf4j.MDC;
import javax.servlet.Filter;
import java.util.UUID;

@Component
public class RequestLoggingFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(RequestLoggingFilter.class);
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        String requestId = UUID.randomUUID().toString();
        MDC.put("requestId", requestId);
        
        try {
            logger.info("Request started");
            chain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }
}

Обновите pattern: %d{yyyy-MM-dd HH:mm:ss} [%X{requestId}] %-5level %msg%n

6. Логирование в контроллере

@RestController
@RequestMapping("/api/users")
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    private final UserService userService;
    
    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        logger.debug("Getting user by id: {}", id);
        try {
            UserDTO user = userService.findById(id);
            logger.info("User found", id);
            return ResponseEntity.ok(user);
        } catch (UserNotFoundException e) {
            logger.warn("User not found", id);
            return ResponseEntity.notFound().build();
        }
    }
    
    @PostMapping
    public ResponseEntity<UserDTO> createUser(@RequestBody CreateUserRequest request) {
        logger.info("Creating user");
        try {
            UserDTO user = userService.create(request);
            logger.info("User created successfully");
            return ResponseEntity.status(HttpStatus.CREATED).body(user);
        } catch (Exception e) {
            logger.error("Failed to create user", e);
            throw e;
        }
    }
}

7. Логирование исключений

@Service
public class PaymentService {
    private static final Logger logger = LoggerFactory.getLogger(PaymentService.class);
    
    public void processPayment(String orderId, BigDecimal amount) {
        try {
            logger.info("Processing payment for order {}", orderId);
        } catch (PaymentException e) {
            logger.error("Payment processing failed: {}", e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            logger.error("Unexpected error during payment", e);
            throw new PaymentException("Payment failed", e);
        }
    }
}

8. Async логирование для производительности

<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
    <queueSize>512</queueSize>
    <discardingThreshold>0</discardingThreshold>
    <appender-ref ref="FILE" />
</appender>

<root level="INFO">
    <appender-ref ref="CONSOLE" />
    <appender-ref ref="ASYNC_FILE" />
</root>

9. Логирование в разные файлы

<logger name="com.mycompany.payment" level="DEBUG" additivity="false">
    <appender-ref ref="PAYMENT_FILE" />
</logger>

<logger name="com.mycompany.user" level="DEBUG" additivity="false">
    <appender-ref ref="USER_FILE" />
</logger>

Лучшие практики

  1. Используйте SLF4J — стандартная абстракция в Java
  2. Логируйте значимые события — старты, ошибки, завершения
  3. Не логируйте sensitive данные — пароли, токены, номера карт
  4. Используйте разные уровни — DEBUG для разработки, INFO для production
  5. Включайте контекст — requestId, userId для трассировки
  6. Логируйте исключения полностью — с stack trace для отладки
  7. Используйте ротацию логов — не заполняйте диск
  8. Параметризуйте логи — используйте {} плейсхолдеры вместо конкатенации

Таким образом, правильное логирование — это фундамент успешного мониторинга и отладки production приложений.

Как реализовать логирование сервиса на Spring Boot? | PrepBro