New readme
This commit is contained in:
parent
dbe38ec816
commit
7b711c2317
2 changed files with 410 additions and 316 deletions
367
ARCHITECTURE.md
Normal file
367
ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
# grafana_gen — архитектура и устройство утилиты
|
||||
|
||||
Утилита автоматически генерирует Grafana-дашборды и правила алертинга для клиентов WAF на основе данных из PostgreSQL и шаблонов из Git-репозитория.
|
||||
|
||||
---
|
||||
|
||||
## Обзор потока данных
|
||||
|
||||
```
|
||||
PostgreSQL
|
||||
sp_info + manual_info (UNION)
|
||||
apps_settings
|
||||
client_info
|
||||
│
|
||||
▼
|
||||
fetchClientsData()
|
||||
map[clientTitle]ClientData
|
||||
│
|
||||
├──────────────────────────────────────┐
|
||||
▼ ▼
|
||||
generateSingleDashboard() generateAndSendAlerts()
|
||||
│ │
|
||||
▼ ▼
|
||||
dashboard_template.json alert_rules_template.json
|
||||
(Git-репозиторий) (Git-репозиторий)
|
||||
│ │
|
||||
▼ ▼
|
||||
POST /api/dashboards/db POST/PUT /api/v1/provisioning/alert-rules
|
||||
(Grafana API) (Grafana Provisioning API, параллельно x5)
|
||||
│ │
|
||||
▼ ▼
|
||||
state.json ──── clients_hash state.json ──── alerts_hash
|
||||
└─── alert_template_hash
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Структура файлов
|
||||
|
||||
| Файл | Назначение |
|
||||
|---|---|
|
||||
| `main.go` | Точка входа, оркестрация всего потока |
|
||||
| `config.go` | Константы, структуры `Config`, `ClientData`, `DomainInfo`, `DashboardTemplate` |
|
||||
| `database.go` | Подключение к PostgreSQL, `fetchClientsData()` |
|
||||
| `dashboard.go` | Генерация JSON дашборда из шаблона и данных клиентов |
|
||||
| `panels.go` | Построение отдельных панелей, реестр query-режимов, `applyRPSThreshold()` |
|
||||
| `alerts.go` | Генерация и отправка правил алертинга, параллельный upsert |
|
||||
| `grafana.go` | HTTP-клиент для Grafana API (дашборды, папки) |
|
||||
| `template.go` | Загрузка `dashboard_template.json` и `alert_rules_template.json` |
|
||||
| `state.go` | Чтение/запись `state.json`, обнаружение изменений |
|
||||
| `git.go` | `git clone` / `git pull` шаблонов из репозитория |
|
||||
| `env.go` | Загрузка `.env` файла |
|
||||
| `dashboard_template.json` | JSON-шаблон дашборда (Git-репозиторий) |
|
||||
| `alert_rules_template.json` | JSON-шаблон алертов (Git-репозиторий) |
|
||||
|
||||
---
|
||||
|
||||
## База данных
|
||||
|
||||
### Источник данных
|
||||
|
||||
Данные всегда берутся из **обеих** таблиц одновременно через `UNION`:
|
||||
|
||||
```sql
|
||||
SELECT ... 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
|
||||
```
|
||||
|
||||
Дубликаты по SID схлопываются автоматически (`UNION` без `ALL`).
|
||||
|
||||
### Таблицы
|
||||
|
||||
**`sp_info` / `manual_info`** — список ресурсов:
|
||||
- `sid` — идентификатор ресурса
|
||||
- `domain_name` — основной домен
|
||||
- `aliases` — JSON-массив дополнительных доменов
|
||||
|
||||
**`apps_settings`** — маппинг SID → клиент:
|
||||
- `l7resourceid` — SID ресурса
|
||||
- `client_title` — название клиента (имя тенанта)
|
||||
|
||||
**`client_info`** — настройки мониторинга клиента:
|
||||
- `client_title` — название клиента
|
||||
- `rps_limit` — порог RPS для алерта (NULL = алерт не создавать)
|
||||
- `rps_commercial_limit` — коммерческий лимит RPS для синей линии на графике (NULL = 100)
|
||||
- `four_hundred` — порог 4xx ошибок в % (NULL = алерт не создавать)
|
||||
- `five_hundred` — порог 5xx ошибок в % (NULL = алерт не создавать)
|
||||
|
||||
### Пример добавления нового клиента
|
||||
|
||||
```sql
|
||||
-- 1. Ресурс появится автоматически из sp_info
|
||||
|
||||
-- 2. Привязать к клиенту
|
||||
INSERT INTO apps_settings (l7resourceid, client_title)
|
||||
VALUES ('SID12345', 'Название клиента');
|
||||
|
||||
-- 3. Задать лимиты для алертов (опционально)
|
||||
INSERT INTO client_info (client_title, rps_limit, rps_commercial_limit, four_hundred, five_hundred)
|
||||
VALUES ('Название клиента', 1800, 1200, 20, 10);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаблоны
|
||||
|
||||
Шаблоны хранятся в отдельном Git-репозитории и обновляются при каждом запуске через `git pull`. Изменение шаблона автоматически приводит к пересозданию дашборда и/или алертов.
|
||||
|
||||
### dashboard_template.json
|
||||
|
||||
Описывает структуру дашборда: метаданные, Grafana-переменные, строки (rows), панели.
|
||||
|
||||
**Ключевые секции:**
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "3.1.0",
|
||||
"datasource": { "type": "...", "uid": "..." },
|
||||
"panels": {
|
||||
"rps": { "query_mode": "bucket_logs", ... },
|
||||
"status_codes": { ... },
|
||||
"response_time": { ... },
|
||||
"traffic_combined": { ... }
|
||||
},
|
||||
"layout": {
|
||||
"client_panels": [...],
|
||||
"overview_panels": [...],
|
||||
"overview_row_title": "Обзор"
|
||||
},
|
||||
"templating": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
**Query-режимы панелей** (`query_mode`):
|
||||
|
||||
| Режим | Описание |
|
||||
|---|---|
|
||||
| `bucket_logs` | Запрос к OpenSearch по одному SID |
|
||||
| `multi_sid` | Запрос к OpenSearch по всем SID клиента |
|
||||
| `combined_sids` | Объединённый запрос по SID + алиасам |
|
||||
| `static` | Статические данные без запроса |
|
||||
|
||||
**Обзорные панели** (`overview_panels`) используют Grafana-переменные (`$SID`, `$tenant`, `$node_name`) и отображаются в свёрнутой строке «Обзор» поверх клиентских строк.
|
||||
|
||||
### alert_rules_template.json
|
||||
|
||||
Описывает шаблон для алертов.
|
||||
|
||||
**Структура:**
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.3.0",
|
||||
"defaults": {
|
||||
"receiver": "Telegram PTAF Grafana",
|
||||
"folder": "WAF - PTAF",
|
||||
"group": "PTAF Grafana"
|
||||
},
|
||||
"rps_alert": {
|
||||
"relative_time_range_from": 1800,
|
||||
"annotation_summary": "Превышен порог в {rps_limit} RPS в {client_title}"
|
||||
},
|
||||
"static_alerts": [ ... ]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Генерация дашборда
|
||||
|
||||
Создаётся **один дашборд** со всеми клиентами. Структура дашборда:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Grafana-переменные: tenant, SID, node │
|
||||
├─────────────────────────────────────────┤
|
||||
│ ▶ Обзор (свёрнутая строка) │
|
||||
│ overview_status_codes │
|
||||
│ overview_tenant_per_nodes │
|
||||
│ overview_tenant_per_node │
|
||||
│ overview_uri_top15 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ ▼ Клиент A (развёрнутая строка) │
|
||||
│ RPS | Status codes | Response time │
|
||||
│ Traffic combined │
|
||||
│ [панели по доменам если > 1 домена] │
|
||||
├─────────────────────────────────────────┤
|
||||
│ ▶ Клиент B (свёрнутая строка) │
|
||||
│ ... │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Threshold на графике RPS
|
||||
|
||||
На панель RPS автоматически накладываются цветные линии из `client_info`:
|
||||
|
||||
| Линия | Значение | Источник |
|
||||
|---|---|---|
|
||||
| Синяя | `rps_commercial_limit` | `client_info.rps_commercial_limit` (NULL → 100) |
|
||||
| Красная | `rps_limit` | `client_info.rps_limit` (0 → линия не рисуется) |
|
||||
|
||||
---
|
||||
|
||||
## Алерты
|
||||
|
||||
### Динамические алерты (per client)
|
||||
|
||||
Создаются для каждого клиента у которого задан соответствующий лимит в `client_info`:
|
||||
|
||||
| Тип | Условие | Структура запроса |
|
||||
|---|---|---|
|
||||
| RPS | `median(count/60) > rps_limit` | OpenSearch count → math /60 → reduce median → threshold |
|
||||
| 4xx | `(errors/total)*100 > four_hundred` | 2x OpenSearch count → reduce → math % → threshold |
|
||||
| 5xx | `(errors/total)*100 > five_hundred` | 2x OpenSearch count → reduce → math % → threshold |
|
||||
|
||||
UID каждого алерта генерируется детерминированно: `md5(client_title + ":" + type)[:8]`. При повторном запуске алерт обновляется (`PUT`), а не создаётся заново.
|
||||
|
||||
### Статические алерты (всегда присутствуют)
|
||||
|
||||
Описаны в `alert_rules_template.json` в секции `static_alerts`, не зависят от БД:
|
||||
|
||||
| Алерт | Условие | for |
|
||||
|---|---|---|
|
||||
| Use in / | диск `/` > 75% | 3m |
|
||||
| Use in /var/log | диск `/var/log` > 75% | 5m |
|
||||
| CPU Busy | CPU > 75% | 3m |
|
||||
| RAM Busy | RAM > 75% | 3m |
|
||||
| Состояние контейнеров | `docker_container_status == 0` | 2m |
|
||||
| Упала Angie | `angie.service` не active | 1m |
|
||||
|
||||
### Параллельная отправка
|
||||
|
||||
Все алерты (динамические + статические) отправляются параллельно через горутины с ограничением **5 одновременных запросов** к Grafana API:
|
||||
|
||||
```
|
||||
[RPS client1] [RPS client2] [4xx client1] [5xx client2] [static: CPU] ← 5 горутин
|
||||
↓ освободился слот
|
||||
[static: RAM] ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State-файл
|
||||
|
||||
Путь по умолчанию: `/var/lib/grafana_gen/state.json`
|
||||
|
||||
Хранит хэши для обнаружения изменений между запусками:
|
||||
|
||||
```json
|
||||
{
|
||||
"last_run": "2026-02-25T10:00:00Z",
|
||||
"template_commit": "a1b2c3d4...",
|
||||
"template_version": "3.1.0",
|
||||
"clients_hash": "sha256...",
|
||||
"client_count": 42,
|
||||
"domain_count": 87,
|
||||
"sids": ["SID001", "SID002", "..."],
|
||||
"alerts_hash": "sha256...",
|
||||
"alert_template_hash": "sha256..."
|
||||
}
|
||||
```
|
||||
|
||||
**Логика запуска:**
|
||||
|
||||
```
|
||||
изменился clients_hash → пересоздать дашборд
|
||||
изменился template_commit → пересоздать дашборд
|
||||
изменился template_version → пересоздать дашборд
|
||||
изменился alerts_hash → переотправить алерты (без пересоздания дашборда)
|
||||
изменился alert_template_hash → переотправить алерты (без пересоздания дашборда)
|
||||
ничего не изменилось → выход без действий (если не указан -force)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Конфигурация
|
||||
|
||||
Приоритет разрешения параметров (от высшего к низшему):
|
||||
|
||||
```
|
||||
1. Флаг командной строки (-grafana-url=...)
|
||||
2. Переменная окружения (GRAFANA_URL=...)
|
||||
3. .env файл (/etc/grafana_gen/grafana_gen.env)
|
||||
4. Константа в config.go (DefaultGrafanaURL)
|
||||
```
|
||||
|
||||
### Пути к .env файлу (перебираются по порядку)
|
||||
|
||||
1. `$GRAFANA_GEN_ENV_FILE` (переменная окружения)
|
||||
2. `/etc/grafana_gen/grafana_gen.env`
|
||||
3. `./grafana_gen.env`
|
||||
4. `./.env`
|
||||
|
||||
### Пример .env файла
|
||||
|
||||
```env
|
||||
# База данных
|
||||
DB_USER=grafana_reader
|
||||
DB_PASSWORD=secret
|
||||
|
||||
# Grafana
|
||||
GRAFANA_URL=https://grafana.example.com
|
||||
GRAFANA_API_KEY=glsa-xxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
# Git (Gitea)
|
||||
GIT_TOKEN=your-gitea-token
|
||||
|
||||
# Алерты
|
||||
ALERTS_DATASOURCE_UID=af84zsvlp9blsa
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Флаги запуска
|
||||
|
||||
| Флаг | Переменная окружения | По умолчанию | Описание |
|
||||
|---|---|---|---|
|
||||
| `-db-host` | — | `10.100.10.8` | PostgreSQL хост |
|
||||
| `-db-port` | — | `5432` | PostgreSQL порт |
|
||||
| `-db-user` | `DB_USER` | — | PostgreSQL пользователь |
|
||||
| `-db-password` | `DB_PASSWORD` | — | PostgreSQL пароль |
|
||||
| `-db-name` | — | `waf_info` | PostgreSQL база данных |
|
||||
| `-grafana-url` | `GRAFANA_URL` | — | URL Grafana |
|
||||
| `-grafana-api-key` | `GRAFANA_API_KEY` | — | Grafana API ключ |
|
||||
| `-grafana-folder` | `GRAFANA_FOLDER` | `WAF - Auto Generated` | Папка для дашбордов |
|
||||
| `-dashboard-title` | `DASHBOARD_TITLE` | `PT AF Nodes` | Название дашборда |
|
||||
| `-alerts-folder` | `ALERTS_FOLDER` | `WAF - PTAF` | Папка для алертов |
|
||||
| `-alerts-receiver` | `ALERTS_RECEIVER` | `Telegram PTAF Grafana` | Получатель уведомлений |
|
||||
| `-alerts-group` | `ALERTS_GROUP` | `PTAF Grafana` | Группа алертов |
|
||||
| `-alerts-datasource-uid` | `ALERTS_DATASOURCE_UID` | `af84zsvlp9blsa` | UID datasource OpenSearch |
|
||||
| `-git-token` | `GIT_TOKEN` | — | Gitea токен |
|
||||
| `-templates-repo` | — | `svc-git.cirex.ru/...` | URL Git-репозитория шаблонов |
|
||||
| `-templates-branch` | — | `master` | Ветка шаблонов |
|
||||
| `-templates-path` | — | `/etc/grafana_gen/templates` | Локальный путь шаблонов |
|
||||
| `-skip-git-pull` | — | `false` | Не обновлять шаблоны из Git |
|
||||
| `-state-file` | — | `/var/lib/grafana_gen/state.json` | Путь к state-файлу |
|
||||
| `-dry-run` | — | `false` | Не отправлять в Grafana, только логировать |
|
||||
| `-force` | — | `false` | Пересоздать всё даже без изменений |
|
||||
|
||||
### Примеры запуска
|
||||
|
||||
```bash
|
||||
# Обычный запуск
|
||||
./grafana_gen
|
||||
|
||||
# Тестовый прогон без отправки в Grafana
|
||||
./grafana_gen -dry-run
|
||||
|
||||
# Принудительное пересоздание всего
|
||||
./grafana_gen -force
|
||||
|
||||
# Без обновления шаблонов из Git
|
||||
./grafana_gen -skip-git-pull
|
||||
|
||||
# Явное указание всех параметров
|
||||
./grafana_gen \
|
||||
-db-host=10.100.10.8 \
|
||||
-db-user=reader \
|
||||
-db-password=secret \
|
||||
-grafana-url=https://grafana.example.com \
|
||||
-grafana-api-key=glsa-xxx
|
||||
```
|
||||
359
README.md
359
README.md
|
|
@ -1,344 +1,71 @@
|
|||
# grafana_gen — Руководство пользователя
|
||||
# grafana_gen
|
||||
|
||||
Утилита автоматически генерирует дашборды Grafana на основе данных из PostgreSQL. При каждом запуске она читает список клиентов и их ресурсов из БД, сравнивает с предыдущим состоянием и пересоздаёт единый дашборд только при наличии изменений.
|
||||
Утилита автоматической генерации Grafana-дашбордов и правил алертинга для клиентов WAF/PTAF.
|
||||
|
||||
---
|
||||
## Что делает
|
||||
|
||||
## Как это работает
|
||||
- Читает список клиентов и их SID из PostgreSQL (`sp_info` + `manual_info`)
|
||||
- Генерирует единый дашборд с панелями на каждого клиента
|
||||
- Создаёт правила алертинга: RPS, 4xx/5xx ошибки (пороги из БД), CPU, RAM, диск, контейнеры, Angie
|
||||
- Обновляет шаблоны дашборда и алертов из Git-репозитория при каждом запуске
|
||||
- Пропускает запуск если ничего не изменилось (отслеживает хэши)
|
||||
|
||||
```
|
||||
PostgreSQL (test_info)
|
||||
↓
|
||||
Список клиентов и ресурсов (SID, domain_name, aliases)
|
||||
↓
|
||||
Проверка изменений (state.json)
|
||||
↓ нет изменений → выход
|
||||
Загрузка шаблона (dashboard_template.json из Git)
|
||||
↓
|
||||
Генерация JSON дашборда
|
||||
↓
|
||||
Grafana API → создание/обновление дашборда
|
||||
```
|
||||
|
||||
На каждый запуск создаётся **один дашборд** со всеми клиентами. Каждый клиент отображается как свёрнутая строка (collapsed row), внутри которой — панели по каждому ресурсу.
|
||||
|
||||
---
|
||||
|
||||
## Требования
|
||||
|
||||
- Go 1.21+
|
||||
- PostgreSQL с базой `test_info`
|
||||
- Grafana с API-доступом (Service Account Token или Legacy API Key)
|
||||
- Git (для загрузки шаблонов)
|
||||
- Доступ к Gitea-репозиторию с шаблоном
|
||||
|
||||
---
|
||||
|
||||
## Установка и запуск
|
||||
|
||||
### Сборка
|
||||
|
||||
```bash
|
||||
git clone <репозиторий утилиты>
|
||||
cd grafana_gen
|
||||
go build -o grafana_gen .
|
||||
```
|
||||
|
||||
### Первый запуск
|
||||
## Быстрый старт
|
||||
|
||||
```bash
|
||||
# Минимальный запуск
|
||||
./grafana_gen \
|
||||
-grafana-url https://grafana.example.com \
|
||||
-grafana-api-key glsa_xxxxxxxxxxxx \
|
||||
-db-user waf_reader \
|
||||
-db-password secret
|
||||
```
|
||||
-db-user=reader \
|
||||
-db-password=secret \
|
||||
-grafana-url=https://grafana.example.com \
|
||||
-grafana-api-key=glsa-xxx
|
||||
|
||||
### Через .env файл (рекомендуется)
|
||||
|
||||
Создайте файл `/etc/grafana_gen/grafana_gen.env`:
|
||||
|
||||
```env
|
||||
GRAFANA_URL=https://grafana.example.com
|
||||
GRAFANA_API_KEY=glsa_xxxxxxxxxxxx
|
||||
DB_USER=waf_reader
|
||||
DB_PASSWORD=secret
|
||||
GIT_TOKEN=your-gitea-token
|
||||
```
|
||||
|
||||
Затем просто:
|
||||
|
||||
```bash
|
||||
# Или через .env файл (приоритет ниже переменных окружения)
|
||||
cp grafana_gen.env.example /etc/grafana_gen/grafana_gen.env
|
||||
./grafana_gen
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Конфигурация
|
||||
|
||||
### Способы задать параметры (в порядке приоритета)
|
||||
Параметры разрешаются в порядке приоритета:
|
||||
**флаг → переменная окружения → .env файл → константа в config.go**
|
||||
|
||||
| Приоритет | Способ | Пример |
|
||||
|-----------|--------|--------|
|
||||
| 1 | Флаг командной строки | `-grafana-url https://...` |
|
||||
| 2 | Переменная окружения | `export GRAFANA_URL=https://...` |
|
||||
| 3 | `.env` файл | `GRAFANA_URL=https://...` |
|
||||
| 4 | Константа в `config.go` | `DefaultGrafanaURL = "https://..."` |
|
||||
Минимально необходимые параметры:
|
||||
|
||||
### Пути поиска .env файла
|
||||
| Параметр | Флаг | Переменная окружения |
|
||||
|---|---|---|
|
||||
| PostgreSQL пользователь | `-db-user` | `DB_USER` |
|
||||
| PostgreSQL пароль | `-db-password` | `DB_PASSWORD` |
|
||||
| URL Grafana | `-grafana-url` | `GRAFANA_URL` |
|
||||
| Grafana API ключ | `-grafana-api-key` | `GRAFANA_API_KEY` |
|
||||
|
||||
Утилита ищет `.env` файл в следующем порядке:
|
||||
Пример `.env` файла:
|
||||
|
||||
1. Путь из переменной `GRAFANA_GEN_ENV_FILE`
|
||||
2. `/etc/grafana_gen/grafana_gen.env`
|
||||
3. `./grafana_gen.env` (рядом с бинарником)
|
||||
4. `./.env`
|
||||
|
||||
---
|
||||
|
||||
## Флаги командной строки
|
||||
|
||||
### База данных
|
||||
|
||||
| Флаг | Переменная окружения | По умолчанию | Описание |
|
||||
|------|---------------------|--------------|----------|
|
||||
| `-db-host` | — | `10.100.10.8` | Хост PostgreSQL |
|
||||
| `-db-port` | — | `5432` | Порт PostgreSQL |
|
||||
| `-db-user` | `DB_USER` | — | Пользователь БД (**обязательно**) |
|
||||
| `-db-password` | `DB_PASSWORD` | — | Пароль БД (**обязательно**) |
|
||||
| `-db-name` | — | `test_info` | Имя базы данных |
|
||||
| `-use-manual` | — | `false` | Использовать таблицу `manual_info` вместо `sp_info` |
|
||||
|
||||
### Grafana
|
||||
|
||||
| Флаг | Переменная окружения | По умолчанию | Описание |
|
||||
|------|---------------------|--------------|----------|
|
||||
| `-grafana-url` | `GRAFANA_URL` | — | URL Grafana (**обязательно**) |
|
||||
| `-grafana-api-key` | `GRAFANA_API_KEY` | — | API-ключ Grafana (**обязательно**) |
|
||||
| `-grafana-folder` | `GRAFANA_FOLDER` | `WAF - Auto Generated` | Папка в Grafana для дашборда |
|
||||
| `-dashboard-title` | `DASHBOARD_TITLE` | `PT AF Nodes` | Название дашборда |
|
||||
|
||||
### Git / шаблоны
|
||||
|
||||
| Флаг | Переменная окружения | По умолчанию | Описание |
|
||||
|------|---------------------|--------------|----------|
|
||||
| `-git-token` | `GIT_TOKEN` | — | Токен доступа к Gitea |
|
||||
| `-templates-repo` | — | *(см. config.go)* | URL Git-репозитория с шаблонами |
|
||||
| `-templates-branch` | — | `master` | Ветка репозитория |
|
||||
| `-templates-path` | — | `/etc/grafana_gen/templates` | Локальный путь для шаблонов |
|
||||
| `-skip-git-pull` | — | `false` | Не обновлять шаблоны из Git |
|
||||
|
||||
### Управление запуском
|
||||
|
||||
| Флаг | По умолчанию | Описание |
|
||||
|------|--------------|----------|
|
||||
| `-dry-run` | `false` | Сгенерировать JSON, но не отправлять в Grafana |
|
||||
| `-force` | `false` | Принудительная регенерация даже без изменений |
|
||||
| `-state-file` | `/var/lib/grafana_gen/state.json` | Путь к файлу состояния |
|
||||
|
||||
---
|
||||
|
||||
## Приоритет параметров
|
||||
|
||||
Пример: если одновременно задан флаг `-grafana-api-key`, переменная `GRAFANA_API_KEY` и значение в `.env` — используется **флаг командной строки** как наиболее приоритетный.
|
||||
|
||||
```
|
||||
Флаг CLI > Переменная окружения > .env файл > константа в config.go
|
||||
```env
|
||||
DB_USER=grafana_reader
|
||||
DB_PASSWORD=secret
|
||||
GRAFANA_URL=https://grafana.example.com
|
||||
GRAFANA_API_KEY=glsa-xxxxxxxxxxxxxxxxxxxx
|
||||
GIT_TOKEN=your-gitea-token
|
||||
```
|
||||
|
||||
Это позволяет безопасно хранить секреты в `.env` и при необходимости переопределять их на лету без изменения файлов.
|
||||
|
||||
---
|
||||
|
||||
## State-файл
|
||||
|
||||
Утилита сохраняет состояние после каждого успешного запуска в JSON-файл (по умолчанию `/var/lib/grafana_gen/state.json`).
|
||||
|
||||
При следующем запуске сравниваются:
|
||||
|
||||
- Коммит шаблона в Git
|
||||
- Версия шаблона (`version` в `dashboard_template.json`)
|
||||
- SHA-256 хэш данных из БД (список клиентов, доменов, SID)
|
||||
- Количество клиентов и доменов
|
||||
|
||||
Если ничего не изменилось — дашборд не пересоздаётся, утилита завершается с кодом 0.
|
||||
|
||||
```
|
||||
=== No Changes Detected ===
|
||||
No changes in templates or database since last run.
|
||||
Skipping dashboard generation.
|
||||
|
||||
Use -force flag to regenerate anyway.
|
||||
```
|
||||
|
||||
Если изменения есть — выводится подробный отчёт:
|
||||
|
||||
```
|
||||
=== Changes Detected ===
|
||||
Changes detected:
|
||||
Template commit changed: abc12345 -> def67890
|
||||
Database content changed
|
||||
- New SIDs: [SID_001, SID_002]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Режим dry-run
|
||||
|
||||
Позволяет проверить что будет сгенерировано без отправки в Grafana:
|
||||
## Полезные флаги
|
||||
|
||||
```bash
|
||||
./grafana_gen -dry-run
|
||||
-dry-run # Сгенерировать и показать в логах, не отправлять в Grafana
|
||||
-force # Пересоздать всё даже если изменений нет
|
||||
-skip-git-pull # Не обновлять шаблоны из Git
|
||||
```
|
||||
|
||||
В лог выводится превью JSON дашборда и итоговая статистика:
|
||||
## Шаблоны
|
||||
|
||||
```
|
||||
DRY RUN: Dashboard generated but not sent to Grafana
|
||||
=== Summary ===
|
||||
Clients: 12
|
||||
Skipped: 0
|
||||
```
|
||||
Дашборд и алерты строятся по JSON-шаблонам из Git-репозитория:
|
||||
|
||||
---
|
||||
- `dashboard_template.json` — структура и панели дашборда
|
||||
- `alert_rules_template.json` — правила алертинга
|
||||
|
||||
## Запуск через cron
|
||||
Изменение любого шаблона автоматически триггерит пересоздание при следующем запуске.
|
||||
|
||||
Рекомендуемый вариант — запуск каждые 15 минут:
|
||||
## Подробнее
|
||||
|
||||
```cron
|
||||
*/15 * * * * /usr/local/bin/grafana_gen >> /var/log/grafana_gen.log 2>&1
|
||||
```
|
||||
|
||||
Утилита сама определяет нужно ли обновлять дашборд — частые запуски без изменений завершаются мгновенно.
|
||||
|
||||
### Systemd timer (альтернатива)
|
||||
|
||||
`/etc/systemd/system/grafana-gen.service`:
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Grafana Dashboard Generator
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=/etc/grafana_gen/grafana_gen.env
|
||||
ExecStart=/usr/local/bin/grafana_gen
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
```
|
||||
|
||||
`/etc/systemd/system/grafana-gen.timer`:
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Run grafana-gen every 15 minutes
|
||||
|
||||
[Timer]
|
||||
OnBootSec=2min
|
||||
OnUnitActiveSec=15min
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
```
|
||||
|
||||
```bash
|
||||
systemctl enable --now grafana-gen.timer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Типичные сценарии
|
||||
|
||||
### Первое развёртывание
|
||||
|
||||
```bash
|
||||
# 1. Создать .env
|
||||
cp grafana_gen.env.example /etc/grafana_gen/grafana_gen.env
|
||||
vim /etc/grafana_gen/grafana_gen.env
|
||||
|
||||
# 2. Проверить без отправки
|
||||
./grafana_gen -dry-run
|
||||
|
||||
# 3. Создать дашборд
|
||||
./grafana_gen
|
||||
```
|
||||
|
||||
### Принудительное обновление после изменения шаблона
|
||||
|
||||
```bash
|
||||
./grafana_gen -force
|
||||
```
|
||||
|
||||
### Переключение на резервную БД
|
||||
|
||||
```bash
|
||||
./grafana_gen -db-host 10.10.10.5
|
||||
```
|
||||
|
||||
### Тестирование с другим шаблоном
|
||||
|
||||
```bash
|
||||
./grafana_gen \
|
||||
-templates-path /tmp/my-templates \
|
||||
-skip-git-pull \
|
||||
-dry-run
|
||||
```
|
||||
|
||||
### Использование таблицы ручного ввода
|
||||
|
||||
```bash
|
||||
./grafana_gen -use-manual
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Структура БД
|
||||
|
||||
Утилита читает данные из двух таблиц базы `test_info`.
|
||||
|
||||
### Таблица `sp_info` (основная)
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `sid` | text | Идентификатор ресурса |
|
||||
| `domain_name` | text | Доменное имя |
|
||||
| `aliases` | jsonb | JSON-массив дополнительных доменов |
|
||||
|
||||
### Таблица `apps_settings` (справочник клиентов)
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `l7resourceid` | text | SID ресурса (связь с `sp_info.sid`) |
|
||||
| `client_title` | text | Название клиента |
|
||||
|
||||
Если `client_title` не найден — клиент группируется под именем `Unknown`.
|
||||
|
||||
Таблица `manual_info` имеет ту же структуру, что и `sp_info`, и используется при флаге `-use-manual` для ручного управления данными без изменения основной таблицы.
|
||||
|
||||
---
|
||||
|
||||
## Файловая система
|
||||
|
||||
```
|
||||
/etc/grafana_gen/
|
||||
├── grafana_gen.env # Конфигурация (секреты)
|
||||
└── templates/ # Клонированный Git-репозиторий с шаблонами
|
||||
└── dashboard_template.json
|
||||
|
||||
/var/lib/grafana_gen/
|
||||
└── state.json # Состояние последнего запуска
|
||||
|
||||
/usr/local/bin/
|
||||
└── grafana_gen # Бинарник утилиты
|
||||
```
|
||||
|
||||
### Права доступа
|
||||
|
||||
```bash
|
||||
# Директории
|
||||
install -d -m 755 /etc/grafana_gen
|
||||
install -d -m 755 /var/lib/grafana_gen
|
||||
|
||||
# .env файл — только для владельца процесса
|
||||
chmod 600 /etc/grafana_gen/grafana_gen.env
|
||||
```
|
||||
См. [ARCHITECTURE.md](ARCHITECTURE.md).
|
||||
Loading…
Add table
Reference in a new issue