Add private Prometheus API metrics and Grafana performance dashboard
Magent CI/CD / verify (push) Successful in 10m24s
Magent CI/CD / deploy-prod (push) Skipped
Magent CI/CD / deploy-beta (push) Skipped

This commit is contained in:
2026-09-07 19:23:35 +12:00
parent bd1f2cb1cb
commit 131b5fc5c7
7 changed files with 553 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# Magent monitoring
Grafana dashboard: `grafana/magent-api-performance.json` (Prometheus UID `prometheus`).
Set `MAGENT_METRICS_ENABLED=true`, `MAGENT_METRICS_BIND=0.0.0.0` and
`MAGENT_METRICS_PORT=9108` inside the container. Publish port 9108 **only on a
private interface**; do not proxy it through the public website. By default the
listener is disabled and its bind address is loopback.
Production publishes `100.114.113.88:9108:9108` on GRZ-DKR01's Tailscale interface.
Prometheus on ANA-DKR01 scrapes it every 15 seconds with job name `magent`.
Grafana's existing file provider loads the dashboard from its Magent folder.
API labels contain method, matched route template and HTTP status, never raw
paths, query values, usernames or credentials. API latency measures time to
response headers, not long-lived event-stream duration. Service metrics cover
the shared ApiClient, including background calls; custom client paths and CSRF
subrequests are not separate calls. CPU/memory refer to the Python backend only.
Metrics start at deployment, with no historical backfill. Rate/percentile panels
need multiple scrapes; unused services have no series until called. Prometheus
retains history across Magent restarts, while process counters reset normally.
@@ -0,0 +1,474 @@
{
"uid": "magent-api-performance",
"title": "Magent — API & Performance",
"tags": [
"magent",
"production"
],
"schemaVersion": 40,
"version": 1,
"refresh": "15s",
"time": {
"from": "now-1h",
"to": "now"
},
"timezone": "browser",
"editable": true,
"description": "Metrics begin when instrumentation is deployed. No historical backfill. API timings are time-to-headers. Outbound metrics cover shared ApiClient calls; CPU/memory cover the Python backend. No user IDs, usernames, tokens, search terms or raw URLs are labels.",
"panels": [
{
"id": 1,
"title": "Magent metrics reachable",
"description": "1 = scrape healthy; 0 = unavailable.",
"type": "stat",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 0,
"y": 0,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "up{job=\"magent\"}",
"legendFormat": "Magent"
}
],
"fieldConfig": {
"defaults": {
"unit": "short"
},
"overrides": []
},
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
]
},
"colorMode": "value"
}
},
{
"id": 2,
"title": "API calls / second",
"description": "",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 12,
"y": 0,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "sum(rate(magent_api_requests_total{job=\"magent\"}[$__rate_interval]))",
"legendFormat": "Calls / sec"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 3,
"title": "API response time — p95 by route",
"description": "Time to response headers; streaming session lifetime is excluded.",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 0,
"y": 8,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "histogram_quantile(0.95, sum by (le, route) (rate(magent_api_response_seconds_bucket{job=\"magent\"}[$__rate_interval])))",
"legendFormat": "{{route}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "s"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 4,
"title": "API responses by status",
"description": "",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 12,
"y": 8,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "sum by (status) (rate(magent_api_requests_total{job=\"magent\"}[$__rate_interval]))",
"legendFormat": "HTTP {{status}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 5,
"title": "API server error percentage",
"description": "",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 0,
"y": 16,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "100 * (sum(rate(magent_api_requests_total{job=\"magent\",status=~\"5..\"}[$__rate_interval])) or vector(0)) / clamp_min(sum(rate(magent_api_requests_total{job=\"magent\"}[$__rate_interval])), 0.000001)",
"legendFormat": "5xx"
}
],
"fieldConfig": {
"defaults": {
"unit": "percent"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 6,
"title": "Busiest API routes",
"description": "",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 12,
"y": 16,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "topk(10,sum by (route) (rate(magent_api_requests_total{job=\"magent\"}[$__rate_interval])))",
"legendFormat": "{{route}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 7,
"title": "Connected service calls / second",
"description": "",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 0,
"y": 24,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "sum by (service) (rate(magent_remote_requests_total{job=\"magent\"}[$__rate_interval]))",
"legendFormat": "{{service}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 8,
"title": "Connected services — p95 response time",
"description": "Instrumented shared API-client calls, including background work. Does not count every low-level HTTP exchange.",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 12,
"y": 24,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "histogram_quantile(0.95,sum by (le,service) (rate(magent_remote_response_seconds_bucket{job=\"magent\"}[$__rate_interval])))",
"legendFormat": "{{service}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "s"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 9,
"title": "Service redirects and errors",
"description": "error = connection/transport failure. Redirects are shown because they can prevent API operations.",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 0,
"y": 32,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "sum by (service,status) (rate(magent_remote_requests_total{job=\"magent\",status=~\"3..|4..|5..|error\"}[$__rate_interval]))",
"legendFormat": "{{service}} · {{status}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 10,
"title": "Backend memory",
"description": "",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 12,
"y": 32,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "process_resident_memory_bytes{job=\"magent\"}",
"legendFormat": "Python backend"
}
],
"fieldConfig": {
"defaults": {
"unit": "bytes"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 11,
"title": "Backend CPU — cores used",
"description": "Backend process only, not the frontend or whole host.",
"type": "timeseries",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 0,
"y": 40,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "rate(process_cpu_seconds_total{job=\"magent\"}[$__rate_interval])",
"legendFormat": "CPU cores"
}
],
"fieldConfig": {
"defaults": {
"unit": "short"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
}
},
{
"id": 12,
"title": "Backend uptime",
"description": "",
"type": "stat",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"x": 12,
"y": 40,
"w": 12,
"h": 8
},
"targets": [
{
"refId": "A",
"expr": "time() - process_start_time_seconds{job=\"magent\"}",
"legendFormat": "Uptime"
}
],
"fieldConfig": {
"defaults": {
"unit": "s"
},
"overrides": []
},
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
]
},
"colorMode": "value"
}
}
]
}