Add monitoring stack: Prometheus, Alertmanager, Grafana
This commit is contained in:
12
monitoring/alertmanager/alertmanager.yml
Normal file
12
monitoring/alertmanager/alertmanager.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
route:
|
||||||
|
receiver: logger
|
||||||
|
group_by: ["alertname"]
|
||||||
|
group_wait: 10s
|
||||||
|
group_interval: 1m
|
||||||
|
repeat_interval: 1h
|
||||||
|
|
||||||
|
receivers:
|
||||||
|
- name: logger
|
||||||
|
webhook_configs:
|
||||||
|
- url: http://alert-logger:8080/
|
||||||
|
send_resolved: true
|
||||||
63
monitoring/compose.yml
Normal file
63
monitoring/compose.yml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
services:
|
||||||
|
prometheus:
|
||||||
|
image: prom/prometheus:v2.53.0
|
||||||
|
container_name: prometheus
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- --config.file=/etc/prometheus/prometheus.yml
|
||||||
|
- --storage.tsdb.retention.time=7d
|
||||||
|
- --web.enable-lifecycle
|
||||||
|
volumes:
|
||||||
|
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||||
|
- ./prometheus/alert_rules.yml:/etc/prometheus/alert_rules.yml:ro
|
||||||
|
- prometheus-data:/prometheus
|
||||||
|
ports:
|
||||||
|
- "9090:9090"
|
||||||
|
networks:
|
||||||
|
- monitoring-net
|
||||||
|
|
||||||
|
alertmanager:
|
||||||
|
image: prom/alertmanager:v0.27.0
|
||||||
|
container_name: alertmanager
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- --config.file=/etc/alertmanager/alertmanager.yml
|
||||||
|
volumes:
|
||||||
|
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
|
||||||
|
- alertmanager-data:/alertmanager
|
||||||
|
ports:
|
||||||
|
- "9093:9093"
|
||||||
|
networks:
|
||||||
|
- monitoring-net
|
||||||
|
|
||||||
|
alert-logger:
|
||||||
|
image: mendhak/http-https-echo:latest
|
||||||
|
container_name: alert-logger
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- monitoring-net
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:11.1.0
|
||||||
|
container_name: grafana
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- GF_SECURITY_ADMIN_USER=admin
|
||||||
|
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
|
||||||
|
volumes:
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||||
|
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||||
|
- grafana-data:/var/lib/grafana
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
networks:
|
||||||
|
- monitoring-net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
prometheus-data:
|
||||||
|
alertmanager-data:
|
||||||
|
grafana-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
monitoring-net:
|
||||||
|
external: true
|
||||||
35
monitoring/grafana/dashboards/webapp.json
Normal file
35
monitoring/grafana/dashboards/webapp.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"title": "Webapp Overview",
|
||||||
|
"uid": "webapp-overview",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"refresh": "10s",
|
||||||
|
"time": { "from": "now-15m", "to": "now" },
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"id": 1, "type": "stat", "title": "Webapp up (1 = yes)",
|
||||||
|
"gridPos": { "x": 0, "y": 0, "w": 6, "h": 6 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"targets": [ { "refId": "A", "expr": "up{job=\"webapp\"}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2, "type": "timeseries", "title": "Request rate by path (req/s)",
|
||||||
|
"gridPos": { "x": 6, "y": 0, "w": 18, "h": 6 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"targets": [ { "refId": "A", "expr": "sum by (path) (rate(http_requests_total[1m]))", "legendFormat": "{{path}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3, "type": "timeseries", "title": "5xx error ratio",
|
||||||
|
"gridPos": { "x": 0, "y": 6, "w": 12, "h": 8 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "percentunit" }, "overrides": [] },
|
||||||
|
"targets": [ { "refId": "A", "expr": "sum(rate(http_requests_total{status=~\"5..\"}[1m])) / sum(rate(http_requests_total[1m]))", "legendFormat": "5xx ratio" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4, "type": "timeseries", "title": "p95 latency (s)",
|
||||||
|
"gridPos": { "x": 12, "y": 6, "w": 12, "h": 8 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] },
|
||||||
|
"targets": [ { "refId": "A", "expr": "histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))", "legendFormat": "p95" } ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
providers:
|
||||||
|
- name: default
|
||||||
|
folder: ""
|
||||||
|
type: file
|
||||||
|
options:
|
||||||
|
path: /var/lib/grafana/dashboards
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
type: prometheus
|
||||||
|
uid: prometheus
|
||||||
|
access: proxy
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: true
|
||||||
29
monitoring/prometheus/alert_rules.yml
Normal file
29
monitoring/prometheus/alert_rules.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
groups:
|
||||||
|
- name: webapp
|
||||||
|
rules:
|
||||||
|
- alert: WebappDown
|
||||||
|
expr: up{job="webapp"} == 0
|
||||||
|
for: 30s
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "Webapp is down"
|
||||||
|
description: "Prometheus cannot scrape the webapp for more than 30 seconds."
|
||||||
|
|
||||||
|
- alert: HighErrorRate
|
||||||
|
expr: sum(rate(http_requests_total{status=~"5.."}[1m])) / sum(rate(http_requests_total[1m])) > 0.05
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
summary: "More than 5% of requests are failing"
|
||||||
|
description: "The 5xx ratio has been above 5% for 1 minute."
|
||||||
|
|
||||||
|
- alert: HighLatencyP95
|
||||||
|
expr: histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) > 0.5
|
||||||
|
for: 2m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
summary: "p95 latency above 500ms"
|
||||||
|
description: "95% of requests take longer than 0.5s."
|
||||||
21
monitoring/prometheus/prometheus.yml
Normal file
21
monitoring/prometheus/prometheus.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
evaluation_interval: 15s
|
||||||
|
|
||||||
|
alerting:
|
||||||
|
alertmanagers:
|
||||||
|
- static_configs:
|
||||||
|
- targets: ["alertmanager:9093"]
|
||||||
|
|
||||||
|
rule_files:
|
||||||
|
- /etc/prometheus/alert_rules.yml
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: prometheus
|
||||||
|
static_configs:
|
||||||
|
- targets: ["localhost:9090"]
|
||||||
|
|
||||||
|
- job_name: webapp
|
||||||
|
metrics_path: /metrics
|
||||||
|
static_configs:
|
||||||
|
- targets: ["webapp:8000"]
|
||||||
Reference in New Issue
Block a user