Состояние и журналы
> Кратко. Живость API показывает /health: базы городов, Redis и схема баз в одном ответе. Код ответа всегда 200, поэтому смотреть надо на поле status. Подробности пишутся в журнал каждого процесса API и в журналы служб. Кто что делал — в журнале действий.
Адреса проверки
| Адрес | Вход | Что показывает |
|---|---|---|
GET /health, /api/health |
не нужен | status (ok / degraded), база, Redis, схема базы, число маршрутов, флаги сервера |
GET /city/<код>/health |
не нужен | То же по одному городу (API на несколько городов) |
GET /api/v1/auth/config |
не нужен | Флаги входа и записи, город, включён ли ИИ |
GET /metrics |
токен METRICS_TOKEN |
Метрики Prometheus. Без METRICS_TOKEN — 404 |
GET /api/v1/ai/status |
любой вход | Включён ли помощник, модель, причина, если выключен |
GET /api/v1/water/status |
любой вход | Отвечает ли движок водопровода, версия WNTR |
martin GET /health |
на 127.0.0.1 |
Живость martin |
движок водопровода GET /health |
на 127.0.0.1 |
Версия WNTR |
Ответ /health
{
"status": "ok",
"database": {"ok": true, "latency_ms": 15.0, "error": null},
"redis": {"ok": true, "latency_ms": 0.0, "error": null, "note": null},
"city_schema": {"status": "ok", "checked_at": "…", "missing": [], "applied": [], "error": null, "recreated": 0},
"routes": 517,
"russian_names_initialized": true,
"flags": {"auth_disabled": false, "dev_login_enabled": false, "strict_auth": true,
"mutations_enabled": true, "topology_mutations_enabled": true}
}
Пример — стенд документации на копии Алматы; флаги показаны как на сервере с включённым входом.
status—degraded, если не отвечает база любого города, Redis или доводка схемы базы закончилась ошибкой (city_schema.status = "error"). HTTP-код при этом остаётся 200. Внешний сторож и скрипты выкатки должны проверять полеstatus, а не только код.- Без префикса города в режиме нескольких городов
database.citiesиcity_schema.citiesпоказывают каждый город отдельно. city_schema.recreated— сколько раз с запуска процесса база была пересоздана десктопом (переконвертация).routes— число маршрутов. Меньше 80 — веб показывает «На сервере устаревший API»./healthоткрыт без входа. В ответ попадают тексты ошибок подключения к базе и Redis, а в них бывает имя или адрес сервера. Наружу через nginx его лучше не публиковать.
Метрики Prometheus
/metrics с заголовком Authorization: Bearer <METRICS_TOKEN>:
| Метрика | Что |
|---|---|
tgid_http_requests_total{method,route,status} |
Запросы по шаблону маршрута и коду |
tgid_http_request_duration_seconds{method,route} |
Время ответа |
tgid_db_pool_connections{city,state} |
Соединения пула базы города |
tgid_city_schema_ok{city,status}, tgid_city_schema_missing{city} |
Схема базы на месте; сколько пунктов недостаёт |
tgid_city_db_recreated{city} |
Переконвертации базы с запуска процесса |
tgid_celery_queue_up, tgid_celery_queue_length |
Доступна ли очередь; сколько задач ждут воркера (сумма очередей городов) |
tgid_info{city,database} |
Город и база процесса |
Для нескольких процессов uvicorn задайте PROMETHEUS_MULTIPROC_DIR — общий каталог, очищаемый перед стартом
службы. Без него каждый процесс отдаёт только свои счётчики. Нет пакета prometheus-client — API работает,
а /metrics выключен; в журнале предупреждение «Метрики /metrics выключены».
Журналы
| Журнал | Где | Что в нём | Ротация |
|---|---|---|---|
| Журнал процесса API | logs/app.log в каталоге API; второй процесс из того же каталога — app-2.log и так далее |
Всё с уровня DEBUG: ошибки маршрутов, доводка схемы, вебхуки, сторож цикла. В строке — номер процесса | 1 МБ × 5 файлов |
| Вывод службы API | <logs>\<служба>.out.log / .err.log |
Строки доступа uvicorn (метод, полный адрес с параметрами, код), ошибки запуска, трассировки | NSSM, по 10 МБ |
| Вывод воркера | <logs>\tgid-worker-…err.log |
Ход задач Celery, ошибки расчётов | NSSM, по 10 МБ |
| Протокол расчёта | база города, calculation_protocol |
Сообщения движка; окно «Протокол» | CALC_PROTOCOL_KEEP_DAYS (365 дней) |
| Журнал действий | UsersDB, activity_log |
Кто, когда, что, откуда, с каким итогом | ACTIVITY_LOG_DAYS (730 дней) |
| История правок | база города, audit_log |
Что именно изменилось в данных | — |
Журналы служб на Windows пишутся в кодировке консоли (cp1251). Их читают, например, через iconv -f cp1251.
Строки доступа uvicorn содержат адрес запроса с параметрами. Значения token, access_token, password и key
(ключ ArcGIS, ключ встраиваемой карты) в них заменяются на *** — так же, как в журнале действий. Остальные
параметры пишутся как есть, поэтому журналы служб всё равно храните с ограниченным доступом.
Журнал действий в окне — Журнал действий; история правок — История правок.
Сторож цикла событий
Если процесс API перестал отвечать дольше LOOP_STALL_S (по умолчанию 5 с), в журнал процесса пишется
«Цикл событий не отвечает» со стеком потока и сроком ближайшего таймера:
- стек в коде приложения — цикл занят синхронной работой;
- стек в
select()при просроченном таймере — цикл «уснул». Сторож будит его, и в журнале появляется «цикл снова отвечает».
Пока цикл стоит, записи идут не чаще раза в 30 с. LOOP_STALL_S=0 выключает сторожа.
Что проверять снаружи
Внешний сторож — например, задача планировщика или Prometheus. На проде эту работу делает отдельная служба, которая не входит в репозитории. Что стоит проверять:
/healthкаждого города:status == "ok";- страницу веба каждого города и её entry-скрипт
_nuxt/…— оба 200; - что службы API, воркеров, веба и martin запущены;
- длину очередей
tgid.<город>в Redis: растёт и не убывает — воркеры стоят; - место на дисках баз, журналов и резервных копий;
- новые строки
ERRORв журналах служб; - итог резервного копирования
last-backup.json— Резервные копии.
«API недоступен» и другие баннеры веба
Веб запрашивает /health при загрузке и показывает полосу под шапкой:
| Полоса | Причина | Что делать |
|---|---|---|
| Красная, «API недоступен» или текст ошибки сети | /health не ответил |
Ниже по порядку |
| Жёлтая, текст про Redis | redis.ok = false |
Запустить Redis; проверить REDIS_ADDR, REDIS_DB |
| Жёлтая, «На сервере устаревший API (N маршрутов)» | меньше 80 маршрутов | Не тот процесс отвечает на адресе API; выкатить API |
Если API недоступен, проверьте по порядку:
- Служба API запущена? Если нет — причина в
<служба>.err.log. Частые причины: ошибка вTGID_CITY_DBS,STRICT_AUTH=trueпри небезопасных настройках («STRICT_AUTH=true forbids…» или «STRICT_AUTH=true requires AUTH_REQUIRED_GET=true»), нет каталогаFILES_DIR, база недоступна при старте. - Отвечает ли
http://127.0.0.1:<порт>/healthна самом сервере? Да, а снаружи нет — ищите причину в nginx:proxy_passгорода, upstream API,nginx -t. - Ответ
degraded— смотритеdatabase.error,redis.error,city_schema.error. - API отвечает медленно или «зависает» — ищите в
logs/app*.logзаписи сторожа цикла. Проверьтеpg_stat_activity: длинные запросы,idle in transaction, исчерпанный пул (DB_POOL_MAX_SIZE). - Расчёты стоят «в очереди» — работают ли воркеры, слушают ли они очередь города (
tgid.<код>), растёт лиtgid_celery_queue_length.
Для разработчика
/health—routers/core.py, метрики —observability.py, журнал процесса —app_logging.py(свой файл на процесс по замкуlogs/app[-N].lock: общий файл на Windows не ротируется), сторож —utils/loop_watchdog.py.- Баннер веба —
layouts/default.vueиrefreshApiHealthвservices/api/http.ts.
