Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как логировать приложение
Правильное логирование критично для отладки, мониторинга и анализа проблем. Рассмотрю best practices.
Архитектура логирования в Java
В Java логирование строится на трёх уровнях:
- SLF4J - фасад (Facade)
- Logback/Log4j - реальная реализация
- Конфигурация - XML файл для настройки
Уровни логирования
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
public void processOrder(Order order) {
// ERROR - критические ошибки
try {
validateOrder(order);
} catch (Exception e) {
log.error("Ошибка валидации заказа id={}", order.getId(), e);
}
// WARN - предупреждения
if (order.getAmount() > 1000000) {
log.warn("Большой заказ на сумму {}", order.getAmount());
}
// INFO - важные события
log.info("Заказ {} обработан", order.getId());
// DEBUG - детальная информация
log.debug("Детали: customer={}, items={}", order.getCustomerId(), order.getItems().size());
}
}
Конфигурация Logback
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n"/>
<property name="LOG_FILE" value="logs/app.log"/>
<!-- Консольный вывод -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</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>logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
Best Practices
1. Параметризованные сообщения
// Плохо
log.debug("User " + user.getId() + " logged in");
// Хорошо
log.debug("User {} logged in", user.getId());
2. Логируй контекст
// Недостаточно
log.error("Payment failed");
// Достаточно
log.error("Payment failed for orderId={}, amount={}", orderId, amount);
3. Логируй исключения полностью
try {
processPayment();
} catch (PaymentException e) {
log.error("Payment failed for order {}", orderId, e);
}
4. MDC для трассировки
String traceId = UUID.randomUUID().toString();
MDC.put("traceId", traceId);
try {
orderService.process(order);
log.info("Order created");
} finally {
MDC.remove("traceId");
}
5. Избегай логирования чувствительных данных
// Плохо
log.info("User password: {}", user.getPassword());
// Хорошо
log.info("User {} authenticated", user.getId());
Логирование в Spring Boot
@Service
public class UserService {
private static final Logger log = LoggerFactory.getLogger(UserService.class);
public User findById(Long id) {
log.debug("Searching for user id {}", id);
User user = userRepository.findById(id)
.orElseThrow(() -> {
log.warn("User not found id {}", id);
return new UserNotFoundException(id);
});
log.info("User found: {}", user.getId());
return user;
}
}
Асинхронное логирование
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<appender-ref ref="FILE"/>
</appender>
Инструменты анализа
- ELK Stack - Elasticsearch, Logstash, Kibana
- Splunk - платный инструмент
- Grafana + Loki - лёгкая альтернатива
- New Relic - облачный мониторинг
Итоги
- Используй SLF4J, не System.out
- Выбирай правильный уровень логирования
- Логируй контекст, не просто событие
- Используй параметризованные сообщения
- Не логируй чувствительные данные
- Используй MDC для трассировки
- Настрой ротацию логов