Grafana Setup¶
Grafana turns your Prometheus metrics into visual dashboards. This guide covers importing the bundled dashboards, building custom panels, and setting up alerts.
Initial Setup¶
Access Grafana¶
After starting the monitoring stack, open http://your-server:3000.
- Default username:
admin - Default password: whatever you set in
GRAFANA_PASSWORD(default:admin)
Change the default password
Grafana will prompt you to change the password on first login. Do it.
Add Prometheus Data Source¶
If provisioning didn't set this up automatically:
- Go to Connections > Data Sources > Add data source
- Select Prometheus
- Set the URL to
http://prometheus:9090 - Click Save & Test
The URL uses the Docker service name because Grafana and Prometheus are on the same Docker network.
Import Pre-Built Dashboards¶
Mailyte ships with dashboard JSON files in monitoring/grafana/dashboards/.
Via the UI¶
- Go to Dashboards > Import
- Click Upload JSON file
- Select a dashboard file from
monitoring/grafana/dashboards/ - Choose your Prometheus data source
- Click Import
Via Provisioning (Automatic)¶
If you mounted the provisioning directory, dashboards load automatically:
# monitoring/grafana/provisioning/dashboards/default.yml
apiVersion: 1
providers:
- name: "Mailyte Dashboards"
orgId: 1
folder: "Mailyte"
type: file
disableDeletion: false
editable: true
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
Bundled Dashboards¶
1. Overview Dashboard¶
The big picture — everything at a glance.
Panels:
- Email throughput (sent/received per minute)
- Active mail queue depth
- Bounce rate trend
- Service health status (up/down for each container)
- Storage usage across all domains
- Top 5 sending domains
2. Mail Flow Dashboard¶
Deep dive into email processing.
Panels:
- Inbound vs outbound volume
- Delivery status breakdown (sent, bounced, deferred, rejected)
- Average delivery latency
- Queue age histogram
- Top recipients by volume
- Spam score distribution
3. Infrastructure Dashboard¶
Server resources and database health.
Panels:
- CPU usage by container
- Memory usage by container
- Disk I/O
- Network traffic
- MySQL connections and query rate
- Redis memory usage and hit rate
Creating Custom Panels¶
Email Volume Over Time¶
Panel settings:
- Visualization: Time series
- Legend:
{{ organization_id }} - Unit: emails/min
Bounce Rate Gauge¶
# PromQL query
(rate(mailyte_emails_bounced_total[1h]) / rate(mailyte_emails_sent_total[1h])) * 100
Panel settings:
- Visualization: Gauge
- Unit: percent (0-100)
- Thresholds: green < 1%, yellow < 3%, red >= 3%
Queue Depth with Trend¶
# Current depth
mailyte_mail_queue_size
# 1-hour average for comparison
avg_over_time(mailyte_mail_queue_size[1h])
Panel settings:
- Visualization: Time series
- Two queries — current (solid) and average (dashed)
Storage by Organization¶
Panel settings:
- Visualization: Bar gauge
- Unit: bytes (IEC)
- Sort: descending
API Latency Heatmap¶
Panel settings:
- Visualization: Heatmap
- Data format: Time series buckets
Service Health Table¶
Panel settings:
- Visualization: Table
- Value mappings: 1 = "UP" (green), 0 = "DOWN" (red)
Setting Up Alerts in Grafana¶
Grafana can send alerts through Slack, email, PagerDuty, and many other channels.
Step 1: Configure a Contact Point¶
- Go to Alerting > Contact points
- Click Add contact point
- Name it (e.g., "Slack Alerts")
- Choose the integration type (Slack, Email, etc.)
- Fill in the details and test it
Step 2: Create Alert Rules¶
- Go to Alerting > Alert rules
- Click New alert rule
- Add a PromQL query
- Set the threshold
- Choose the notification contact point
Example Alert Rules¶
Queue Backlog:
- Query:
mailyte_mail_queue_size - Condition: IS ABOVE 500
- Evaluate every: 1m, for: 5m
High API Error Rate:
- Query:
rate(mailyte_api_requests_total{status=~"5.."}[5m]) / rate(mailyte_api_requests_total[5m]) - Condition: IS ABOVE 0.05
- Evaluate every: 1m, for: 5m
SSL Certificate Expiring:
- Query:
mailyte_ssl_cert_expiry_days - Condition: IS BELOW 14
- Evaluate every: 1h, for: 1h
Dashboard Variables¶
Make dashboards interactive with template variables:
Organization Filter¶
- Go to Dashboard settings > Variables
- Add a variable:
- Name:
organization - Type: Query
- Query:
label_values(mailyte_emails_sent_total, organization_id)
- Name:
- Use it in panels:
mailyte_emails_sent_total{organization_id="$organization"}
Time Range Comparison¶
Add a variable for comparing to previous periods:
- Name:
comparison - Type: Custom
- Values:
1h,6h,24h,7d
Then in your panel query, add a second query with offset:
# Current
rate(mailyte_emails_sent_total{organization_id="$organization"}[5m])
# Previous period
rate(mailyte_emails_sent_total{organization_id="$organization"}[5m] offset $comparison)
Tips¶
- Use recording rules for complex queries that run on every dashboard load — they're pre-computed by Prometheus
- Set realistic thresholds — tune alerts after a week of baseline data
- Organize dashboards into folders: Overview, Mail, Infrastructure, per-Organization
- Share read-only — set up a viewer role for ops teams that shouldn't edit dashboards
- Auto-refresh — set dashboards to refresh every 30s for ops screens