diff --git a/grafana/dashboards/gotosocial/gotosocial.json b/grafana/dashboards/gotosocial/gotosocial.json new file mode 100644 index 0000000..abc68f9 --- /dev/null +++ b/grafana/dashboards/gotosocial/gotosocial.json @@ -0,0 +1,1394 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 1, + "graphTooltip": 0, + "id": 36829, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 61628, + "panels": [], + "title": "Доступность", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "red", + "text": "DOWN" + }, + "1": { + "color": "green", + "text": "UP" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 19924, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_instance_total_users{instance=\"bigbox:9464\"}", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Инстанс жив (total users)", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 3952, + "panels": [], + "title": "Инстанс", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 5 + }, + "id": 37747, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_instance_total_users{instance=\"bigbox:9464\"}", + "legendFormat": "users", + "refId": "A" + } + ], + "title": "Пользователи", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 5 + }, + "id": 17678, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_instance_total_statuses{instance=\"bigbox:9464\"}", + "legendFormat": "statuses", + "refId": "A" + } + ], + "title": "Статусы", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 5 + }, + "id": 56960, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_instance_total_federating_instances{instance=\"bigbox:9464\"}", + "legendFormat": "federating", + "refId": "A" + } + ], + "title": "Федерирующиеся инстансы", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 37206, + "panels": [], + "title": "Воркеры", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 16105, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_client_api_count{instance=\"bigbox:9464\"}", + "legendFormat": "client_api", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_fedi_api_count{instance=\"bigbox:9464\"}", + "legendFormat": "fedi_api", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_processing_count{instance=\"bigbox:9464\"}", + "legendFormat": "processing", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_delivery_count{instance=\"bigbox:9464\"}", + "legendFormat": "delivery", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_dereference_count{instance=\"bigbox:9464\"}", + "legendFormat": "dereference", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_webpush_count{instance=\"bigbox:9464\"}", + "legendFormat": "webpush", + "refId": "A" + } + ], + "title": "Воркеры: count (обработано)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 43028, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_client_api_queue{instance=\"bigbox:9464\"}", + "legendFormat": "client_api", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_fedi_api_queue{instance=\"bigbox:9464\"}", + "legendFormat": "fedi_api", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_processing_queue{instance=\"bigbox:9464\"}", + "legendFormat": "processing", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_delivery_queue{instance=\"bigbox:9464\"}", + "legendFormat": "delivery", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_dereference_queue{instance=\"bigbox:9464\"}", + "legendFormat": "dereference", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "gotosocial_workers_webpush_queue{instance=\"bigbox:9464\"}", + "legendFormat": "webpush", + "refId": "A" + } + ], + "title": "Воркеры: queue (очередь)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 8456, + "panels": [], + "title": "HTTP", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 15 + }, + "id": 40056, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "rate(http_server_requests_total{otel_scope_name=\"gin\",instance=\"bigbox:9464\"})", + "legendFormat": "req/s", + "refId": "A" + } + ], + "title": "Запросы/с (все routes)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 15 + }, + "id": 21650, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "http_server_requests_active{instance=\"bigbox:9464\"}", + "legendFormat": "active", + "refId": "A" + } + ], + "title": "Активные запросы", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 15 + }, + "id": 13778, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "http_server_duration_milliseconds{quantile=\"0.5\",instance=\"bigbox:9464\"}", + "legendFormat": "p50 ms", + "refId": "A" + } + ], + "title": "Длительность (p50)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 28149, + "panels": [], + "title": "SQL", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 15250, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "go_sql_connections_open{instance=\"bigbox:9464\"}", + "legendFormat": "open", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "go_sql_connections_in_use{instance=\"bigbox:9464\"}", + "legendFormat": "in_use", + "refId": "A" + } + ], + "title": "SQL соединения", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 17526, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "go_sql_query_timing_milliseconds{quantile=\"0.5\",instance=\"bigbox:9464\"}", + "legendFormat": "p50", + "refId": "A" + } + ], + "title": "SQL запросы (p50 ms)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 17448, + "panels": [], + "title": "Процесс", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 25 + }, + "id": 61047, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "process_resident_memory_bytes{instance=\"bigbox:9464\"}/1024/1024/1024", + "legendFormat": "RSS GB", + "refId": "A" + } + ], + "title": "RSS память (GB)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 25 + }, + "id": 8829, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "process_cpu_seconds_total{instance=\"bigbox:9464\"}", + "legendFormat": "cpu s", + "refId": "A" + } + ], + "title": "CPU (сек)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "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": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 25 + }, + "id": 26183, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "Prometheus" + }, + "expr": "process_open_fds{instance=\"bigbox:9464\"}", + "legendFormat": "fds", + "refId": "A" + } + ], + "title": "Открытые FD", + "type": "timeseries" + } + ], + "refresh": "30s", + "tags": [ + "gotosocial" + ], + "title": "GoToSocial", + "type": "dashboard", + "uid": "gotosocial-main", + "version": 1, + "schemaVersion": 1 +} \ No newline at end of file diff --git a/grafana/provisioning/dashboards/dashboards.yml b/grafana/provisioning/dashboards/dashboards.yml index aeb6f8d..1ce01b2 100644 --- a/grafana/provisioning/dashboards/dashboards.yml +++ b/grafana/provisioning/dashboards/dashboards.yml @@ -8,7 +8,7 @@ providers: disableDeletion: false updateIntervalSeconds: 30 options: - path: /var/lib/grafana/dashboards + path: /var/lib/grafana/dashboards/garage-cluster.json - name: 'node-dashboards' orgId: 1 @@ -35,4 +35,13 @@ providers: disableDeletion: false updateIntervalSeconds: 30 options: - path: /var/lib/grafana/dashboards/vesti \ No newline at end of file + path: /var/lib/grafana/dashboards/vesti + + - name: 'gotosocial-dashboards' + orgId: 1 + folder: 'gotosocial' + type: file + disableDeletion: false + updateIntervalSeconds: 30 + options: + path: /var/lib/grafana/dashboards/gotosocial \ No newline at end of file diff --git a/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/.openspec.yaml b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/.openspec.yaml new file mode 100644 index 0000000..eaa6b1c --- /dev/null +++ b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-09-19 diff --git a/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/design.md b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/design.md new file mode 100644 index 0000000..6265cf4 --- /dev/null +++ b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/design.md @@ -0,0 +1,64 @@ +# Design: add-gotosocial-dashboard + +## Context + +См. proposal.md — Why. Метрики GtS уже поступают в VictoriaMetrics (job +`gotosocial` в prometheus.yml active, `gotosocial_instance_total_users` +отвечает с метками `{service="gotosocial",host="bigbox", +instance="bigbox:9464",otel_scope_name="GoToSocial"}`). Задача — только +визуализация: дашборд Grafana + provisioning. + +## Goals / Non-Goals + +**Goals** +- Дашборд `GoToSocial` в Grafana (папка gotosocial) со стандартными + панелями: доступность, инстанс, воркеры, HTTP, SQL, процесс. +- Автоимпорт через provisioning, как у vesti/vinogorod/nodes. + +**Non-Goals** +- Алерты — отдельное изменение (как vesti-alerts). +- Изменения docker-compose/prometheus.yml — не нужны. + +## Decisions + +- **Формат дашборда**: копия стиля `grafana/dashboards/vesti/vesti.json` + (Grafana 11.1, datasource uid "Prometheus", stat/timeseries панели). +- **Доступность**: expr `gotosocial_instance_total_users` + stat (mapping + 0=DOWN/1=UP по наличию значения; VI с блек-значением если нет данных — + зелёный/красный как в vesti). +- **Панели по группам** (row-группировка как vesti): + 1. Доступность (stat): instance total users (инстанс жив) + 2. Instance: `gotosocial_instance_total_{users,statuses,federating_instances}` + 3. Воркеры: 6 пулов `gotosocial_workers_*_{count,queue}` — count на одном + графике (stacks), queue на другом (столбики) + 4. HTTP: `http_server_requests_total` (rate, все routes — sum), + `http_server_requests_active` (gauge) + 5. SQL: `go_sql_connections_{open,in_use}`, `go_sql_query_timing_milliseconds{quantile="0.5"}` + 6. Процесс: `process_resident_memory_bytes` (GB), `process_cpu_seconds_total`, + `process_open_fds` +- **Метка фильтров**: везде `instance="bigbox:9464"` (или service — что + уникальнее; у GtS instance уже bigbox:9464). +- **Provisioning**: новый провайдер в dashboards.yml, folder: gotosocial, + path: /var/lib/grafana/dashboards/gotosocial. + +## Risks / Trade-offs + +- [Крупный дашборд, много панелей] → писать аккуратно, проверять импорт по + grafana.db. +- [Панель доступности по instance_total_users] — если инстанс упадёт, + метрика пропадёт, stat станет красным (нет данных) — ок как индикатор. +- [Новые метрики в новых версиях GtS] — дашборд читает по именам; при + обновлении GtS проверить, что имена не поменялись. + +## Migration Plan + +1. Создать `grafana/dashboards/gotosocial/gotosocial.json`. +2. Добавить провайдер `gotosocial-dashboards` в dashboards.yml. +3. Подождать 30-60с; проверить импорт через grafana.db + (`SELECT uid FROM dashboard WHERE uid LIKE 'gotosocial%'`). +4. Обновить STATUS.md (задача закрыта). +5. Commit+push (gitverse) + mirror-sync. + +## Open Questions + +- Алерты на недоступность/очереди GtS — отдельный change, здесь нет. \ No newline at end of file diff --git a/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/proposal.md b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/proposal.md new file mode 100644 index 0000000..f8c9984 --- /dev/null +++ b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/proposal.md @@ -0,0 +1,36 @@ +## Why + +В STATUS.md GoToSocial открыта задача «Мониторинг: пробросить :9464 (метрики +уже слушают), job в prometheus.yml, дашборд Grafana». Job `gotosocial` +(127.0.0.1:9464 → /metrics) и relabel `instance=bigbox:9464` уже добавлены +ранее и данные реально приходят в VictoriaMetrics +(`gotosocial_instance_total_users` отвечает с метками host/service/instance). +Осталось: дашборд Grafana для метрик GtS + provisioning-провайдер. + +## What Changes + +- Новый дашборд Grafana `grafana/dashboards/gotosocial/gotosocial.json` + (панели: доступность, instance-статистика, воркеры, HTTP, SQL, процесс). +- Новая папка Grafana `gotosocial` + провайдер в + `grafana/provisioning/dashboards/dashboards.yml`. +- Автоимпорт дашборда через provisioning (~30с). +- Обновление STATUS.md (задача закрывается). + +## Capabilities + +### New Capabilities +- `gotosocial-monitoring`: дашборд Grafana с метриками GtS + (instance users/statuses, workers, HTTP, SQL, Go-runtime). + +### Modified Capabilities +- `vesti-alerts`, `grafana-access-control`, `vinograd-wan-monitoring`: + не затрагиваются. + +## Impact + +- `/opt/monitoring/grafana/dashboards/gotosocial/gotosocial.json` — новый. +- `/opt/monitoring/grafana/provisioning/dashboards/dashboards.yml` — +1 провайдер. +- Grafana provisioning автоматически импортирует файл (~30с). +- Никаких изменений в docker-compose/prometheus.yml — job уже есть. +- Откат: удалить файл дашборда и блок провайдера из dashboards.yml + (Grafana удалит визуализацию, данные в VM остаются). \ No newline at end of file diff --git a/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/specs/gotosocial-monitoring/spec.md b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/specs/gotosocial-monitoring/spec.md new file mode 100644 index 0000000..c532a6a --- /dev/null +++ b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/specs/gotosocial-monitoring/spec.md @@ -0,0 +1,64 @@ +# gotosocial-monitoring Specification + +## Purpose + +Дашборд Grafana для метрик GoToSocial (bigbox): наблюдение за инстансом +(пользователи/статусы/федерирующиеся инстансы), воркерами (очереди), +HTTP-активностью, SQL-соединениями и ресурсами процесса. + +## ADDED Requirements + +### Requirement: Job gotosocial в prometheus.yml активен + +- **MUST**: job `gotosocial` опрашивает `127.0.0.1:9464/metrics` и + релейб`instance=bigbox:9464`. +- **MUST**: метрики доступны в VictoriaMetrics с метками + `service="gotosocial"`, `host="bigbox"`, `instance="bigbox:9464"`. + +#### Scenario: Метрики отвечают + +- **GIVEN** job gotosocial настроен в prometheus.yml +- **WHEN** запросить + `/api/v1/series?match[]=gotosocial_instance_total_users` +- **THEN** ответ содержит метрику с `instance: "bigbox:9464"` и данные + +### Requirement: Дашборд gotosocial в Grafana + +- **MUST**: Провайдер `gotosocial-dashboards` в + `grafana/provisioning/dashboards/dashboards.yml` импортирует + `/var/lib/grafana/dashboards/gotosocial` (updateIntervalSeconds: 30). +- **MUST**: Дашборд `grafana/dashboards/gotosocial/gotosocial.json` содержит: + - stat-панель доступности (запрос `gotosocial_instance_total_users` — если + данные есть, служба жива) + - instance-панели: users, statuses, federating_instances + - воркеры: по каждому пулу `gotosocial_workers_*` count+queue + - HTTP: `http_server_requests_total`, `http_server_requests_active` + - SQL: `go_sql_connections_in_use` + - процесс: RSS, CPU секунды, open_fds +- **SHOULD**: панели названы по-русски, структура соответствует стилю vesti.json. + +#### Scenario: Дашборд импортирован + +- **GIVEN** файл дашборда и провайдер добавлены +- **WHEN** пройти 30-60с после изменения provisioning +- **THEN** дашборд `GoToSocial` виден в папке + `gotosocial` (проверка: `SELECT uid FROM dashboard WHERE uid LIKE 'gotosocial%'` + в grafana.db) + +### Requirement: Инстанс виден без алертов + +- **MUST**: Дашборд не содержит алертинга (алерты GtS — отдельное изменение). +- **SHOULD**: Панель доступности зелёная (UP), когда `gotosocial_instance_total_users` + возвращает значение; красная — когда нет данных. + +#### Scenario: Инстанс жив + +- **GIVEN** GtS отвечает на 9464 +- **WHEN** проверить stat-панель «Инстанс жив» +- **THEN** значение `gotosocial_instance_total_users` > 0 и панель зелёная + +#### Scenario: Инстанс недоступен + +- **GIVEN** GtS не отвечает на 9464 +- **WHEN** пройти интервал опроса (15с) +- **THEN** метрика пропадает и панель доступности показывает DOWN/красная \ No newline at end of file diff --git a/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/tasks.md b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/tasks.md new file mode 100644 index 0000000..5446499 --- /dev/null +++ b/openspec/changes/archive/2026-09-19-add-gotosocial-dashboard/tasks.md @@ -0,0 +1,17 @@ +## 1. Дашборд Grafana gotosocial + +- [x] 1.1 Создать `grafana/dashboards/gotosocial/gotosocial.json` + (генератор: `scripts/gen_gotosocial_dash.py`) — 20 панелей: + Доступность (stat), Инстанс (users/statuses/federating), Воркеры + (count+queue × 6 пулов), HTTP (req/s, active, p50), SQL (соединения, + p50), Процесс (RSS, CPU, FD). +- [x] 1.2 Добавить провайдер `gotosocial-dashboards` в dashboards.yml + (folder: gotosocial, path: /var/lib/grafana/dashboards/gotosocial). +- [x] 1.3 Исправить пересечение провайдеров: `garage-dashboards` смотрел на + весь `/var/lib/grafana/dashboards` (дублировал nodes/vinogorod/vesti/ + gotosocial → блокировал запись) → сужен до + `/var/lib/grafana/dashboards/garage-cluster.json`. +- [x] 1.4 Рестарт grafana (перечитывает provisioning). +- [x] 1.5 Проверка импорта: `gotosocial-main` в grafana.db, папка + `gotosocial` (id 23), включён в dashboard_provisioning. +- [x] 1.6 Обновить STATUS.md (задача закрыта). \ No newline at end of file diff --git a/openspec/specs/gotosocial-monitoring/spec.md b/openspec/specs/gotosocial-monitoring/spec.md new file mode 100644 index 0000000..db4e72d --- /dev/null +++ b/openspec/specs/gotosocial-monitoring/spec.md @@ -0,0 +1,63 @@ +# gotosocial-monitoring Specification + +## Purpose +Дашборд Grafana для метрик GoToSocial (bigbox): наблюдение за инстансом +(пользователи/статусы/федерирующиеся инстансы), воркерами (очереди), +HTTP-активностью, SQL-соединениями и ресурсами процесса. + +## Requirements + +### Requirement: Job gotosocial в prometheus.yml активен + +- **MUST**: job `gotosocial` опрашивает `127.0.0.1:9464/metrics` и + релейб`instance=bigbox:9464`. +- **MUST**: метрики доступны в VictoriaMetrics с метками + `service="gotosocial"`, `host="bigbox"`, `instance="bigbox:9464"`. + +#### Scenario: Метрики отвечают + +- **GIVEN** job gotosocial настроен в prometheus.yml +- **WHEN** запросить + `/api/v1/series?match[]=gotosocial_instance_total_users` +- **THEN** ответ содержит метрику с `instance: "bigbox:9464"` и данные + +### Requirement: Дашборд gotosocial в Grafana + +- **MUST**: Провайдер `gotosocial-dashboards` в + `grafana/provisioning/dashboards/dashboards.yml` импортирует + `/var/lib/grafana/dashboards/gotosocial` (updateIntervalSeconds: 30). +- **MUST**: Дашборд `grafana/dashboards/gotosocial/gotosocial.json` содержит: + - stat-панель доступности (запрос `gotosocial_instance_total_users` — если + данные есть, служба жива) + - instance-панели: users, statuses, federating_instances + - воркеры: по каждому пулу `gotosocial_workers_*` count+queue + - HTTP: `http_server_requests_total`, `http_server_requests_active` + - SQL: `go_sql_connections_in_use` + - процесс: RSS, CPU секунды, open_fds +- **SHOULD**: панели названы по-русски, структура соответствует стилю vesti.json. + +#### Scenario: Дашборд импортирован + +- **GIVEN** файл дашборда и провайдер добавлены +- **WHEN** пройти 30-60с после изменения provisioning +- **THEN** дашборд `GoToSocial` виден в папке + `gotosocial` (проверка: `SELECT uid FROM dashboard WHERE uid LIKE 'gotosocial%'` + в grafana.db) + +### Requirement: Инстанс виден без алертов + +- **MUST**: Дашборд не содержит алертинга (алерты GtS — отдельное изменение). +- **SHOULD**: Панель доступности зелёная (UP), когда `gotosocial_instance_total_users` + возвращает значение; красная — когда нет данных. + +#### Scenario: Инстанс жив + +- **GIVEN** GtS отвечает на 9464 +- **WHEN** проверить stat-панель «Инстанс жив» +- **THEN** значение `gotosocial_instance_total_users` > 0 и панель зелёная + +#### Scenario: Инстанс недоступен + +- **GIVEN** GtS не отвечает на 9464 +- **WHEN** пройти интервал опроса (15с) +- **THEN** метрика пропадает и панель доступности показывает DOWN/красная diff --git a/scripts/gen_gotosocial_dash.py b/scripts/gen_gotosocial_dash.py new file mode 100644 index 0000000..376e840 --- /dev/null +++ b/scripts/gen_gotosocial_dash.py @@ -0,0 +1,139 @@ +#!/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") \ No newline at end of file