middle
Как организовать централизованное логирование?
Централизованное логирование — это сбор логов со всех микросервисов в одном месте для удобного поиска и анализа. Основные стеки: ELK (Elasticsearch + Logstash + Kibana) и Grafana Loki.
Пример
Микросервисы → Logstash (или Filebeat) → Elasticsearch → Kibana
Настройка структурированного логирования (Logback + JSON)
<!-- logback-spring.xml -->
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeMdcKeyName>traceId</includeMdcKeyName>
<includeMdcKeyName>spanId</includeMdcKeyName>
<customFields>
{"service":"payment-service","environment":"${ENV}"}
</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Результат — структурированный JSON-лог:
{
"@timestamp": "2026-04-18T10:30:00.123Z",
"level": "INFO",
"service": "payment-service",
"traceId": "abc123def456",
"spanId": "span789012",
"message": "Платёж обработан успешно",
"paymentId": "PAY-001",
"amount": 50000,
"environment": "production"
}
Grafana Loki – альтернатива ELK
Loki не индексирует содержимое логов, а только метки (labels), что делает его значительно дешевле и проще в эксплуатации.
Рекомендации по логированию в микросервисах
- Всегда включайте traceId — для связывания логов одного запроса.
- Используйте структурированные логи (JSON) — для удобного поиска и фильтрации.
- Логируйте бизнес-события — не только ошибки, но и важные бизнес-действия.
- Не логируйте чувствительные данные — номера карт, пароли, персональные данные (PCI DSS!).
- Используйте уровни логирования правильно: ERROR — сбои, WARN — нештатные ситуации, INFO — бизнес-события, DEBUG — для отладки (отключено в prod).
Пример правильного логирования
@Slf4j
@Service
public class PaymentService {
public void processPayment(PaymentRequest request) {
log.info("Начало обработки платежа: paymentId={}, amount={}, currency={}",
request.getPaymentId(), request.getAmount(), request.getCurrency());
try {
// ... бизнес-логика
log.info("Платёж успешно обработан: paymentId={}", request.getPaymentId());
} catch (InsufficientFundsException e) {
log.warn("Недостаточно средств: paymentId={}, accountId={}",
request.getPaymentId(), request.getAccountId());
throw e;
} catch (Exception e) {
log.error("Ошибка обработки платежа: paymentId={}",
request.getPaymentId(), e);
throw e;
}
}
}
На собеседовании: покажите, что знаете стек (ELK или Loki), и что логи должны быть структурированными (JSON) с traceId. Частая ошибка — забыть про маскирование чувствительных данных в логах.