Files
ds-galo/openspec/changes/archive/2026-10-11-add-observability-logging/tasks.md
T
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

25 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks
## 1. Конфигурация логирования (A)
- [x] 1.1 Добавить пакет `backend/internal/logging` с разбором уровня (`ParseLevel`) и сборкой handler (`NewHandler(format, level)`); проверка — `go test ./internal/logging` покрывает разбор `debug|info|warn|error`, `json|text` и ошибки.
- [x] 1.2 Добавить секцию `Log` в `config.Config` и чтение `LOG_LEVEL`/`LOG_FORMAT` с валидацией; проверка — `go test ./internal/config` покрывает значения по умолчанию и отказ на недопустимом значении.
- [x] 1.3 Строить `slog`-handler в `cmd/server/main.go` из `cfg.Log` вместо жёсткого `LevelInfo`; проверка — запуск с `LOG_LEVEL=debug`/`LOG_FORMAT=text` меняет вывод, а недопустимый `LOG_LEVEL` завершает старт явной ошибкой.
- [x] 1.4 Описать `LOG_LEVEL`/`LOG_FORMAT` в `.env.example` и `README.md`; проверка — задокументированный запуск с `LOG_LEVEL=debug` выводит подробные строки.
## 2. Идентификатор запроса и access-лог (B)
- [x] 2.1 Middleware в `app.Router()`: `request_id` из валидного `X-Request-ID` либо сгенерированный, запись в контекст запроса и заголовок ответа `X-Request-ID`; проверка — тест: переданный id сохраняется и возвращается, отсутствующий генерируется.
- [x] 2.2 Access-строка уровня `debug` (method, route `c.FullPath()`, status, latency, bytes, client_ip, user_id, request_id) без query; проверка — тест: на `debug` строка пишется, на `info` нет, query-параметры не попадают.
- [x] 2.3 Фильтрация access-логов: `/api/health` исключён всегда, `/api/objects/*` и `/api/sse/*` — только `debug`; проверка — тест на наборе маршрутов и уровне.
## 3. Регистрация внутренних ошибок (D)
- [x] 3.1 В `httpx.RespondError`/`Abort` регистрировать не-`AppError` через `c.Error(err)`; проверка — тест: неизвестная ошибка попадает в `c.Errors`, ответ остаётся обобщённым `500`.
- [x] 3.2 Логировать собранные ошибки в middleware: не-`AppError` и `AppError` со статусом `>=500` — уровень `error` с причиной и request_id, `AppError <500` — уровень `debug`; проверка — тест с буфером лога на обе ветки.
- [x] 3.3 Гарантировать приватность: не логировать query-строку, `Authorization` и тела запросов; проверка — тест с `?token=...` и телом убеждается, что значения не встречаются в буфере лога.
## 4. Интеграционная проверка
- [x] 4.1 Прогнать локальный инстанс с `LOG_LEVEL=debug`, выполнить несколько запросов (включая аутентифицированный и `/api/health`) и убедиться: access-строки есть, `X-Request-ID` возвращается в ответе, `/api/health` не логируется, секреты в логах отсутствуют.