- Add Grafana dashboard for web vitals metrics visualization - Add Prisma migration for admin audit log table Co-Authored-By: Paperclip <noreply@paperclip.ing>
398 lines
12 KiB
JSON
398 lines
12 KiB
JSON
{
|
|
"annotations": { "list": [] },
|
|
"editable": true,
|
|
"fiscalYearStartMonth": 0,
|
|
"graphTooltip": 1,
|
|
"links": [],
|
|
"panels": [
|
|
{
|
|
"title": "Core Web Vitals — Overview",
|
|
"type": "row",
|
|
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
|
"collapsed": false
|
|
},
|
|
{
|
|
"title": "LCP (Largest Contentful Paint)",
|
|
"description": "Target: < 2.5s (good), < 4.0s (needs improvement)",
|
|
"type": "gauge",
|
|
"gridPos": { "h": 6, "w": 6, "x": 0, "y": 1 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_lcp_seconds_bucket[5m])) by (le))",
|
|
"legendFormat": "p75 LCP",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"min": 0,
|
|
"max": 10,
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 2.5 },
|
|
{ "color": "red", "value": 4.0 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "FCP (First Contentful Paint)",
|
|
"description": "Target: < 1.8s (good), < 3.0s (needs improvement)",
|
|
"type": "gauge",
|
|
"gridPos": { "h": 6, "w": 6, "x": 6, "y": 1 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_fcp_seconds_bucket[5m])) by (le))",
|
|
"legendFormat": "p75 FCP",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"min": 0,
|
|
"max": 5,
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 1.8 },
|
|
{ "color": "red", "value": 3.0 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "CLS (Cumulative Layout Shift)",
|
|
"description": "Target: < 0.1 (good), < 0.25 (needs improvement)",
|
|
"type": "gauge",
|
|
"gridPos": { "h": 6, "w": 6, "x": 12, "y": 1 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_cls_bucket[5m])) by (le))",
|
|
"legendFormat": "p75 CLS",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "none",
|
|
"min": 0,
|
|
"max": 1,
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 0.1 },
|
|
{ "color": "red", "value": 0.25 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "TTFB (Time to First Byte)",
|
|
"description": "Target: < 800ms (good)",
|
|
"type": "gauge",
|
|
"gridPos": { "h": 6, "w": 6, "x": 18, "y": 1 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_ttfb_seconds_bucket[5m])) by (le))",
|
|
"legendFormat": "p75 TTFB",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"min": 0,
|
|
"max": 5,
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 0.8 },
|
|
{ "color": "red", "value": 1.8 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "Rating Distribution",
|
|
"type": "row",
|
|
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 7 },
|
|
"collapsed": false
|
|
},
|
|
{
|
|
"title": "Web Vital Ratings (Good / Needs Improvement / Poor)",
|
|
"type": "piechart",
|
|
"gridPos": { "h": 8, "w": 8, "x": 0, "y": 8 },
|
|
"targets": [
|
|
{
|
|
"expr": "sum(goodgo_web_vitals_total) by (rating)",
|
|
"legendFormat": "{{rating}}",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {},
|
|
"overrides": [
|
|
{ "matcher": { "id": "byName", "options": "good" }, "properties": [{ "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } }] },
|
|
{ "matcher": { "id": "byName", "options": "needs-improvement" }, "properties": [{ "id": "color", "value": { "fixedColor": "yellow", "mode": "fixed" } }] },
|
|
{ "matcher": { "id": "byName", "options": "poor" }, "properties": [{ "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } }] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"title": "Events by Vital Type",
|
|
"type": "barchart",
|
|
"gridPos": { "h": 8, "w": 8, "x": 8, "y": 8 },
|
|
"targets": [
|
|
{
|
|
"expr": "sum(goodgo_web_vitals_total) by (name)",
|
|
"legendFormat": "{{name}}",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": { "unit": "short" }
|
|
}
|
|
},
|
|
{
|
|
"title": "INP (Interaction to Next Paint)",
|
|
"description": "Target: < 200ms (good), < 500ms (needs improvement)",
|
|
"type": "gauge",
|
|
"gridPos": { "h": 8, "w": 8, "x": 16, "y": 8 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_inp_seconds_bucket[5m])) by (le))",
|
|
"legendFormat": "p75 INP",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"min": 0,
|
|
"max": 1,
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 0.2 },
|
|
{ "color": "red", "value": 0.5 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "Trends Over Time",
|
|
"type": "row",
|
|
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 },
|
|
"collapsed": false
|
|
},
|
|
{
|
|
"title": "LCP Trend (p50 / p75 / p95)",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 17 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.50, sum(rate(goodgo_web_vitals_lcp_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p50",
|
|
"refId": "A"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_lcp_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p75",
|
|
"refId": "B"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.95, sum(rate(goodgo_web_vitals_lcp_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p95",
|
|
"refId": "C"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"custom": { "drawStyle": "line", "fillOpacity": 10, "pointSize": 5 },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 2.5 },
|
|
{ "color": "red", "value": 4.0 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "CLS Trend (p50 / p75 / p95)",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 17 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.50, sum(rate(goodgo_web_vitals_cls_bucket[15m])) by (le))",
|
|
"legendFormat": "p50",
|
|
"refId": "A"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_cls_bucket[15m])) by (le))",
|
|
"legendFormat": "p75",
|
|
"refId": "B"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.95, sum(rate(goodgo_web_vitals_cls_bucket[15m])) by (le))",
|
|
"legendFormat": "p95",
|
|
"refId": "C"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "none",
|
|
"custom": { "drawStyle": "line", "fillOpacity": 10, "pointSize": 5 },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 0.1 },
|
|
{ "color": "red", "value": 0.25 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "TTFB Trend (p50 / p75 / p95)",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 25 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.50, sum(rate(goodgo_web_vitals_ttfb_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p50",
|
|
"refId": "A"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_ttfb_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p75",
|
|
"refId": "B"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.95, sum(rate(goodgo_web_vitals_ttfb_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p95",
|
|
"refId": "C"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"custom": { "drawStyle": "line", "fillOpacity": 10, "pointSize": 5 },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 0.8 },
|
|
{ "color": "red", "value": 1.8 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "INP Trend (p50 / p75 / p95)",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 25 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.50, sum(rate(goodgo_web_vitals_inp_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p50",
|
|
"refId": "A"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_inp_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p75",
|
|
"refId": "B"
|
|
},
|
|
{
|
|
"expr": "histogram_quantile(0.95, sum(rate(goodgo_web_vitals_inp_seconds_bucket[15m])) by (le))",
|
|
"legendFormat": "p95",
|
|
"refId": "C"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "s",
|
|
"custom": { "drawStyle": "line", "fillOpacity": 10, "pointSize": 5 },
|
|
"thresholds": {
|
|
"mode": "absolute",
|
|
"steps": [
|
|
{ "color": "green", "value": null },
|
|
{ "color": "yellow", "value": 0.2 },
|
|
{ "color": "red", "value": 0.5 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"title": "Page Breakdown",
|
|
"type": "row",
|
|
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 33 },
|
|
"collapsed": false
|
|
},
|
|
{
|
|
"title": "LCP by Page (p75)",
|
|
"type": "table",
|
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 34 },
|
|
"targets": [
|
|
{
|
|
"expr": "histogram_quantile(0.75, sum(rate(goodgo_web_vitals_lcp_seconds_bucket[1h])) by (le, page)) > 0",
|
|
"legendFormat": "{{page}}",
|
|
"refId": "A",
|
|
"format": "table",
|
|
"instant": true
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": { "unit": "s" }
|
|
},
|
|
"transformations": [
|
|
{ "id": "organize", "options": { "excludeByName": { "Time": true, "le": true } } }
|
|
]
|
|
},
|
|
{
|
|
"title": "Vitals Event Rate",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 34 },
|
|
"targets": [
|
|
{
|
|
"expr": "sum(rate(goodgo_web_vitals_total[5m])) by (name)",
|
|
"legendFormat": "{{name}}",
|
|
"refId": "A"
|
|
}
|
|
],
|
|
"fieldConfig": {
|
|
"defaults": {
|
|
"unit": "ops",
|
|
"custom": { "drawStyle": "line", "fillOpacity": 10 }
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"schemaVersion": 39,
|
|
"tags": ["web-vitals", "rum", "frontend"],
|
|
"templating": { "list": [] },
|
|
"time": { "from": "now-6h", "to": "now" },
|
|
"title": "Frontend Performance — Core Web Vitals",
|
|
"uid": "goodgo-web-vitals",
|
|
"version": 1
|
|
}
|