# grafana_gen — схема базы данных База данных PostgreSQL `waf_info`. Утилита работает в режиме **только чтение** — данные не изменяются. --- ## Таблицы ### `sp_info` Автоматически заполняемый список ресурсов из ServicePipe. | Колонка | Тип | Описание | |---|---|---| | `sid` | `text` | Идентификатор ресурса (SID). NULL-записи игнорируются | | `domain_name` | `text` | Основной домен ресурса | | `aliases` | `jsonb` | JSON-массив дополнительных доменов | **Пример:** ```sql SELECT sid, domain_name, aliases FROM sp_info WHERE sid IS NOT NULL LIMIT 3; ``` ``` sid | domain_name | aliases --------+------------------------+---------------------------------- 10307 | nationallottery.ru | ["www.nationallottery.ru"] 11768 | fonbet-adapter.cloud.nationallottery.ru | [] 14048 | self.nationallottery.ru | [] ``` --- ### `manual_info` Ресурсы добавленные вручную (аналогична по структуре `sp_info`). | Колонка | Тип | Описание | |---|---|---| | `sid` | `text` | Идентификатор ресурса | | `domain_name` | `text` | Основной домен | | `aliases` | `jsonb` | JSON-массив дополнительных доменов | > Обе таблицы объединяются через `UNION` (без дублей). Если SID присутствует в обеих таблицах — берётся одна запись. --- ### `apps_settings` Маппинг SID ресурса на клиента (тенанта). Содержит пороги алертов по ошибкам — per-SID. | Колонка | Тип | По умолчанию | Описание | |---|---|---|---| | `l7resourceid` | `text` | — | SID ресурса (FK к `sp_info.sid` / `manual_info.sid`) | | `client_title` | `text` | — | Название клиента — имя тенанта в дашборде | | `four_hundred` | `integer` | 20 | Порог 4xx ошибок в % для данного SID | | `five_hundred` | `integer` | 10 | Порог 5xx ошибок в % для данного SID | | `ptaf_fallback_code_alert_count` | `integer` | 1 | Порог WAF block алерта в штуках за минуту | **Пример:** ```sql SELECT l7resourceid, client_title, four_hundred, five_hundred, ptaf_fallback_code_alert_count FROM apps_settings LIMIT 5; ``` ``` l7resourceid | client_title | four_hundred | five_hundred | ptaf_fallback_code_alert_count --------------+--------------+--------------+--------------+-------------------------------- 10307 | nloto | 20 | 10 | 1 11768 | nloto | 20 | 10 | 1 15363 | gorodpay | 30 | 10 | 3 12266 | gardia | 20 | 10 | 1 ``` > Один клиент может иметь несколько SID. Пороги `four_hundred` и `five_hundred` можно задавать индивидуально для каждого SID. --- ### `client_info` Настройки мониторинга и пороги алертов для каждого клиента. | Колонка | Тип | По умолчанию | Описание | |---|---|---|---| | `client_title` | `text` | — | Название клиента (PK, совпадает с `apps_settings.client_title`) | | `rps_limit` | `integer` | NULL | Порог RPS для алерта. NULL = алерт не создавать | | `rps_commercial_limit` | `integer` | NULL | Коммерческий лимит RPS — синяя линия на графике. NULL → 100 | | `waf_provider` | `text` | NULL | Тип провайдера WAF. NULL = клиент игнорируется | | `ptaf_fallback_code` | `text` | NULL | HTTP код блокировки PTAF (`418`, `403` и т.д.). `pass` или NULL = WAF block алерт не создавать | **Значения `waf_provider`:** | Значение | Дашборд | Группа алертов | Contact point | |---|---|---|---| | `spik` | PT AF Requests (VictoriaLogs) | `PTAF Grafana` | `tg+mail+mattermost PTAF Grafana` | | `sp` | SP PT AF Requests (VictoriaLogs) | `SP PTAF Grafana` | `For_SP` | | `NULL` | — | — | — (клиент игнорируется) | **Пример:** ```sql SELECT client_title, waf_provider, rps_limit, rps_commercial_limit, ptaf_fallback_code FROM client_info ORDER BY client_title; ``` ``` client_title | waf_provider | rps_limit | rps_commercial_limit | ptaf_fallback_code --------------+--------------+-----------+----------------------+-------------------- gardia | spik | 500 | 300 | 418 gorodpay | spik | 1000 | 800 | 418 nloto | spik | 7000 | 5000 | 418 inferit | sp | NULL | NULL | pass ``` > Если `rps_limit = NULL` — алерт на RPS не создаётся, но клиент всё равно попадает в дашборд. > Если `waf_provider = NULL` — клиент полностью игнорируется (не попадает ни в дашборд, ни в алерты). > Если `ptaf_fallback_code = 'pass'` или NULL — WAF block алерт не создаётся. --- ## Основной запрос Утилита использует один объединённый запрос. Клиенты с `waf_provider IS NULL` игнорируются: ```sql SELECT s.sid, s.domain_name, s.aliases, a.client_title, ci.rps_limit, ci.rps_commercial_limit, COALESCE(a.four_hundred, 20) as limit_4xx, COALESCE(a.five_hundred, 10) as limit_5xx, COALESCE(a.ptaf_fallback_code_alert_count, 1) as ptaf_fallback_code_alert_count, ci.waf_provider, ci.ptaf_fallback_code FROM ( SELECT sid, domain_name, aliases FROM sp_info WHERE sid IS NOT NULL UNION SELECT sid, domain_name, aliases FROM manual_info WHERE sid IS NOT NULL ) s LEFT JOIN apps_settings a ON s.sid = a.l7resourceid LEFT JOIN client_info ci ON a.client_title = ci.client_title WHERE ci.waf_provider IS NOT NULL ORDER BY a.client_title, s.sid; ``` Ресурсы без привязки к клиенту (`client_title IS NULL`) и клиенты без `waf_provider` — **пропускаются**. --- ## Управление данными ### Добавление нового клиента ```sql -- Шаг 1: ресурс появится автоматически из sp_info (если интеграция настроена) -- Или добавить вручную: INSERT INTO manual_info (sid, domain_name, aliases) VALUES ('99999', 'example.com', '["www.example.com"]'); -- Шаг 2: привязать ресурс к клиенту INSERT INTO apps_settings (l7resourceid, client_title) VALUES ('99999', 'Название клиента'); -- Шаг 3: задать провайдера, лимиты и код блокировки PTAF -- waf_provider обязателен — без него клиент будет игнорироваться INSERT INTO client_info (client_title, waf_provider, rps_limit, rps_commercial_limit, ptaf_fallback_code) VALUES ('Название клиента', 'spik', 1800, 1200, '418'); -- для SP клиента: waf_provider = 'sp' -- если PTAF не блокирует: ptaf_fallback_code = 'pass' -- Шаг 4 (опционально): задать индивидуальные пороги ошибок для каждого SID -- По умолчанию four_hundred=20, five_hundred=10, ptaf_fallback_code_alert_count=1 UPDATE apps_settings SET four_hundred = 30 WHERE l7resourceid = 'SID12345'; ``` ### Добавление нового ресурса к существующему клиенту ```sql -- Только шаг 1 и 2: INSERT INTO manual_info (sid, domain_name, aliases) VALUES ('88888', 'new-domain.example.com', '[]'); INSERT INTO apps_settings (l7resourceid, client_title) VALUES ('88888', 'Название клиента'); -- Пороги алертов уже есть в client_info — добавлять не нужно ``` ### Изменение порогов алертов ```sql UPDATE client_info SET rps_limit = 2000, four_hundred = 30 WHERE client_title = 'Название клиента'; ``` ### Смена waf_provider ```sql -- Перевести клиента из spik в sp UPDATE client_info SET waf_provider = 'sp' WHERE client_title = 'Название клиента'; -- Скрыть клиента из всех дашбордов (не удалять) UPDATE client_info SET waf_provider = NULL WHERE client_title = 'Название клиента'; ``` > После смены `waf_provider` при следующем запуске генератора старые алерты будут удалены автоматически и созданы новые в нужной группе. ### Настройка WAF block алерта ```sql -- Задать код блокировки PTAF для клиента UPDATE client_info SET ptaf_fallback_code = '418' WHERE client_title = 'Название клиента'; -- Отключить WAF block алерт (PTAF работает в режиме pass) UPDATE client_info SET ptaf_fallback_code = 'pass' WHERE client_title = 'Название клиента'; -- Изменить порог для конкретного SID (по умолчанию 1 штука за минуту) UPDATE apps_settings SET ptaf_fallback_code_alert_count = 5 WHERE l7resourceid = 'SID12345'; ``` ### Изменение порогов ошибок для конкретного SID ```sql -- Изменить порог 4xx для конкретного домена UPDATE apps_settings SET four_hundred = 30 WHERE l7resourceid = 'SID12345'; -- Изменить порог 5xx для конкретного домена UPDATE apps_settings SET five_hundred = 5 WHERE l7resourceid = 'SID12345'; ``` ### Отключение алерта для клиента ```sql -- Отключить только RPS алерт UPDATE client_info SET rps_limit = NULL WHERE client_title = 'Название клиента'; -- Отключить WAF block алерт UPDATE client_info SET ptaf_fallback_code = 'pass' WHERE client_title = 'Название клиента'; -- Отключить все динамические алерты UPDATE client_info SET rps_limit = NULL, ptaf_fallback_code = 'pass' WHERE client_title = 'Название клиента'; ``` ### Удаление клиента из дашборда ```sql -- Удалить привязку всех ресурсов клиента DELETE FROM apps_settings WHERE client_title = 'Название клиента'; -- Удалить пороги (опционально) DELETE FROM client_info WHERE client_title = 'Название клиента'; ``` ### Просмотр всех клиентов с их ресурсами ```sql SELECT a.client_title, COUNT(s.sid) AS domain_count, array_agg(s.sid ORDER BY s.sid) AS sids, ci.rps_limit, ci.ptaf_fallback_code, ci.waf_provider FROM ( SELECT sid FROM sp_info WHERE sid IS NOT NULL UNION SELECT sid FROM manual_info WHERE sid IS NOT NULL ) s JOIN apps_settings a ON s.sid = a.l7resourceid LEFT JOIN client_info ci ON a.client_title = ci.client_title GROUP BY a.client_title, ci.rps_limit, ci.ptaf_fallback_code, ci.waf_provider ORDER BY a.client_title; ``` --- ## Влияние данных на генерацию | Данные | Влияние | |---|---| | Новый SID в `sp_info`/`manual_info` + запись в `apps_settings` | Новый домен добавится в строку клиента | | Новый `client_title` + `waf_provider` в `client_info` | Новая строка клиента в соответствующем дашборде | | Изменение `waf_provider` (`spik` → `sp` или наоборот) | Клиент переносится в другой дашборд, старые алерты удаляются, создаются новые | | Установка `waf_provider = NULL` | Клиент исчезает из всех дашбордов, алерты удаляются | | Изменение `rps_limit` | Пересоздание алерта RPS, обновление красной линии на графике | | Изменение `rps_commercial_limit` | Обновление синей линии на графике | | Изменение `four_hundred` / `five_hundred` в `apps_settings` | Пересоздание алертов 4xx/5xx для конкретного SID | | Изменение `ptaf_fallback_code_alert_count` в `apps_settings` | Пересоздание WAF block алерта для конкретного SID | | Изменение `ptaf_fallback_code` в `client_info` | Пересоздание WAF block алертов для всех SID клиента | | `ptaf_fallback_code = 'pass'` | WAF block алерты удаляются для всех SID клиента | | NULL в `rps_limit` | Алерт RPS удаляется (или не создаётся) | | Удаление из `apps_settings` | Клиент/домен исчезает из дашборда, алерты удаляются автоматически | > Изменения в БД обнаруживаются через хэш (`alerts_hash` в `state.json`). При изменении любого поля — алерты пересоздаются автоматически при следующем запуске. > Устаревшие алерты удаляются автоматически через `deleteObsoleteAlerts()`.