f3566a3c1a
Co-Authored-By: Mira Rehfeld <noreply@anthropic.com>
604 lines
20 KiB
JSON
604 lines
20 KiB
JSON
{
|
|
"__inputs": [
|
|
{
|
|
"name": "DS_LOKI",
|
|
"label": "Loki",
|
|
"description": "Loki receiving Bunny.net CDN access logs via Promtail (promtail-cdn-logs.yaml). Shows ALL requests including CDN cache hits.",
|
|
"type": "datasource",
|
|
"pluginId": "loki",
|
|
"pluginName": "Loki"
|
|
},
|
|
{
|
|
"name": "DS_PROMETHEUS",
|
|
"label": "Prometheus",
|
|
"description": "Prometheus scraping the APIX registry /q/metrics. Shows only cache misses that reached the origin.",
|
|
"type": "datasource",
|
|
"pluginId": "prometheus",
|
|
"pluginName": "Prometheus"
|
|
}
|
|
],
|
|
"__requires": [
|
|
{ "type": "grafana", "id": "grafana", "name": "Grafana", "version": "10.0.0" },
|
|
{ "type": "panel", "id": "timeseries", "name": "Time series", "version": "" },
|
|
{ "type": "panel", "id": "stat", "name": "Stat", "version": "" },
|
|
{ "type": "panel", "id": "gauge", "name": "Gauge", "version": "" },
|
|
{ "type": "panel", "id": "bargauge", "name": "Bar gauge", "version": "" },
|
|
{ "type": "panel", "id": "piechart", "name": "Pie chart", "version": "" },
|
|
{ "type": "panel", "id": "barchart", "name": "Bar chart", "version": "" },
|
|
{ "type": "datasource", "id": "loki", "name": "Loki", "version": "" },
|
|
{ "type": "datasource", "id": "prometheus", "name": "Prometheus", "version": "" }
|
|
],
|
|
"annotations": {
|
|
"list": [
|
|
{
|
|
"builtIn": 1,
|
|
"datasource": { "type": "grafana", "uid": "-- Grafana --" },
|
|
"enable": true,
|
|
"hide": true,
|
|
"iconColor": "rgba(0, 211, 255, 1)",
|
|
"name": "Annotations & Alerts",
|
|
"type": "dashboard"
|
|
}
|
|
]
|
|
},
|
|
"description": "Live APIX Registry traffic — OpenClaw community demo. Loki panels cover ALL requests (CDN cache hits + misses) via Bunny.net syslog forwarding. Prometheus panels cover origin cache misses only. Refresh every 5s.",
|
|
"editable": true,
|
|
"fiscalYearStartMonth": 0,
|
|
"graphTooltip": 1,
|
|
"id": null,
|
|
"links": [],
|
|
"refresh": "5s",
|
|
"schemaVersion": 38,
|
|
"tags": ["apix", "demo", "openclaw"],
|
|
"time": { "from": "now-15m", "to": "now" },
|
|
"timepicker": {},
|
|
"timezone": "browser",
|
|
"title": "APIX Registry — OpenClaw Demo",
|
|
"uid": "apix-demo-v1",
|
|
"version": 1,
|
|
|
|
"templating": {
|
|
"list": [
|
|
{
|
|
"current": {},
|
|
"hide": 0,
|
|
"includeAll": false,
|
|
"label": "Loki datasource",
|
|
"multi": false,
|
|
"name": "DS_LOKI",
|
|
"options": [],
|
|
"query": "loki",
|
|
"refresh": 1,
|
|
"type": "datasource"
|
|
},
|
|
{
|
|
"current": {},
|
|
"hide": 0,
|
|
"includeAll": false,
|
|
"label": "Prometheus datasource",
|
|
"multi": false,
|
|
"name": "DS_PROMETHEUS",
|
|
"options": [],
|
|
"query": "prometheus",
|
|
"refresh": 1,
|
|
"type": "datasource"
|
|
}
|
|
]
|
|
},
|
|
|
|
"panels": [
|
|
|
|
{
|
|
"id": 1,
|
|
"type": "stat",
|
|
"title": "CDN Searches",
|
|
"description": "Total /services + /devices requests in the selected time range, including CDN cache hits.",
|
|
"gridPos": { "x": 0, "y": 0, "w": 6, "h": 3 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
|
"orientation": "auto",
|
|
"textMode": "auto",
|
|
"colorMode": "background",
|
|
"graphMode": "none",
|
|
"justifyMode": "auto"
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "thresholds" },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "#1f60c4", "value": null },
|
|
{ "color": "#37872d", "value": 500 },
|
|
{ "color": "#8f3bb8", "value": 10000 }
|
|
]
|
|
},
|
|
"unit": "short",
|
|
"noValue": "0"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "sum(count_over_time({job=\"apix-cdn\", req_path=~\"/services.*|/devices.*\"}[$__range]))",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": ""
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 2,
|
|
"type": "gauge",
|
|
"title": "Cache Hit Ratio",
|
|
"description": "Percentage of CDN requests served from edge cache without hitting the origin VPS.",
|
|
"gridPos": { "x": 6, "y": 0, "w": 6, "h": 3 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
|
"orientation": "auto",
|
|
"showThresholdLabels": false,
|
|
"showThresholdMarkers": true,
|
|
"minVizWidth": 75,
|
|
"minVizHeight": 75
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "thresholds" },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "#c4162a", "value": null },
|
|
{ "color": "#ff9830", "value": 50 },
|
|
{ "color": "#37872d", "value": 80 }
|
|
]
|
|
},
|
|
"unit": "percent",
|
|
"min": 0,
|
|
"max": 100,
|
|
"noValue": "—"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "sum(count_over_time({job=\"apix-cdn\", cache_status=\"HIT\"}[$__range])) / sum(count_over_time({job=\"apix-cdn\"}[$__range])) * 100",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": ""
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 3,
|
|
"type": "stat",
|
|
"title": "Active PoPs",
|
|
"description": "Number of distinct Bunny.net edge PoPs that served traffic in the selected time range.",
|
|
"gridPos": { "x": 12, "y": 0, "w": 6, "h": 3 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
|
"orientation": "auto",
|
|
"textMode": "auto",
|
|
"colorMode": "background",
|
|
"graphMode": "none",
|
|
"justifyMode": "auto"
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "thresholds" },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "#1f60c4", "value": null },
|
|
{ "color": "#37872d", "value": 3 },
|
|
{ "color": "#8f3bb8", "value": 8 }
|
|
]
|
|
},
|
|
"unit": "short",
|
|
"noValue": "0"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "count(sum by (cdn_pop) (count_over_time({job=\"apix-cdn\"}[$__range])))",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": ""
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 4,
|
|
"type": "stat",
|
|
"title": "Searches / sec",
|
|
"description": "Current CDN search request rate across all edge PoPs.",
|
|
"gridPos": { "x": 18, "y": 0, "w": 6, "h": 3 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
|
"orientation": "auto",
|
|
"textMode": "auto",
|
|
"colorMode": "background",
|
|
"graphMode": "area"
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "thresholds" },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "#1f60c4", "value": null },
|
|
{ "color": "#37872d", "value": 1 },
|
|
{ "color": "#f2cc0c", "value": 10 },
|
|
{ "color": "#8f3bb8", "value": 100 }
|
|
]
|
|
},
|
|
"unit": "reqps",
|
|
"decimals": 2,
|
|
"noValue": "0"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "sum(rate({job=\"apix-cdn\", req_path=~\"/services.*|/devices.*\"}[$__rate_interval]))",
|
|
"instant": false,
|
|
"queryType": "range",
|
|
"legendFormat": ""
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 10,
|
|
"type": "row",
|
|
"title": "Capability Traffic — Real-Time",
|
|
"collapsed": false,
|
|
"gridPos": { "x": 0, "y": 3, "w": 24, "h": 1 },
|
|
"panels": []
|
|
},
|
|
|
|
{
|
|
"id": 5,
|
|
"type": "timeseries",
|
|
"title": "Requests per Second by Capability",
|
|
"description": "Live stream of capability search rates across all CDN PoPs. Each line = one capability being queried. This includes CDN cache hits — the spike you see is the real community traffic.",
|
|
"gridPos": { "x": 0, "y": 4, "w": 24, "h": 8 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"tooltip": { "mode": "multi", "sort": "desc" },
|
|
"legend": {
|
|
"displayMode": "table",
|
|
"placement": "right",
|
|
"calcs": ["lastNotNull", "max", "sum"]
|
|
}
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "palette-classic" },
|
|
"custom": {
|
|
"lineWidth": 2,
|
|
"fillOpacity": 8,
|
|
"gradientMode": "opacity",
|
|
"showPoints": "never",
|
|
"spanNulls": false
|
|
},
|
|
"unit": "reqps"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "sum by (capability) (rate({job=\"apix-cdn\", capability!=\"\"}[$__rate_interval]))",
|
|
"instant": false,
|
|
"queryType": "range",
|
|
"legendFormat": "{{capability}}"
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 20,
|
|
"type": "row",
|
|
"title": "Distribution",
|
|
"collapsed": false,
|
|
"gridPos": { "x": 0, "y": 12, "w": 24, "h": 1 },
|
|
"panels": []
|
|
},
|
|
|
|
{
|
|
"id": 6,
|
|
"type": "bargauge",
|
|
"title": "Top 10 Capabilities",
|
|
"description": "Most queried capabilities in the time range (all CDN traffic). These are the API categories the OpenClaw community is actively using.",
|
|
"gridPos": { "x": 0, "y": 13, "w": 15, "h": 8 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
|
"orientation": "horizontal",
|
|
"displayMode": "gradient",
|
|
"valueMode": "color",
|
|
"showUnfilled": true,
|
|
"minVizWidth": 8,
|
|
"minVizHeight": 16,
|
|
"namePlacement": "left",
|
|
"legendDisplayMode": "hidden"
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "continuous-BlPu" },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [{ "color": "blue", "value": null }]
|
|
},
|
|
"unit": "short"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "topk(10, sum by (capability) (count_over_time({job=\"apix-cdn\", capability!=\"\"}[$__range])))",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": "{{capability}}"
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 7,
|
|
"type": "piechart",
|
|
"title": "Cache Status",
|
|
"description": "HIT = served from CDN edge, no origin load. MISS = edge cache cold, forwarded to origin. BYPASS = edge rule prevented caching (/q/* health paths).",
|
|
"gridPos": { "x": 15, "y": 13, "w": 9, "h": 8 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"pieType": "donut",
|
|
"displayLabels": ["name", "percent"],
|
|
"legend": {
|
|
"displayMode": "table",
|
|
"placement": "right",
|
|
"calcs": ["sum"]
|
|
}
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "fixed" },
|
|
"unit": "short"
|
|
},
|
|
"overrides": [
|
|
{
|
|
"matcher": { "id": "byName", "options": "HIT" },
|
|
"properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#37872d" } }]
|
|
},
|
|
{
|
|
"matcher": { "id": "byName", "options": "MISS" },
|
|
"properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#ff9830" } }]
|
|
},
|
|
{
|
|
"matcher": { "id": "byName", "options": "BYPASS" },
|
|
"properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#6e7279" } }]
|
|
}
|
|
]
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "sum by (cache_status) (count_over_time({job=\"apix-cdn\"}[$__range]))",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": "{{cache_status}}"
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 30,
|
|
"type": "row",
|
|
"title": "Geographic Distribution",
|
|
"collapsed": false,
|
|
"gridPos": { "x": 0, "y": 21, "w": 24, "h": 1 },
|
|
"panels": []
|
|
},
|
|
|
|
{
|
|
"id": 8,
|
|
"type": "barchart",
|
|
"title": "Requests by CDN PoP",
|
|
"description": "Which Bunny.net edge PoPs served traffic. PoP names come from the syslog HOSTNAME field (e.g. sg.b-cdn.net = Singapore, hk.b-cdn.net = Hong Kong). Asia traffic is visible here even though the origin VPS is in Europe.",
|
|
"gridPos": { "x": 0, "y": 22, "w": 16, "h": 7 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"orientation": "horizontal",
|
|
"xTickLabelRotation": 0,
|
|
"xTickLabelMaxLength": 30,
|
|
"groupWidth": 0.7,
|
|
"barWidth": 0.97,
|
|
"fillOpacity": 80,
|
|
"gradientMode": "none",
|
|
"tooltip": { "mode": "single", "sort": "none" },
|
|
"legend": { "displayMode": "hidden", "placement": "bottom" }
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "continuous-BlYlRd" },
|
|
"custom": { "fillOpacity": 80 },
|
|
"unit": "short"
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "topk(15, sum by (cdn_pop) (count_over_time({job=\"apix-cdn\"}[$__range])))",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": "{{cdn_pop}}"
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 9,
|
|
"type": "piechart",
|
|
"title": "/services vs /devices",
|
|
"description": "Split of AI agent API searches (/services) vs IoT device discovery (/devices). As the OpenClaw community grows, /services should dominate initially, with /devices rising as embedded systems adopt APIX.",
|
|
"gridPos": { "x": 16, "y": 22, "w": 8, "h": 7 },
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"options": {
|
|
"pieType": "pie",
|
|
"displayLabels": ["name", "percent"],
|
|
"legend": {
|
|
"displayMode": "list",
|
|
"placement": "bottom",
|
|
"calcs": []
|
|
}
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": { "unit": "short" },
|
|
"overrides": [
|
|
{
|
|
"matcher": { "id": "byName", "options": "/services" },
|
|
"properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#1f60c4" } }]
|
|
},
|
|
{
|
|
"matcher": { "id": "byName", "options": "/devices" },
|
|
"properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#37872d" } }]
|
|
}
|
|
]
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "loki", "uid": "${DS_LOKI}" },
|
|
"editorMode": "code",
|
|
"expr": "sum by (req_path) (count_over_time({job=\"apix-cdn\", req_path=~\"/services|/devices\"}[$__range]))",
|
|
"instant": true,
|
|
"queryType": "instant",
|
|
"legendFormat": "{{req_path}}"
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 40,
|
|
"type": "row",
|
|
"title": "Origin Metrics (cache misses only — Prometheus)",
|
|
"collapsed": false,
|
|
"gridPos": { "x": 0, "y": 29, "w": 24, "h": 1 },
|
|
"panels": []
|
|
},
|
|
|
|
{
|
|
"id": 11,
|
|
"type": "timeseries",
|
|
"title": "Avg Results per Search (origin)",
|
|
"description": "Average result set size per capability search, measured at origin. Low values mean a capability is registered but has few services. Zero means no services are registered for that capability yet — demand without supply.",
|
|
"gridPos": { "x": 0, "y": 30, "w": 12, "h": 7 },
|
|
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
|
"options": {
|
|
"tooltip": { "mode": "multi", "sort": "desc" },
|
|
"legend": {
|
|
"displayMode": "table",
|
|
"placement": "right",
|
|
"calcs": ["lastNotNull", "mean"]
|
|
}
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "palette-classic" },
|
|
"custom": {
|
|
"lineWidth": 2,
|
|
"fillOpacity": 5,
|
|
"showPoints": "never",
|
|
"spanNulls": true
|
|
},
|
|
"unit": "short",
|
|
"decimals": 1
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
|
"expr": "rate(apix_search_result_count_sum{resource=\"services\"}[$__rate_interval]) / rate(apix_search_result_count_count{resource=\"services\"}[$__rate_interval])",
|
|
"legendFormat": "services",
|
|
"instant": false,
|
|
"range": true
|
|
},
|
|
{
|
|
"refId": "B",
|
|
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
|
"expr": "rate(apix_search_result_count_sum{resource=\"devices\"}[$__rate_interval]) / rate(apix_search_result_count_count{resource=\"devices\"}[$__rate_interval])",
|
|
"legendFormat": "devices",
|
|
"instant": false,
|
|
"range": true
|
|
}
|
|
]
|
|
},
|
|
|
|
{
|
|
"id": 12,
|
|
"type": "timeseries",
|
|
"title": "Origin Search Rate by Capability (cache misses)",
|
|
"description": "Prometheus counters at origin — only incremented on CDN cache misses. The ratio between this panel and the Loki 'Requests/sec' panel above shows the CDN offload factor: if origin sees 1 req/s and Loki shows 50 req/s, the CDN is absorbing 98% of traffic.",
|
|
"gridPos": { "x": 12, "y": 30, "w": 12, "h": 7 },
|
|
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
|
"options": {
|
|
"tooltip": { "mode": "multi", "sort": "desc" },
|
|
"legend": {
|
|
"displayMode": "table",
|
|
"placement": "right",
|
|
"calcs": ["lastNotNull", "max"]
|
|
}
|
|
},
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"color": { "mode": "palette-classic" },
|
|
"custom": {
|
|
"lineWidth": 1,
|
|
"fillOpacity": 4,
|
|
"showPoints": "never",
|
|
"spanNulls": true,
|
|
"lineStyle": { "fill": "dash", "dash": [4, 4] }
|
|
},
|
|
"unit": "reqps",
|
|
"decimals": 3
|
|
}
|
|
},
|
|
"targets": [
|
|
{
|
|
"refId": "A",
|
|
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
|
"expr": "sum by (capability) (rate(apix_search_services_total[$__rate_interval]))",
|
|
"legendFormat": "{{capability}}",
|
|
"instant": false,
|
|
"range": true
|
|
}
|
|
]
|
|
}
|
|
|
|
]
|
|
}
|