mirror of
https://gitverse.ru/kpa39l/monitoring.git
synced 2026-09-29 09:55:09 +00:00
139 lines
6.4 KiB
Python
139 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
# Генератор дашборда Grafana "GoToSocial" — по стилю vesti.json
|
|
# Результат: grafana/dashboards/gotosocial/gotosocial.json
|
|
import json, os, uuid
|
|
|
|
DS = {"type": "prometheus", "uid": "Prometheus"}
|
|
F = "bigbox:9464"
|
|
|
|
def tgt(expr, legend="", ref="A"):
|
|
return {"datasource": DS, "expr": expr, "legendFormat": legend, "refId": ref}
|
|
|
|
def stat_panel(title, expr, x, y, w=4, h=3, mapping=None, unit="short", thresholds=None):
|
|
if mapping is None:
|
|
mapping = {"0": {"color": "red", "text": "DOWN"}, "1": {"color": "green", "text": "UP"}}
|
|
if thresholds is None:
|
|
thresholds = {"mode": "absolute", "steps": [
|
|
{"color": "red", "value": None}, {"color": "green", "value": 1}]}
|
|
return {
|
|
"datasource": DS,
|
|
"fieldConfig": {"defaults": {
|
|
"color": {"mode": "thresholds"},
|
|
"mappings": [{"options": mapping, "type": "value"}],
|
|
"thresholds": thresholds, "unit": unit},
|
|
"overrides": []},
|
|
"gridPos": {"h": h, "w": w, "x": x, "y": y},
|
|
"id": uuid.uuid4().int & 0xFFFF,
|
|
"options": {
|
|
"colorMode": "background", "graphMode": "none", "justifyMode": "auto",
|
|
"orientation": "auto",
|
|
"reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": False},
|
|
"textMode": "auto"},
|
|
"pluginVersion": "11.1.0",
|
|
"targets": [tgt(expr, "")],
|
|
"title": title, "type": "stat",
|
|
}
|
|
|
|
def ts_panel(title, exprs, x, y, w=12, h=4, unit="short", legend=False):
|
|
# exprs: list of (expr, legend) tuples
|
|
return {
|
|
"datasource": DS,
|
|
"fieldConfig": {"defaults": {
|
|
"color": {"mode": "palette-classic"},
|
|
"custom": {
|
|
"axisCenteredZero": False, "axisColorMode": "text", "axisLabel": "",
|
|
"axisPlacement": "auto", "drawStyle": "line", "fillOpacity": 10,
|
|
"gradientMode": "none",
|
|
"hideFrom": {"legend": False, "tooltip": False, "viz": False},
|
|
"lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5,
|
|
"scaleDistribution": {"type": "linear"}, "showPoints": "never",
|
|
"spanNulls": False, "stacking": {"group": "A", "mode": "none"},
|
|
"thresholdsStyle": {"mode": "off"}},
|
|
"mappings": [], "thresholds": {"mode": "absolute", "steps": [
|
|
{"color": "green", "value": None}]},
|
|
"unit": unit}, "overrides": []},
|
|
"gridPos": {"h": h, "w": w, "x": x, "y": y},
|
|
"id": uuid.uuid4().int & 0xFFFF,
|
|
"options": {"legend": {"calcs": [], "displayMode": "list", "placement": "bottom",
|
|
"showLegend": legend},
|
|
"tooltip": {"mode": "multi", "sort": "none"}},
|
|
"targets": [tgt(e, l) for e, l in exprs],
|
|
"title": title, "type": "timeseries",
|
|
}
|
|
|
|
def row(title, y):
|
|
return {"collapsed": False, "gridPos": {"h": 1, "w": 24, "x": 0, "y": y},
|
|
"id": uuid.uuid4().int & 0xFFFF, "panels": [], "title": title, "type": "row"}
|
|
|
|
panels = []
|
|
y = 0
|
|
|
|
# ---- Доступность ----
|
|
panels.append(row("Доступность", y)); y += 1
|
|
panels.append(stat_panel("Инстанс жив (total users)",
|
|
f'gotosocial_instance_total_users{{instance="{F}"}}', 0, y, w=8, h=3)); y += 3
|
|
|
|
# ---- Instance ----
|
|
panels.append(row("Инстанс", y)); y += 1
|
|
panels.append(ts_panel("Пользователи", [(f'gotosocial_instance_total_users{{instance="{F}"}}', "users")], 0, y, w=8, h=4))
|
|
panels.append(ts_panel("Статусы", [(f'gotosocial_instance_total_statuses{{instance="{F}"}}', "statuses")], 8, y, w=8, h=4))
|
|
panels.append(ts_panel("Федерирующиеся инстансы", [(f'gotosocial_instance_total_federating_instances{{instance="{F}"}}', "federating")], 16, y, w=8, h=4)); y += 4
|
|
|
|
# ---- Workers ----
|
|
panels.append(row("Воркеры", y)); y += 1
|
|
workers = ["client_api", "fedi_api", "processing", "delivery", "dereference", "webpush"]
|
|
count_exprs = [(f'gotosocial_workers_{w}_count{{instance="{F}"}}', w) for w in workers]
|
|
queue_exprs = [(f'gotosocial_workers_{w}_queue{{instance="{F}"}}', w) for w in workers]
|
|
panels.append(ts_panel("Воркеры: count (обработано)", count_exprs, 0, y, w=12, h=4, legend=True))
|
|
panels.append(ts_panel("Воркеры: queue (очередь)", queue_exprs, 12, y, w=12, h=4, legend=True)); y += 4
|
|
|
|
# ---- HTTP ----
|
|
panels.append(row("HTTP", y)); y += 1
|
|
panels.append(ts_panel("Запросы/с (все routes)",
|
|
[(f'rate(http_server_requests_total{{otel_scope_name="gin",instance="{F}"}})',
|
|
"req/s")], 0, y, w=8, h=4))
|
|
panels.append(ts_panel("Активные запросы",
|
|
[(f'http_server_requests_active{{instance="{F}"}}', "active")], 8, y, w=8, h=4))
|
|
panels.append(ts_panel("Длительность (p50)",
|
|
[(f'http_server_duration_milliseconds{{quantile="0.5",instance="{F}"}}', "p50 ms")],
|
|
16, y, w=8, h=4)); y += 4
|
|
|
|
# ---- SQL ----
|
|
panels.append(row("SQL", y)); y += 1
|
|
panels.append(ts_panel("SQL соединения",
|
|
[(f'go_sql_connections_open{{instance="{F}"}}', "open"),
|
|
(f'go_sql_connections_in_use{{instance="{F}"}}', "in_use")], 0, y, w=12, h=4, legend=True))
|
|
panels.append(ts_panel("SQL запросы (p50 ms)",
|
|
[(f'go_sql_query_timing_milliseconds{{quantile="0.5",instance="{F}"}}', "p50")],
|
|
12, y, w=12, h=4)); y += 4
|
|
|
|
# ---- Процесс ----
|
|
panels.append(row("Процесс", y)); y += 1
|
|
panels.append(ts_panel("RSS память (GB)",
|
|
[(f'process_resident_memory_bytes{{instance="{F}"}}/1024/1024/1024', "RSS GB")], 0, y, w=8, h=4))
|
|
panels.append(ts_panel("CPU (сек)",
|
|
[(f'process_cpu_seconds_total{{instance="{F}"}}', "cpu s")], 8, y, w=8, h=4))
|
|
panels.append(ts_panel("Открытые FD",
|
|
[(f'process_open_fds{{instance="{F}"}}', "fds")], 16, y, w=8, h=4)); y += 4
|
|
|
|
dash = {
|
|
"annotations": {"list": []},
|
|
"editable": True,
|
|
"fiscalYearStartMonth": 1,
|
|
"graphTooltip": 0,
|
|
"id": uuid.uuid4().int & 0xFFFF,
|
|
"links": [], "panels": panels, "refresh": "30s",
|
|
"tags": ["gotosocial"],
|
|
"title": "GoToSocial",
|
|
"type": "dashboard",
|
|
"uid": "gotosocial-main",
|
|
"version": 1,
|
|
"schemaVersion": 1,
|
|
}
|
|
|
|
outdir = os.path.join(os.path.dirname(__file__), "..", "grafana", "dashboards", "gotosocial")
|
|
os.makedirs(outdir, exist_ok=True)
|
|
out = os.path.join(outdir, "gotosocial.json")
|
|
with open(out, "w") as f:
|
|
json.dump(dash, f, ensure_ascii=False, indent=1)
|
|
print("OK:", out, len(panels), "panels") |