Перейти к содержанию
Панель

Логирование

Централизованное структурированное логирование через 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 --- драйвер PostgreSQL
  • pyrogram --- Telegram MTProto
  • httpx / 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. Никогда не выбрасывает исключения --- только логирует ошибки.

Правила именования событий

  1. Всегда snake_case
  2. Паттерн: модуль_действие --- first_contact_sent, account_started
  3. Суффиксы: _error, _failed, _completed, _started, _timeout
  4. Контекстные поля: client_id, account_id, conversation_id
  5. Не логировать 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.