
Как упростить управление целым парком из 800+ экземпляров СУБД на базе PostgreSQL? Можно доработать postgres_exporter, чтобы настроить получение метрик под себя. А если ещё проще? Мониторить связкой Grafana, Prometheus и кастомизированным postgres_exporter, а данные получать через ИИ‑отчёт, который будет агрегировать данные Prometheus через прямые PromQL‑запросы.
Но если и этого мало, то можно вообще поручить ИИ‑агенту типовые тикеты вроде очистки места на диске и плановой остановки БД.
Меня зовут Станислав Епишин, я из команды «R4C.Support.Всадники апокалипсиса» в СберТехе. Я уже писал, как мы дорабатывали postgres_exporter → pangolin_exporter, исправляя баг в расчёте длительности транзакций, и как внедряли связку Prometheus + Pipeliner + TaskTracker + GigaChat для автоматического создания тикетов.
В этой статье расскажу про R&D‑исследование для небольшой команды DBA, в котором мы тестировали гипотезу: получится ли собрать автономного агента, который сам будет обрабатывать тикеты: очищать дисковое пространство, выполнять VACUUM/ANALYZE и планировать остановки БД?
Здесь я описал инструкцию по созданию агента (с полным кодом и пояснениями) и развёрнутый реальный пример про автономный VACUUM/ANALYZE с обнаружением аномалий через LLM. Также покажу, как организовать ленту событий для мониторинга работы агента, и детально разберу, где и как в проекте используется LLM.
Архитектура проекта: два режима работы
В проекте существует два независимых режима, которые используют одну кодовую базу и общие инструменты, но запускаются по‑разному и преследуют разные цели:
Интерактивный агент (LangGraph). Пользователь → Streamlit WebUI → граф LangGraph → 32 инструмента → внешние системы (СУБД Platform V Pangolin DB, TaskTracker, Prometheus, Pipeliner, LLM).
Автономный агент (cron). Cron → Ticket Scanner → Handlers (Statistics / DiskSpace / PlannedMaintenance) → внешние системы (TaskTracker, СУБД, LLM).
Интерактивный агент предназначен для ручной диагностики и операций через чат, автономный — для автоматического решения тикетов по расписанию.
Где используется LLM во всём проекте
LLM (GigaChat) применяется в четырёх различных сценариях. Ниже краткое описание каждого (вместо сложной диаграммы):
Интерактивный агент (LangGraph) — LLM вызывается многократно в цикле: понимает запрос, выбирает инструмент, обогащает аргументы, запрашивает подтверждение и формирует ответ.
Автономный агент (cron) — LLM вызывается однократно для извлечения структурированных данных из текста тикета (хост, mountpoint, дата и время, действие). После этого выполняется жёсткая логика (SSH, SQL).
analyze_pangolin_ai собирает метрики из Prometheus и журналы ошибок, и передаёт их в LLM для генерации выводов и рекомендаций на русском языке.
get_db_log_errors анализирует журналы СУБД, выделяет критические ошибки (FATAL, PANIC, deadlock) и может отдавать их на анализ LLM (точка расширения).
Лента событий — окно во внутренний мир агента
Агент записывает каждое значимое действие в JSONL‑журнал (logs/agent_events.jsonl). В WebUI реализована страница «Лента событий», которая позволяет:
фильтровать события по уровню важности (INFO, WARNING, ERROR, DEBUG);
искать по номеру тикета, обработчику (StatisticsHandler, DiskSpaceHandler) или по фрагменту сообщения;
просматривать подробности — какой шаг выполнялся, какие параметры передавались, результат;
следить за ходом обработки в реальном времени (с автообновлением).
Пример отображения ленты:
✅ CORESUP-61769 — StatisticsHandler — 1 событие (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61768 — StatisticsHandler — 1 событие (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61770 — StatisticsHandler — 1 событие (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61771 — StatisticsHandler — 5 событий (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61772 — StatisticsHandler — 5 событий (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61773 — StatisticsHandler — 5 событий (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61774 — StatisticsHandler — 3 события (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61775 — StatisticsHandler — 5 событий (тикет обнаружен в 03.06 16:50)
✅ CORESUP-61776 — StatisticsHandler — 5 событий (тикет обнаружен в 03.06 16:50)
ℹ️ CORESUP-61749 — PlannedMaintenanceHandler — 4 события (тикет обнаружен в 03.06 16:51)
Пример записи в журнале:
{“timestamp”: “2025-04-15T10:23:45”, “event_type”: “progress”, “ticket”: “R4CDBA-12345”, “handler”: “StatisticsHandler”, “step”: “llm_plan”, “message”: “LLM план: vacuum orders.status_updates, analyze”, “level”: “INFO”}
Быстрое начало: пишем своего агента за 30 минут (пошагово)
Полный рабочий шаблон проекта (со всем кодом, конфигурациями и скриптами) доступен в публичном репозитории (ссылка ведёт на обезличенный шаблон, готовый к запуску). Здесь я покажу только ключевые элементы, чтобы можно было быстро начать, клонировав репозиторий.
1. Структура проекта

2. Ключевой обработчик StatisticsHandler (сокращённо, только ядро)
class StatisticsHandler(BaseHandler): # ... (инициализация, can_handle, extract_details опущены — см. репозиторий) def __init__(self): self.llm = LLMClient() # ... настройки # ... (опущены вспомогательные методы, полный код в репозитории) def process(self, ticket_code, ticket_data=None): log_event("progress", ticket_code, "StatisticsHandler", "start", "INFO") # 1. Извлечение хоста и базы из тикета (с помощью regex или LLM) host, dbname = self._extract_host_and_db(ticket_data) # 2. Проверка нагрузки load = self._check_load(host, dbname) if not load["safe_to_proceed"]: return "postponed" # 3. Получение таблиц tables = self._get_tables_needing_maintenance(host, dbname) if not tables: self._close_ticket(ticket_code, "Fixed") return "no_issues" # 4. LLM планирование и валидация (ядро) plan = self._llm_plan(tables) # вызывает LLM для составления плана if not self._validate_plan(plan, tables): self._add_comment(ticket_code, "LLM plan rejected by safety validation") return "plan_rejected" # 5. Выполнение (dry-run по умолчанию, но можно переключить) dry_run = True # в продакшене переключается через конфиг results = [] for action in plan.get("actions", []): sql = f"{action['type'].upper()} {action['schema']}.{action['table']};" if not dry_run: # если не dry-run, выполняем реальный SQL self._execute_sql(host, dbname, sql) results.append(f"{'[DRY RUN] ' if dry_run else ''}{sql}") # 6. Закрытие тикета с комментарием comment = "Выполнено:\n" + "\n".join(results) self._add_comment(ticket_code, comment) if not dry_run: self._close_ticket(ticket_code, "Fixed") return "success" # ... остальные методы (проверка нагрузки, получение таблиц и т.д.) — см. репозиторий
#... остальные методы (проверка нагрузки, получение таблиц и так далее) — см. репозиторий
Безопасность: LLM может предложить что угодно. Агент всегда проверяет план: таблицы, пути, типы действий. Только после этого выполняет (и то в dry‑run по умолчанию). Полная логика проверки доступна в репозитории.
3. Интеграция с TaskTracker и JSONL‑логирование
Примеры клиентов для TaskTracker и логгера событий приведены в репозитории. Здесь ограничимся описанием: TaskTrackerClient умеет добавлять комментарии и закрывать тикеты, а log_event пишет структурированные записи в JSONL с блокировкой.
4. Основной сканер (scanner.py)
def scan_and_process(): client = TaskTrackerClient() tickets = client.search_tickets_by_label("MONITORING_VACUUM_ANALYZE") handler = StatisticsHandler() for ticket in tickets: if not handler.already_processed(ticket["code"]): handler.process(ticket["code"], ticket) if __name__ == "__main__": scan_and_process()
Запуск по cron: добавьте в crontab: */5 * * * * cd /path/to/my_dba_agent && pythonscanner.py, и ваш агент начнёт обрабатывать тикеты каждые пять минут.
Реальный пример: автономный VACUUM/ANALYZE
Поступил тикет с меткой MONITORING_VACUUM_ANALYZE. Описание:
Сервер: vm‑db‑app-01.solution.sbt
База данных: order_service
Обнаружены таблицы с большим количеством мёртвых строк. Требуется обслуживание.
Метрики Prometheus показывали: у таблицы orders.status_updates более 150 000 мёртвых строк, last_analyze не обновлялся 12 дней. Автовакуум был отключен на уровне таблицы.
Действия агента (StatisticsHandler)
Извлёк параметры (хост, БД).
Проверил нагрузку — низкая.
Получил 7 проблемных таблиц.
LLM спланировала действия: выполнить VACUUM и ANALYZE для всех, дополнительно рекомендовать включить autovacuum для
orders.status_updates.Агент проверил план — все таблицы существуют, действия безопасны.
Выполнил VACUUM/ANALYZE. Операция заняла четыре минуты.
Добавил комментарий с отчётом и рекомендацией включить autovacuum.
Закрыл тикет.
Первые результаты работы агента на тестовых БД
Мы запустили агента в тестовой среде 15 мая. За первые 5 дней система обработала 347 тикетов, из них:
StatisticsHandler(VACUUM/ANALYZE, 309 тикетов) → 89%;DiskSpaceHandler(очистка диска, 31 тикетов) → 9%;PlannedMaintenanceHandler(плановые остановки, 7 тикетов) → 2%;переданы человеку с меткой
NO_AUTO_RESOLVE— (неудач, ≈10 тикетов) → 3%.
Среднее время обработки одного тикета составило 2,5 минуты, что в 12 раз быстрее, чем при ручном реагировании (в среднем 30 минут). Основные причины неудач — ошибки доступа (SSH‑ключи) или нехватка данных в описании тикета (например, не указан mountpoint).
Уже через неделю нагрузка выросла в разы (мы включили дополнительные оповещения), и агент успешно справился с пиком более 1000 тикетов в сутки. Подробный разбор с графиками, тепловыми картами и анализом потребления токенов LLM выйдет в четвёртой статье цикла. Здесь же мы фиксируем, что концепция доказала свою эффективность даже на ограниченной выборке.
Вывод по этому случаю: в идеале, нужна настройка autovacuum под нагрузку. Но на тестовых стендах, когда стенды удаляются и появляются новые, агент — быстрое и эффективное решение, закрывающее проблему за минуты.
Другие ключевые инструменты (чат‑бот и автономные операции)
В проекте реализовано 32 инструмента, доступных как через чат‑бот, так и используемых в автономных хендлерах. Основные из них:
? Скачать журнал СУБД Pangolin с хоста: с возможностью ИИ‑анализа ошибок (GigaChat выделяет критические события и даёт рекомендации).
? pg_profile: отчёты и снэпшоты: аналог AWR‑отчёта Oracle для СУБД Pangolin.
? AI‑отчёт analyze_pangolin_ai: собирает метрики CPU/RAM/HDD из Prometheus, топ-5 запросов, анализирует журналы ошибок и блокировок с помощью LLM.
? Установить pg_profile на хост: автоматическая установка расширения (требует подтверждения, перезапуск БД).
? Поставить хост(ы) на мониторинг: добавление хостов в Prometheus target через задачу в Pipeliner (требует подтверждения).
Все инструменты журналируются в общей ленте событий, что позволяет отслеживать любые действия, выполненные через чат или автономно.
Обеспечение безопасности
Dry‑run по умолчанию: все действия сначала только журналируются.
Проверка LLM‑планов: агент проверяет предложения LLM на соответствие white‑листам и допустимым операциям.
Проверка нагрузки: операции не выполняются при высокой нагрузке.
Метка NO_AUTO_RESOLVE: после двух неудачных попыток агент не трогает тикет.
Полный аудит: JSONL‑журнал всех действий, включая сырые ответы LLM.
Реализация на практике: ThreadPool внутри cron‑запуска
В текущей реализации агент запускается по cron каждые 10 минут. При этом для параллельной обработки нескольких тикетов используется ThreadPoolExecutor из стандартной библиотеки Python. Такой подход остаётся простым, не требует перехода на постоянно работающий сервис, но уже даёт выигрыш в скорости при большом количестве тикетов.
Пример реализации (ключевой фрагмент):
from concurrent.futures import ThreadPoolExecutor def worker(ticket): handler = StatisticsHandler() return handler.process(ticket["code"], ticket) with ThreadPoolExecutor(max_workers=5) as executor: futures = [executor.submit(worker, t) for t in tickets] # ... обработка результатов и логирование
Полный код доступен в репозитории.
Сам скрипт вызывается cron‑демоном, а пул потоков позволяет обрабатывать несколько тикетов одновременно. При необходимости можно увеличить max_workers или добавить приоритеты, но текущей конфигурации достаточно для 800+ БД.
Как агент пережил тестовую среду и что случилось потом
Агент успешно работает на 800+ тестовых БД. Как показали первые недели, он использует LLM для планирования действий, затем проверяет эти планы и выполняет только безопасные операции. Лента событий даёт полную прозрачность. Шаблоны кода адаптируются под любой трекер задач (Jira, YouTrack) и любую LLM (GigaChat, GPT, Claude).
В настоящее время агент уже переведён в режим второй линии поддержки, и мы готовим отдельную статью с полной статистикой за месяц работы, графиками нагрузки, анализом экономии человеко‑часов и планами развития.
Если интересно, не переключайтесь!
Комментарии (2)

stuxnetix
23.09.2026 15:43Неплохо , узнав о 800 БД , сразу подумал о скрипте как минимум на Go т.к соединений много и который собирал бы из логов особо опасные инциденты и запускал , то что нужно по инструкции , используя триггеры лога , запускался бы ответный fix-запрос на указанные инциденты. А тут уже с ИИ + метрики , как я понимаю ему еще условно дали разрешение на выполнение определенных задач , т.к иногда он непредсказуем.. может и дропнуть что ни будь или вообще перезагрузить сервер в боевой работе.
Tzimie
Когда пришли за программистами, я молчал
Когда пришли за DBA...