Files
iu 6361e48b20 feat(observability): configurable logging, request ids and error logs
- internal/logging: LOG_LEVEL/LOG_FORMAT parsing and slog handler
- request_id middleware (X-Request-ID or generated, echoed) + debug access log
- httpx registers errors; middleware logs internal causes with request_id
- health excluded, objects/sse debug-only, no query/body/secrets in logs
- new observability capability spec; README/.env.example docs
2026-10-11 13:40:11 +03:00

3.6 KiB
Raw Permalink Blame History

Tasks

1. Конфигурация логирования (A)

  • 1.1 Добавить пакет backend/internal/logging с разбором уровня (ParseLevel) и сборкой handler (NewHandler(format, level)); проверка — go test ./internal/logging покрывает разбор debug|info|warn|error, json|text и ошибки.
  • 1.2 Добавить секцию Log в config.Config и чтение LOG_LEVEL/LOG_FORMAT с валидацией; проверка — go test ./internal/config покрывает значения по умолчанию и отказ на недопустимом значении.
  • 1.3 Строить slog-handler в cmd/server/main.go из cfg.Log вместо жёсткого LevelInfo; проверка — запуск с LOG_LEVEL=debug/LOG_FORMAT=text меняет вывод, а недопустимый LOG_LEVEL завершает старт явной ошибкой.
  • 1.4 Описать LOG_LEVEL/LOG_FORMAT в .env.example и README.md; проверка — задокументированный запуск с LOG_LEVEL=debug выводит подробные строки.

2. Идентификатор запроса и access-лог (B)

  • 2.1 Middleware в app.Router(): request_id из валидного X-Request-ID либо сгенерированный, запись в контекст запроса и заголовок ответа X-Request-ID; проверка — тест: переданный id сохраняется и возвращается, отсутствующий генерируется.
  • 2.2 Access-строка уровня debug (method, route c.FullPath(), status, latency, bytes, client_ip, user_id, request_id) без query; проверка — тест: на debug строка пишется, на info нет, query-параметры не попадают.
  • 2.3 Фильтрация access-логов: /api/health исключён всегда, /api/objects/* и /api/sse/* — только debug; проверка — тест на наборе маршрутов и уровне.

3. Регистрация внутренних ошибок (D)

  • 3.1 В httpx.RespondError/Abort регистрировать не-AppError через c.Error(err); проверка — тест: неизвестная ошибка попадает в c.Errors, ответ остаётся обобщённым 500.
  • 3.2 Логировать собранные ошибки в middleware: не-AppError и AppError со статусом >=500 — уровень error с причиной и request_id, AppError <500 — уровень debug; проверка — тест с буфером лога на обе ветки.
  • 3.3 Гарантировать приватность: не логировать query-строку, Authorization и тела запросов; проверка — тест с ?token=... и телом убеждается, что значения не встречаются в буфере лога.

4. Интеграционная проверка

  • 4.1 Прогнать локальный инстанс с LOG_LEVEL=debug, выполнить несколько запросов (включая аутентифицированный и /api/health) и убедиться: access-строки есть, X-Request-ID возвращается в ответе, /api/health не логируется, секреты в логах отсутствуют.