v05.00.01 � Grafana dashboard overhaul, library panels, monitoring fixes #6

Merged
jmiller merged 19 commits from dev into main 2026-05-12 05:20:45 +00:00
24 changed files with 1027 additions and 699 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "mokoconsulting-tech/enterprise",
"description": "MokoStandards Enterprise API \u2014 PHP implementation",
"type": "library",
"version": "05.00.00",
"version": "05.00.01",
"license": "GPL-3.0-or-later",
"authors": [
{
@@ -0,0 +1,85 @@
{
"name": "CPU Usage",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 20,
"gradientMode": "scheme",
"lineWidth": 2
},
"max": 1,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 0.7
},
{
"color": "red",
"value": 0.9
}
]
},
"unit": "percentunit"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Yesterday CPU"
},
"properties": [
{
"id": "custom.lineStyle",
"value": {
"dash": [
10,
10
],
"fill": "dash"
}
},
{
"id": "custom.fillOpacity",
"value": 0
},
{
"id": "custom.lineWidth",
"value": 1
},
{
"id": "color",
"value": {
"fixedColor": "rgba(255,255,255,0.35)",
"mode": "fixed"
}
}
]
}
]
},
"targets": [
{
"expr": "1 - avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m]))",
"legendFormat": "Total CPU",
"refId": "A"
},
{
"expr": "1 - avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m] offset 1d))",
"legendFormat": "Yesterday CPU",
"refId": "B"
}
],
"title": "CPU Usage %",
"type": "timeseries"
}
}
@@ -0,0 +1,45 @@
{
"name": "Disk Usage",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"max": 1,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 0.75
},
{
"color": "red",
"value": 0.9
}
]
},
"unit": "percentunit"
}
},
"targets": [
{
"expr": "1 - (node_filesystem_avail_bytes{mountpoint=\"/\",fstype!=\"tmpfs\"} / node_filesystem_size_bytes{mountpoint=\"/\",fstype!=\"tmpfs\"})",
"legendFormat": "/ (root)",
"refId": "A"
},
{
"expr": "1 - (node_filesystem_avail_bytes{mountpoint=\"/mnt/backup\",fstype!=\"tmpfs\"} / node_filesystem_size_bytes{mountpoint=\"/mnt/backup\",fstype!=\"tmpfs\"})",
"legendFormat": "/mnt/backup",
"refId": "B"
}
],
"title": "Filesystem Usage",
"type": "gauge"
}
}
@@ -0,0 +1,28 @@
{
"name": "Docker Container CPU",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 20,
"lineWidth": 2,
"stacking": {
"mode": "normal"
}
},
"unit": "percentunit"
}
},
"targets": [
{
"expr": "rate(container_cpu_usage_seconds_total{name!=\"\",name!~\".*POD.*\"}[5m])",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"title": "CPU Usage by Container",
"type": "timeseries"
}
}
@@ -0,0 +1,28 @@
{
"name": "Docker Container Memory",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 20,
"lineWidth": 2,
"stacking": {
"mode": "normal"
}
},
"unit": "bytes"
}
},
"targets": [
{
"expr": "container_memory_usage_bytes{name!=\"\",name!~\".*POD.*\"}",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"title": "Memory Usage by Container",
"type": "timeseries"
}
}
@@ -0,0 +1,44 @@
{
"name": "Memory Usage",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 30,
"lineWidth": 2,
"stacking": {
"group": "A",
"mode": "normal"
}
},
"unit": "bytes"
}
},
"targets": [
{
"expr": "node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes - node_memory_SReclaimable_bytes",
"legendFormat": "Used",
"refId": "A"
},
{
"expr": "node_memory_Buffers_bytes",
"legendFormat": "Buffers",
"refId": "B"
},
{
"expr": "node_memory_Cached_bytes + node_memory_SReclaimable_bytes",
"legendFormat": "Cached",
"refId": "C"
},
{
"expr": "node_memory_MemFree_bytes",
"legendFormat": "Free",
"refId": "D"
}
],
"title": "Memory Usage",
"type": "timeseries"
}
}
@@ -0,0 +1,34 @@
{
"name": "MySQL Connections",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 15,
"lineWidth": 2
}
}
},
"targets": [
{
"expr": "mysql_global_status_threads_connected",
"legendFormat": "Connected",
"refId": "A"
},
{
"expr": "mysql_global_status_threads_running",
"legendFormat": "Running",
"refId": "B"
},
{
"expr": "mysql_global_variables_max_connections",
"legendFormat": "Max",
"refId": "C"
}
],
"title": "Connections",
"type": "timeseries"
}
}
@@ -0,0 +1,65 @@
{
"name": "MySQL Queries per Second",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 20,
"lineWidth": 2
},
"unit": "ops"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Yesterday"
},
"properties": [
{
"id": "custom.lineStyle",
"value": {
"dash": [
10,
10
],
"fill": "dash"
}
},
{
"id": "custom.fillOpacity",
"value": 0
},
{
"id": "custom.lineWidth",
"value": 1
},
{
"id": "color",
"value": {
"fixedColor": "rgba(255,255,255,0.35)",
"mode": "fixed"
}
}
]
}
]
},
"targets": [
{
"expr": "rate(mysql_global_status_queries[5m])",
"legendFormat": "Queries/s",
"refId": "A"
},
{
"expr": "rate(mysql_global_status_queries[5m] offset 1d)",
"legendFormat": "Yesterday",
"refId": "B"
}
],
"title": "Queries per Second",
"type": "timeseries"
}
}
@@ -0,0 +1,75 @@
{
"name": "Network Traffic",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 20,
"lineWidth": 2
},
"unit": "bps"
},
"overrides": [
{
"matcher": {
"id": "byRegexp",
"options": "/Yesterday.*/"
},
"properties": [
{
"id": "custom.lineStyle",
"value": {
"dash": [
10,
10
],
"fill": "dash"
}
},
{
"id": "custom.fillOpacity",
"value": 0
},
{
"id": "custom.lineWidth",
"value": 1
},
{
"id": "color",
"value": {
"fixedColor": "rgba(255,255,255,0.35)",
"mode": "fixed"
}
}
]
}
]
},
"targets": [
{
"expr": "rate(node_network_receive_bytes_total{device!~\"lo|veth.*|br-.*|docker.*\"}[5m]) * 8",
"legendFormat": "RX {{device}}",
"refId": "A"
},
{
"expr": "-rate(node_network_transmit_bytes_total{device!~\"lo|veth.*|br-.*|docker.*\"}[5m]) * 8",
"legendFormat": "TX {{device}}",
"refId": "B"
},
{
"expr": "rate(node_network_receive_bytes_total{device!~\"lo|veth.*|br-.*|docker.*\"}[5m] offset 1d) * 8",
"legendFormat": "Yesterday RX {{device}}",
"refId": "C"
},
{
"expr": "-rate(node_network_transmit_bytes_total{device!~\"lo|veth.*|br-.*|docker.*\"}[5m] offset 1d) * 8",
"legendFormat": "Yesterday TX {{device}}",
"refId": "D"
}
],
"title": "Network Traffic",
"type": "timeseries"
}
}
@@ -0,0 +1,39 @@
{
"name": "Nginx Connections",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 20,
"lineWidth": 2
}
}
},
"targets": [
{
"expr": "nginx_connections_active",
"legendFormat": "Active",
"refId": "A"
},
{
"expr": "nginx_connections_reading",
"legendFormat": "Reading",
"refId": "B"
},
{
"expr": "nginx_connections_writing",
"legendFormat": "Writing",
"refId": "C"
},
{
"expr": "nginx_connections_waiting",
"legendFormat": "Waiting",
"refId": "D"
}
],
"title": "Connections Over Time",
"type": "timeseries"
}
}
@@ -0,0 +1,42 @@
{
"name": "Nginx Request Rate",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 25,
"gradientMode": "scheme",
"lineWidth": 2
},
"thresholds": {
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 50
},
{
"color": "red",
"value": 200
}
]
},
"unit": "reqps"
}
},
"targets": [
{
"expr": "rate(nginx_http_requests_total[5m])",
"legendFormat": "Requests/s",
"refId": "A"
}
],
"title": "Request Rate",
"type": "timeseries"
}
}
@@ -0,0 +1,45 @@
{
"name": "Response Time",
"kind": 1,
"model": {
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"description": "",
"fieldConfig": {
"defaults": {
"unit": "s"
}
},
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "multi"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"expr": "probe_http_duration_seconds{site_name=~\"$site\", job=\"blackbox-http\", phase=\"transfer\"}",
"legendFormat": "{{site_name}} transfer"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"expr": "probe_http_duration_seconds{site_name=~\"$site\", job=\"blackbox-http\", phase=\"processing\"}",
"legendFormat": "{{site_name}} processing"
}
],
"title": "Response Time",
"type": "timeseries"
}
}
@@ -0,0 +1,64 @@
{
"name": "Service Health",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "mappings",
"value": [
{
"options": {
"0": {
"color": "red",
"text": "DOWN"
},
"1": {
"color": "green",
"text": "UP"
}
},
"type": "value"
}
]
}
]
}
]
},
"targets": [
{
"expr": "up",
"format": "table",
"instant": true,
"refId": "A"
}
],
"title": "Scrape Target Health",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Time": true,
"__name__": true
},
"renameByName": {
"Value": "Status",
"instance": "Instance",
"job": "Service"
}
}
}
],
"type": "table"
}
}
@@ -0,0 +1,68 @@
{
"name": "SSL Certificate Expiry",
"kind": 1,
"model": {
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"drawStyle": "line",
"fillOpacity": 10,
"lineWidth": 2,
"spanNulls": false,
"thresholdsStyle": {
"mode": "area"
}
},
"decimals": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "yellow",
"value": 7
},
{
"color": "green",
"value": 30
}
]
},
"unit": "short"
},
"overrides": []
},
"options": {
"legend": {
"calcs": [
"lastNotNull",
"min"
],
"displayMode": "table",
"placement": "bottom"
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"expr": "moko_ssl_cert_expiry_seconds{domain=\"git.mokoconsulting.tech\"} / 86400",
"legendFormat": "git.mokoconsulting.tech \u2014 days",
"refId": "A"
},
{
"expr": "moko_ssl_cert_expiry_seconds{domain=\"ntfy.mokoconsulting.tech\"} / 86400",
"legendFormat": "ntfy.mokoconsulting.tech \u2014 days",
"refId": "B"
}
],
"title": "Certificate Expiry Timeline",
"type": "timeseries"
}
}
@@ -0,0 +1,59 @@
{
"name": "Uptime Availability",
"kind": 1,
"model": {
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"fillOpacity": 10,
"lineWidth": 2
},
"max": 1,
"min": 0,
"thresholds": {
"steps": [
{
"color": "red",
"value": 0
},
{
"color": "yellow",
"value": 0.95
},
{
"color": "green",
"value": 0.99
}
]
},
"unit": "percentunit"
}
},
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"expr": "avg_over_time(probe_success{site_name=~\"$site\", job=\"blackbox-http\"}[1h])",
"legendFormat": "{{site_name}}"
}
],
"title": "Availability (30d)",
"type": "timeseries"
}
}
File diff suppressed because it is too large Load Diff
@@ -109,10 +109,10 @@ All contributions must follow [MokoStandards](https://git.mokoconsulting.tech/Mo
## Custom Workflows
Place repo-specific workflows in `.github/workflows/custom/` — they are **never overwritten or deleted** by MokoStandards sync:
Place repo-specific workflows in `.mokogitea/workflows/custom/` — they are **never overwritten or deleted** by MokoStandards sync:
```
.github/workflows/
.mokogitea/workflows/
├── deploy-dev.yml ← Synced from MokoStandards
├── auto-release.yml ← Synced from MokoStandards
└── custom/ ← Your custom workflows (safe)
+9 -9
View File
@@ -53,7 +53,7 @@ Located in `ISSUE_TEMPLATE/` directory:
- **Custom Templates**: Project-specific issue types
- **Configuration** (`config.yml`): Issue template configuration
**Usage**: Copy entire `ISSUE_TEMPLATE/` directory to your repository's `.gitea/` directory.
**Usage**: Copy entire `ISSUE_TEMPLATE/` directory to your repository's `.mokogitea/` directory.
### Pull Request Template
@@ -61,7 +61,7 @@ Located in `ISSUE_TEMPLATE/` directory:
**Purpose**: Standardize pull request descriptions and ensure all necessary information is provided before review.
**Usage**: Copy to `.gitea/PULL_REQUEST_TEMPLATE.md` in your repository.
**Usage**: Copy to `.mokogitea/PULL_REQUEST_TEMPLATE.md` in your repository.
### CODEOWNERS Template
@@ -70,7 +70,7 @@ Located in `ISSUE_TEMPLATE/` directory:
**Purpose**: Define code ownership for automatic review assignment.
**Usage**:
1. Copy to `.gitea/CODEOWNERS` (remove `.template` suffix)
1. Copy to `.mokogitea/CODEOWNERS` (remove `.template` suffix)
2. Customize with your team and file patterns
3. Commit to repository
@@ -79,7 +79,7 @@ Located in `ISSUE_TEMPLATE/` directory:
### Setup Process
1. **Choose Templates**: Identify which templates your repository needs
2. **Copy to Repository**: Copy templates to your repository's `.gitea/` directory
2. **Copy to Repository**: Copy templates to your repository's `.mokogitea/` directory
3. **Customize**: Adapt templates to your project's needs
4. **Test**: Create test issues/PRs to validate templates
5. **Document**: Update README with any project-specific requirements
@@ -88,7 +88,7 @@ Located in `ISSUE_TEMPLATE/` directory:
```
your-repository/
└── .gitea/
└── .mokogitea/
├── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ ├── feature_request.md
@@ -205,7 +205,7 @@ The CODEOWNERS file:
* @org/default-team
/docs/ @org/docs-team
/src/ @org/dev-team
/.gitea/workflows/ @org/devops-team
/.mokogitea/workflows/ @org/devops-team
/scripts/ @org/automation-team
/docs/policy/security-*.md @org/security-team
```
@@ -274,7 +274,7 @@ Before publishing templates:
For small projects:
```
.gitea/
.mokogitea/
├── ISSUE_TEMPLATE/
│ └── bug_report.md
└── PULL_REQUEST_TEMPLATE.md
@@ -284,7 +284,7 @@ For small projects:
For large projects:
```
.gitea/
.mokogitea/
├── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ ├── feature_request.md
@@ -299,7 +299,7 @@ For large projects:
For repositories with multiple components:
```
.gitea/
.mokogitea/
├── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ ├── feature_request.md