Логирование¶
Централизованное структурированное логирование через structlog 25.x. Более 300 именованных событий по всей системе.
Конфигурация¶
Функция setup_logging() вызывается один раз при старте (app/main.py). Уровень задается через env-переменную LOG_LEVEL (default: INFO).
Процессоры structlog¶
graph LR
A[merge_contextvars] --> B[add_log_level]
B --> C[StackInfoRenderer]
C --> D[set_exc_info]
D --> E[TimeStamper<br/>ISO 8601]
E --> F{Режим?}
F -->|Dev| G[ConsoleRenderer<br/>цветной вывод]
F -->|Prod| H[JSONRenderer<br/>одна строка = событие]
Уровни логирования¶
| Уровень | Описание | Когда использовать |
|---|---|---|
DEBUG |
Все сообщения | Локальная отладка |
INFO |
Основной поток | Продакшн (default) |
WARNING |
Восстановимые ошибки | Мониторинг |
ERROR |
Невосстановимые ошибки | Алерты |
Подавление шума библиотек¶
Следующие логгеры принудительно установлены в WARNING:
sqlalchemy.engine--- SQL-запросыasyncpg--- драйвер PostgreSQLpyrogram--- Telegram MTProtohttpx/httpcore/urllib3--- HTTP-клиенты (HuggingFace и др.)
Маршрутизация логов (Docker)¶
Все Docker-сервисы пишут в logs/{SERVICE_NAME}.log через RotatingFileHandler (10MB x 3 файла) + stdout.
| Сервис | Файл | Контейнер |
|---|---|---|
| dialog-orchestrator | logs/dialog-orchestrator.log |
debt_collector_orchestrator |
| admin-bot | logs/admin-bot.log |
debt_collector_admin_bot |
| api | logs/api.log |
debt_collector_api |
| celery-worker | logs/celery-worker.log |
debt_collector_celery_worker |
| celery-worker-warming | logs/celery-worker-warming.log |
debt_collector_celery_worker_warming |
| celery-beat | logs/celery-beat.log |
debt_collector_celery_beat |
| embedding-worker | logs/embedding-worker.log |
HOST (systemd) |
| emulator-worker | logs/emulator-worker.log |
HOST (systemd) |
Celery loglevel
Захардкожен --loglevel=info в docker-compose.yml для всех Celery-воркеров.
Каталог событий¶
Lifecycle (8 событий)¶
| Событие | Уровень | Описание |
|---|---|---|
starting_debt_collector |
info | Запуск системы |
dialog_manager_started |
info | DialogManager инициализирован |
dialog_manager_stopped |
info | DialogManager остановлен |
shutdown_signal_received |
info | SIGINT/SIGTERM получен |
shutting_down |
info | Начало graceful shutdown |
shutdown_complete |
info | Завершение |
admin_bot_task_created |
info | Admin bot запущен |
debt_collector_running |
info | Все компоненты запущены |
AI Engine (12+ событий)¶
| Событие | Уровень | Описание |
|---|---|---|
ai_engine_using_cli |
info | CLI fallback (нет API key) |
departments_loaded_into_ai |
info | Кампании загружены |
company_loaded_into_ai |
info | Компания загружена |
claude_query_completed |
debug | SDK запрос завершен |
claude_cli_error |
error | CLI subprocess ошибка |
claude_cli_timeout |
error | CLI таймаут |
sdk_query_failed |
error | Anthropic SDK ошибка |
json_parse_failed |
warning | JSON парсинг неудача |
parse_retry_succeeded |
info | Повторный парсинг успешен |
response_guard_violations |
warning | Запрещенный паттерн обнаружен |
empty_first_contact_response |
warning | Пустой ответ AI |
rag_context_trimmed |
info | RAG-контекст урезан по token budget |
Диалоги и беседы (7 событий)¶
| Событие | Уровень | Описание |
|---|---|---|
conversation_closed |
info | Беседа закрыта |
conversation_taken_over |
info | Takeover оператором |
conversation_already_exists |
warning | Дубликат |
lock_acquisition_timeout |
warning | Таймаут Redis lock |
first_contact_sent |
info | Первый контакт отправлен |
followup_sent |
info | Follow-up отправлен |
engagement_ping_sent |
info | Engagement ping |
Telegram (7+ событий)¶
| Событие | Уровень | Описание |
|---|---|---|
account_started |
info | Аккаунт подключен |
account_stopped |
info | Аккаунт отключен |
account_already_running |
warning | Повторный запуск |
no_available_accounts |
warning | Нет свободных аккаунтов |
send_failed_after_retries |
error | FloodWait исчерпан |
user_blocked |
warning | Пользователь заблокировал |
error_classified |
debug | Ошибка классифицирована |
Celery Workers (6+ событий)¶
| Событие | Уровень | Описание |
|---|---|---|
followups_processed |
info | Batch follow-ups обработан |
new_contacts_initiated |
info | Новые контакты отправлены |
health_check_error |
error | Health check упал |
warming_task_no_accounts |
warning | Нет аккаунтов для прогрева |
client_summaries_updated |
info | Аналитика обновлена |
daily_counters_reset |
info | Счетчики сброшены |
RAG и Embedding Worker (20+ событий)¶
| Событие | Уровень | Модуль | Описание |
|---|---|---|---|
rag_model_loaded |
info | rag_engine | Модель загружена |
rag_model_load_failed |
warning | rag_engine | Ошибка загрузки модели |
embedding_worker_started |
info | embedding_worker | Worker запущен |
embedding_worker_stopped |
info | embedding_worker | Worker остановлен |
batch_embedded |
info | embedding_worker | Batch обработан |
rag_search_completed |
info | dialog_manager | Семантический поиск завершен |
rag_search_failed |
warning | dialog_manager | Fallback на legacy |
embed_pending_enqueued |
info | tasks | Safety net: сообщения в очередь |
Admin Notifier (4 события)¶
| Событие | Уровень | Описание |
|---|---|---|
notifier_no_admin_bot_token |
warning | Токен не настроен |
notifier_no_admin_ids |
debug | Нет получателей |
notifier_send_failed |
warning | Алерт не доставлен |
notifier_close_error |
debug | Ошибка закрытия сессии |
Просмотр логов¶
Docker-контейнеры¶
# Все сервисы
docker compose logs -f
# Конкретный сервис
docker compose logs -f dialog-orchestrator
docker compose logs -f celery-worker
# Последние N строк
docker compose logs --tail=100 api
# Фильтр по событию
docker compose logs api 2>&1 | grep "response_guard"
# Все файлы сразу
tail -f logs/*.log
HOST-сервисы (systemd)¶
# Embedding Worker
tail -f logs/embedding-worker.log
journalctl -u embedding-worker -f
# Emulator Worker
tail -f logs/emulator-worker.log
journalctl -u emulator-worker -f
Unified-скрипт¶
./scripts/logs.sh # Все сервисы
./scripts/logs.sh api # Только API
./scripts/logs.sh dialog-orchestrator # Только оркестратор
Мониторинг¶
Database-backed метрики
Prometheus/StatsD не используются. Метрики хранятся в PostgreSQL.
| Модель | Обновление | Данные |
|---|---|---|
ConversationAnalytics |
Per-dialog | negotiation_stage, debtor_type, discount_offered |
ClientSummary |
Каждые 30 мин (Celery) | risk_score (0-100), broken_promises |
TgAccount counters |
Per-message | daily_messages, daily_dialogs |
Admin Notifier (admin_bot/notifier.py) --- standalone Bot API алерты в Telegram. Никогда не выбрасывает исключения --- только логирует ошибки.
Правила именования событий¶
- Всегда snake_case
- Паттерн:
модуль_действие---first_contact_sent,account_started - Суффиксы:
_error,_failed,_completed,_started,_timeout - Контекстные поля:
client_id,account_id,conversation_id - Не логировать PII (телефоны, имена) --- только ID
Добавление логирования¶
import structlog
logger = structlog.get_logger()
class MyService:
async def do_something(self, client_id: int):
logger.info("my_action_started", client_id=client_id)
try:
result = await self._process(client_id)
logger.info("my_action_completed",
client_id=client_id, result=result)
except SomeError as e:
logger.error("my_action_failed",
client_id=client_id, error=str(e))
raise
Без __name__
Всегда structlog.get_logger() без аргументов --- structlog автоматически определяет контекст через contextvars.