DatabaseUnavailable (vidconf_db_up == 0, for: 30s, critical) и DbConnectionPoolNearExhaustion/RedisConnectionPoolNearExhaustion (занято > 80% дольше минуты, warning) — сигнал оператору, не автолечение: healthcheck backend'а по решению оператора остаётся мягким, рестарт при недоступной БД оборвал бы WS у всех, кто в конференциях. Дашборд Grafana «БД и пулы соединений» — занятость пулов на графике, следующий нагрузочный тест будут смотреть глазами.
174 lines
8.8 KiB
JSON
174 lines
8.8 KiB
JSON
{
|
||
"title": "БД и пулы соединений",
|
||
"description": "Доступность БД (vidconf_db_up) и занятость основных пулов (SQLAlchemy/БД, Redis) — метрики читаются вне самих пулов, доступны и при их исчерпании (сессия 33, разбор инцидента 07.08 — .forcc/session-results/32-loadtest-07-08-debug.md). Пороги алертов см. deploy/monitoring/alerts.yml (группа vidconf-db).",
|
||
"uid": "vidconf-db-pool",
|
||
"editable": false,
|
||
"timezone": "browser",
|
||
"schemaVersion": 39,
|
||
"version": 1,
|
||
"time": { "from": "now-1h", "to": "now" },
|
||
"refresh": "10s",
|
||
"tags": ["vidconf", "db", "pool"],
|
||
"panels": [
|
||
{
|
||
"id": 1,
|
||
"title": "БД доступна",
|
||
"description": "vidconf_db_up — отдельное соединение вне основного пула (core/db.py::check_db_up). Алерт DatabaseUnavailable, for: 30s.",
|
||
"type": "stat",
|
||
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 0 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"mappings": [
|
||
{ "type": "value", "options": { "0": { "text": "DOWN", "color": "red" }, "1": { "text": "UP", "color": "green" } } }
|
||
],
|
||
"thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }, { "color": "green", "value": 1 }] }
|
||
},
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_db_up", "refId": "A" }
|
||
]
|
||
},
|
||
{
|
||
"id": 2,
|
||
"title": "Занятость пула БД сейчас, %",
|
||
"description": "vidconf_db_pool_checked_out / (vidconf_db_pool_size + vidconf_db_pool_max_overflow) * 100. Порог алерта DbConnectionPoolNearExhaustion — 80% дольше минуты.",
|
||
"type": "stat",
|
||
"gridPos": { "h": 4, "w": 6, "x": 6, "y": 0 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "percent",
|
||
"min": 0,
|
||
"max": 100,
|
||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "orange", "value": 60 }, { "color": "red", "value": 80 }] }
|
||
},
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"expr": "(vidconf_db_pool_checked_out / (vidconf_db_pool_size + vidconf_db_pool_max_overflow)) * 100",
|
||
"refId": "A"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 3,
|
||
"title": "Занятость пула Redis сейчас, %",
|
||
"description": "vidconf_redis_pool_in_use / vidconf_redis_pool_max_connections * 100. Порог алерта RedisConnectionPoolNearExhaustion — 80% дольше минуты.",
|
||
"type": "stat",
|
||
"gridPos": { "h": 4, "w": 6, "x": 12, "y": 0 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "percent",
|
||
"min": 0,
|
||
"max": 100,
|
||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "orange", "value": 60 }, { "color": "red", "value": 80 }] }
|
||
},
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"expr": "(vidconf_redis_pool_in_use / vidconf_redis_pool_max_connections) * 100",
|
||
"refId": "A"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 4,
|
||
"title": "Активных алертов группы vidconf-db",
|
||
"description": "ALERTS{alertname=~\"DatabaseUnavailable|.*PoolNearExhaustion\", alertstate=\"firing\"} — снимок того, что прямо сейчас видит Alertmanager/страница Alerts.",
|
||
"type": "stat",
|
||
"gridPos": { "h": 4, "w": 6, "x": 18, "y": 0 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "red", "value": 1 }] }
|
||
},
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"expr": "count(ALERTS{alertname=~\"DatabaseUnavailable|.*PoolNearExhaustion\", alertstate=\"firing\"}) OR on() vector(0)",
|
||
"refId": "A"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 5,
|
||
"title": "Занятость пула БД (соединений)",
|
||
"description": "vidconf_db_pool_checked_out на фоне вместимости (size + max_overflow) — эта картина должна расти под нагрузочным тестом до срабатывания алерта. Ранний сигнал: в инциденте 07.08 занятость росла постепенно по мере входа участников в комнату, а не рывком от общей HTTP-нагрузки.",
|
||
"type": "timeseries",
|
||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 4 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": { "custom": { "drawStyle": "line", "fillOpacity": 10 } },
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_db_pool_checked_out", "legendFormat": "занято", "refId": "A" },
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_db_pool_size + vidconf_db_pool_max_overflow", "legendFormat": "вместимость (size+overflow)", "refId": "B" }
|
||
]
|
||
},
|
||
{
|
||
"id": 6,
|
||
"title": "Занятость пула Redis (соединений)",
|
||
"description": "vidconf_redis_pool_in_use на фоне vidconf_redis_pool_max_connections. Второй потолок того же класса, что у БД (закрыт в 0.0.31, redis-py 8 сменил дефолт max_connections на 100).",
|
||
"type": "timeseries",
|
||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 4 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": { "custom": { "drawStyle": "line", "fillOpacity": 10 } },
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_redis_pool_in_use", "legendFormat": "занято", "refId": "A" },
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_redis_pool_max_connections", "legendFormat": "вместимость", "refId": "B" }
|
||
]
|
||
},
|
||
{
|
||
"id": 7,
|
||
"title": "БД доступна во времени",
|
||
"description": "vidconf_db_up как временной ряд — удобно видеть провал целиком (начало/длительность отказа), не только текущее состояние.",
|
||
"type": "timeseries",
|
||
"gridPos": { "h": 6, "w": 12, "x": 0, "y": 12 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"min": 0,
|
||
"max": 1,
|
||
"custom": { "drawStyle": "line", "fillOpacity": 20, "lineInterpolation": "stepAfter" },
|
||
"mappings": [
|
||
{ "type": "value", "options": { "0": { "text": "DOWN" }, "1": { "text": "UP" } } }
|
||
]
|
||
},
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_db_up", "legendFormat": "db_up", "refId": "A" }
|
||
]
|
||
},
|
||
{
|
||
"id": 8,
|
||
"title": "Сеансы failed / очереди Celery (для сверки с общей нагрузкой)",
|
||
"description": "Тот же контекст, что на дашборде «Пайплайны пост-обработки» — здесь рядом с пулами, чтобы не переключаться между дашбордами при разборе инцидента.",
|
||
"type": "timeseries",
|
||
"gridPos": { "h": 6, "w": 12, "x": 12, "y": 12 },
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"fieldConfig": {
|
||
"defaults": { "custom": { "drawStyle": "line", "fillOpacity": 5 } },
|
||
"overrides": []
|
||
},
|
||
"targets": [
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "vidconf_pipeline_sessions{status=\"failed\"}", "legendFormat": "сеансов failed", "refId": "A" },
|
||
{ "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(vidconf_celery_queue_depth)", "legendFormat": "глубина очередей (сумма)", "refId": "B" }
|
||
]
|
||
}
|
||
]
|
||
}
|