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

Как осмотришь лог

2.2 Middle🔥 141 комментариев
#Другое

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

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

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

Ответ

Как осмотреть логи в Java приложении

Логирование критично для отладки и мониторинга. Рассмотрю инструменты, форматы и стратегии анализа логов.

1. Структура лога — что смотреть

2024-03-22 10:45:32.123 [main] INFO  com.example.UserService - User registered: user123
  └─ Timestamp        └─ Thread     └─ Level └─ Logger Name      └─ Message

В каждом логе содержится:

  • Timestamp — когда произошло
  • Thread — в каком потоке
  • Level — критичность (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
  • Logger name — откуда логируется (класс)
  • Message — что произошло
  • Exception — стек трассировки ошибки (если есть)

2. Файлы логов — где их найти

# Spring Boot приложение
/var/log/myapp.log          # На production сервере
logs/spring.log             # В директории приложения

# Docker контейнер
docker logs <container-id>  # Выводит логи контейнера
docker logs -f <container-id> # Следить за логами в реальном времени

# Kubernetes pod
kubectl logs <pod-name>     # Логи пода
kubectl logs -f <pod-name>  # Tail логи
kubectl logs --previous <pod-name> # Логи предыдущего пода (если переставал работать)

3. Чтение логов — команды Linux

# Показать последние 50 строк
tail -n 50 myapp.log

# Следить за логами в реальном времени
tail -f myapp.log

# Показать последние 100 строк по времени
tail -f myapp.log | grep "2024-03-22 10:45"

# Поиск по уровню логирования
grep "ERROR" myapp.log
grep "WARN" myapp.log

# Поиск по классу
grep "com.example.UserService" myapp.log

# Показать ошибки за последний час
grep "ERROR" myapp.log | tail -100

# Просмотр стека ошибки
grep -A 20 "Exception" myapp.log  # -A 20: 20 строк после совпадения

# Подсчёт ошибок
grep -c "ERROR" myapp.log

4. Анализ ошибок — типичные паттерны

# NullPointerException
grep "NullPointerException" myapp.log
# Ищем что привело: обычно строка перед исключением
grep -B 5 "NullPointerException" myapp.log

# Database connection errors
grep -i "connection" myapp.log | grep "ERROR"

# Out of Memory
grep "OutOfMemoryError" myapp.log

# Timeout errors
grep -i "timeout\|timed out" myapp.log

# HTTP errors
grep "500\|503\|502" myapp.log  # Server errors
grep "404\|401\|403" myapp.log  # Client errors

5. Программное чтение логов в Java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class UserService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    
    public void registerUser(User user) {
        logger.info("Starting user registration: {}", user.getEmail());
        
        try {
            userRepository.save(user);
            logger.info("User registered successfully: {}", user.getId());
        } catch (Exception e) {
            logger.error("Failed to register user: {}", user.getEmail(), e);
            // e — исключение автоматически добавит stack trace
        }
    }
}

Вывод:

2024-03-22 10:45:32 INFO  com.example.UserService - Starting user registration: user@example.com
2024-03-22 10:45:33 INFO  com.example.UserService - User registered successfully: 123

# Если ошибка:
2024-03-22 10:46:00 ERROR com.example.UserService - Failed to register user: other@example.com
java.sql.SQLException: Connection timeout
    at com.example.db.Database.connect(Database.java:45)
    at com.example.repo.UserRepository.save(UserRepository.java:32)
    ...

6. Логирование на разных уровнях

public class ApplicationService {
    private static final Logger logger = LoggerFactory.getLogger(ApplicationService.class);
    
    public void processOrder(Order order) {
        // TRACE — самый подробный (обычно отключен)
        logger.trace("Entering processOrder with order: {}", order);
        
        // DEBUG — для разработчиков при отладке
        logger.debug("Order validation started");
        
        if (order.isValid()) {
            // INFO — важные события
            logger.info("Order processed successfully: orderId={}", order.getId());
        } else {
            // WARN — что-то неправильно, но приложение продолжает работу
            logger.warn("Order validation failed: orderId={}, reason={}", 
                order.getId(), order.getValidationErrors());
        }
        
        try {
            saveOrder(order);
        } catch (DatabaseException e) {
            // ERROR — ошибка, которая повлияет на функциональность
            logger.error("Failed to save order: orderId={}", order.getId(), e);
        }
    }
}

7. Конфигурация уровней логирования (logback.xml)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_FILE" value="logs/application.log"/>
    
    <!-- Appender: куда писать логи -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    
    <!-- Console appender для разработки -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- Уровни логирования по пакетам -->
    <logger name="com.example.myapp" level="DEBUG"/>
    <logger name="org.springframework" level="INFO"/>
    <logger name="org.hibernate" level="WARN"/>
    
    <root level="INFO">
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

8. Поиск проблем в логах — стратегия

# 1. Поиск по времени проблемы
# Пользователь сообщил об ошибке в 10:45
grep "2024-03-22 10:4[0-5]" myapp.log | grep "ERROR"

# 2. Поиск связанных логов (trace ID)
# Современные системы используют trace ID
grep "traceId=abc123def456" myapp.log

# 3. Поиск истории пользователя
grep "userId=123" myapp.log

# 4. Полный стек ошибки
grep -A 30 "java.lang.NullPointerException" myapp.log

# 5. Периодические ошибки
grep "Timeout" myapp.log | wc -l  # Количество ошибок
grep "Timeout" myapp.log | tail -20  # Последние 20

9. Best Practices для логирования

// ✅ ПРАВИЛЬНО
logger.info("Order created: orderId={}, userId={}, amount={}", 
    order.getId(), order.getUserId(), order.getAmount());

// ✅ Используй placeholders вместо конкатенации
logger.debug("Processing user: {}", user);

// ❌ НЕ ДЕЛАЙ
logger.info("Order created: " + order.getId()); // Строка создаётся всегда
logger.debug("Debug: " + expensiveFunction()); // Вызывается даже если DEBUG отключен

// ✅ Ленивое вычисление для дорогих операций
if (logger.isDebugEnabled()) {
    logger.debug("Data: {}", expensiveOperation());
}

// ✅ Логируй исключения
try {
    doSomething();
} catch (Exception e) {
    logger.error("Failed to do something", e); // e добавит stack trace
}

10. Инструменты для анализа логов

ИнструментИспользование
grepПоиск по паттерну (быстро)
tail -fСледить за логами в реальном времени
ELK StackElasticsearch + Logstash + Kibana (большие приложения)
SplunkЦентрализованный анализ логов
DataDogМониторинг логов и метрик
CloudWatchAWS логи
awk/sedОбработка и фильтрация логов

Краткая стратегия:

  1. Найди временной период проблемы
  2. Ищи ERROR/WARN в этом диапазоне
  3. Посмотри на исключения и stack trace
  4. Проследи цепочку событий перед ошибкой
  5. Проверь конфигурацию и ресурсы сервера