Files
threadnet-operating/monitoring/grafana/dashboards/gameserver/pterodactyl-server.json
T
Thore Cimbal fa26393649 monitoring: Gameserver-Dashboard neu bauen (#0002)
Die bisherige Fassung fragte elf Metriken des loens2-Exporters ab
(pterodactyl_server_cpu_absolute, _memory_mebibyte, _uptime_milliseconds ...).
Keine davon existiert - der Exporter hat nie funktioniert, das Dashboard war
seit jeher leer, und es ist niemandem aufgefallen.

Neu auf dem, was tatsaechlich anliegt: fuenf pterodactyl_server_*-Metriken des
Exporters, der die Panel-Datenbank liest, plus die fuenf gameserver:*-Recording-
Rules fuer CPU, Speicher und Netz.

Zwei Fallen in den Daten, beide beruecksichtigt:

- status, players und max_players tragen KEIN uuid und KEIN game, nur server_id
  und server_name. Die Zusatzangaben in der Tabelle kommen deshalb ueber einen
  Join auf pterodactyl_server_info.
- players liefert NaN, wenn der Server steht. Ohne den Vergleich > -1 zoege ein
  einziger gestoppter Server die Gesamtsumme auf NaN.

Alle elf Queries vor dem Commit gegen den laufenden Prometheus geprueft, nicht
nur geschrieben - genau der Fehler, an dem die alte Fassung starb.
2026-08-20 12:00:00 +00:00

245 lines
9.8 KiB
JSON

{
"uid": "pterodactyl-server",
"title": "Gameserver",
"description": "Zustand, Spieler und Auslastung je Gameserver (management #0002). Neu gebaut am 2026-08-20: Die vorherige Fassung fragte pterodactyl_server_cpu_absolute und zehn weitere Metriken des loens2-Exporters ab - der hat nie funktioniert (Client-API mit Application-Key ueber http), das Dashboard war seit jeher leer. Jetzt auf dem Exporter, der die Panel-Datenbank liest, plus den Recording Rules gameserver:*, die den Join Container-UUID -> Klarname vorwegnehmen.",
"tags": ["gameserver", "pterodactyl"],
"timezone": "browser",
"schemaVersion": 41,
"editable": true,
"time": { "from": "now-6h", "to": "now" },
"refresh": "1m",
"panels": [
{
"type": "stat",
"title": "Server",
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 0 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"instant": true,
"expr": "count(pterodactyl_server_info)"
}
],
"options": { "reduceOptions": { "calcs": ["lastNotNull"] }, "colorMode": "none", "graphMode": "none" },
"fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }
},
{
"type": "stat",
"title": "laufend",
"gridPos": { "h": 4, "w": 6, "x": 6, "y": 0 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"instant": true,
"expr": "sum(pterodactyl_server_status)"
}
],
"options": { "reduceOptions": { "calcs": ["lastNotNull"] }, "colorMode": "value", "graphMode": "none" },
"fieldConfig": {
"defaults": {
"unit": "short",
"thresholds": { "mode": "absolute", "steps": [ { "color": "text", "value": null }, { "color": "green", "value": 1 } ] }
},
"overrides": []
}
},
{
"type": "stat",
"title": "Spieler online",
"description": "Nur Server, deren Abfrage geantwortet hat. Der Vergleich > -1 filtert NaN heraus - ein gestoppter Server liefert NaN und wuerde die Summe sonst unbrauchbar machen.",
"gridPos": { "h": 4, "w": 6, "x": 12, "y": 0 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"instant": true,
"expr": "sum(pterodactyl_server_players > -1)"
}
],
"options": { "reduceOptions": { "calcs": ["lastNotNull"] }, "colorMode": "value", "graphMode": "none" },
"fieldConfig": {
"defaults": {
"unit": "short",
"thresholds": { "mode": "absolute", "steps": [ { "color": "text", "value": null }, { "color": "blue", "value": 1 } ] }
},
"overrides": []
}
},
{
"type": "stat",
"title": "Abfrage fehlgeschlagen",
"description": "Server, deren Spielabfrage nicht antwortet. Bei gestoppten Servern normal; bei einem laufenden Server ein Hinweis auf ein Problem.",
"gridPos": { "h": 4, "w": 6, "x": 18, "y": 0 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"instant": true,
"expr": "count(pterodactyl_server_query_success == 0) or vector(0)"
}
],
"options": { "reduceOptions": { "calcs": ["lastNotNull"] }, "colorMode": "background", "graphMode": "none" },
"fieldConfig": {
"defaults": {
"unit": "short",
"thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 } ] }
},
"overrides": []
}
},
{
"type": "table",
"title": "Server im Einzelnen",
"description": "Zustand mit Spiel, Version und Port. Die Zusatzangaben kommen ueber einen Join auf pterodactyl_server_info - status allein traegt nur server_id und server_name.",
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 4 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"instant": true,
"format": "table",
"expr": "pterodactyl_server_status * on(server_id) group_left(game, version, port) pterodactyl_server_info"
}
],
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": { "Time": true, "__name__": true, "host": true, "instance": true, "job": true, "server_id": true },
"renameByName": {
"server_name": "Server",
"game": "Spiel",
"version": "Version",
"port": "Port",
"Value": "Zustand"
}
}
}
],
"fieldConfig": {
"defaults": {},
"overrides": [
{
"matcher": { "id": "byName", "options": "Zustand" },
"properties": [
{
"id": "mappings",
"value": [
{ "type": "value", "options": { "0": { "text": "gestoppt", "color": "text", "index": 0 }, "1": { "text": "läuft", "color": "green", "index": 1 } } }
]
},
{ "id": "custom.cellOptions", "value": { "type": "color-text" } }
]
}
]
}
},
{
"type": "timeseries",
"title": "Spieler",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 12 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"legendFormat": "{{server_name}}",
"expr": "pterodactyl_server_players > -1"
}
],
"fieldConfig": {
"defaults": { "unit": "short", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 2, "fillOpacity": 10, "showPoints": "never" } },
"overrides": []
},
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi" } }
},
{
"type": "timeseries",
"title": "CPU-Kerne",
"description": "Aus der Recording Rule gameserver:cpu_cores - sie nimmt den Join Container-UUID -> Klarname vorweg, weil cAdvisor die Gameserver nur unter ihrer UUID kennt.",
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 12 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"legendFormat": "{{server_name}}",
"expr": "gameserver:cpu_cores"
}
],
"fieldConfig": {
"defaults": { "unit": "short", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 2, "fillOpacity": 10, "showPoints": "never" } },
"overrides": []
},
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi" } }
},
{
"type": "timeseries",
"title": "Arbeitsspeicher",
"description": "Belegung und, wo gesetzt, das Limit. Nicht jeder Server hat eines - dann fehlt die gestrichelte Linie.",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 20 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"legendFormat": "{{server_name}}",
"expr": "gameserver:memory_working_set_bytes"
},
{
"refId": "B",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"legendFormat": "{{server_name}} — Limit",
"expr": "gameserver:memory_limit_bytes"
}
],
"fieldConfig": {
"defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 2, "fillOpacity": 10, "showPoints": "never" } },
"overrides": [
{
"matcher": { "id": "byRegexp", "options": ".*Limit" },
"properties": [
{ "id": "custom.fillOpacity", "value": 0 },
{ "id": "custom.lineStyle", "value": { "dash": [8, 6], "fill": "dash" } }
]
}
]
},
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi" } }
},
{
"type": "timeseries",
"title": "Netzwerk",
"description": "Eingehend positiv, ausgehend negativ aufgetragen.",
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 20 },
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"targets": [
{
"refId": "A",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"legendFormat": "{{server_name}} — ein",
"expr": "gameserver:network_receive_bytes_per_second"
},
{
"refId": "B",
"datasource": { "type": "prometheus", "uid": "belof8d814dtse" },
"legendFormat": "{{server_name}} — aus",
"expr": "- gameserver:network_transmit_bytes_per_second"
}
],
"fieldConfig": {
"defaults": { "unit": "Bps", "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 15, "showPoints": "never" } },
"overrides": []
},
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi" } }
}
]
}