Complete guide for monitoring the Analytics Server using Prometheus, Grafana, and Alertmanager.
Version: 1.0 Last Updated: 2025-01-13
- Overview
- Monitoring Stack Components
- Accessing Monitoring Tools
- Grafana Dashboards
- Prometheus Metrics
- Alert Configuration
- Common Monitoring Tasks
- Troubleshooting
The Analytics Server includes a comprehensive monitoring stack for tracking system health, performance, and operational metrics. This is internal monitoring for infrastructure and application health, not the public analytics dashboard.
- Monitoring (this guide): Internal operational metrics (API health, queue depth, database performance)
- Public Analytics: Product usage statistics displayed on website (tool usage, geographic distribution)
┌─────────────┐ ┌──────────────┐ ┌───────────────┐
│ Analytics │────▶│ Prometheus │────▶│ Grafana │
│ Server │ │ (metrics) │ │ (dashboards) │
│ (API/Worker)│ └──────────────┘ └───────────────┘
└─────────────┘ │
│
▼
┌──────────────┐
│ Alertmanager │
│(notifications)│
└──────────────┘
- Purpose: Metrics collection and storage
- Port: 9090
- Data Retention: 30 days
- Scrape Interval: 15 seconds (API: 10 seconds)
- Purpose: Visualization and dashboards
- Port: 3001
- Default Credentials: admin/admin (change on first login)
- Dashboards: 3 pre-configured dashboards
- Purpose: Alert routing and notifications
- Port: 9093
- Notification Methods: Email, Slack (configurable)
# Start all services including monitoring
docker compose up -d
# Access URLs
Prometheus: http://localhost:9090
Grafana: http://localhost:3001
Alertmanager: http://localhost:9093Monitoring tools are only exposed to localhost in production. Access via SSH tunnel:
# SSH tunnel to access Grafana
ssh -L 3001:localhost:3001 user@your-server.com
# Then access in browser
http://localhost:3001Security Note: Never expose Prometheus, Grafana, or Alertmanager directly to the internet.
Purpose: Monitor API server health and performance
Key Metrics:
- Request Rate: HTTP requests per second by endpoint
- Error Rate: 4xx and 5xx error percentages
- Response Time: p50, p95, p99 latency percentiles
- Events Received: Analytics events ingested per second
- API Uptime: Current service status
When to Check:
- Daily health checks
- After deployments
- When users report issues
- During traffic spikes
Alert Thresholds:
- Error rate >5%: Warning
- Error rate >10%: Critical
- Response time p95 >1s: Warning
- API down: Critical
Purpose: Monitor event processing pipeline
Key Metrics:
- Queue Depth: Number of events waiting to be processed
- Events Processed: Successful and failed event processing rate
- Batch Size: Distribution of worker batch sizes
- Processing Time: Time to process event batches
- Worker Errors: Errors by type (database_insert, aggregation_update, batch_processing)
When to Check:
- When queue depth is growing
- After schema changes
- During database maintenance
- When processing seems slow
Alert Thresholds:
- Queue depth >1000: Warning
- Queue depth >5000: Critical
- Queue near capacity (>9000): Critical
- Processing stalled: Critical
Purpose: Monitor database and system resources
Key Metrics:
- Query Duration: Database query performance (p50, p95, p99)
- Query Rate: Database queries per second
- Connection Pool: Active, idle, and waiting connections
- Cache Hit Rate: Percentage of cache hits
- Memory Usage: Process memory consumption
- CPU Usage: Process CPU utilization
When to Check:
- When database seems slow
- When memory is high
- During performance tuning
- Before/after index changes
Alert Thresholds:
- Connection pool >80: Warning
- Slow queries >1s: Warning
- Memory >400MB: Warning
- Memory >450MB: Critical
Prometheus UI: http://localhost:9090
Raw Metrics: http://localhost:3000/metrics (API endpoint)
# Total HTTP requests
http_requests_total
# Request duration histogram
http_request_duration_seconds_bucket
# By status code
http_requests_total{status_code="200"}
# Events received
events_received_total{analytics_level="minimal",tool="forecast"}
# Events processed
events_processed_total{status="success"}
# Processing duration
events_processing_duration_seconds
# Current queue depth
queue_depth
# Queue operations
queue_operations_total{operation="enqueue",status="success"}
# Query duration
database_query_duration_seconds
# Queries total
database_queries_total{operation="insert",table="events"}
# Connection pool
database_connection_pool{state="total"}
# Batch size
worker_batch_size
# Worker errors
worker_errors_total{error_type="database_insert"}
API Error Rate (last 5 minutes):
100 * (
sum(rate(http_requests_total{status_code=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
)
p95 Response Time:
histogram_quantile(0.95,
rate(http_request_duration_seconds_bucket[5m])
)
Events per Minute:
rate(events_received_total[1m]) * 60
- Critical: Immediate action required (paged)
- Warning: Should be investigated (emailed)
- Info: For awareness only (logged)
- APIDown: API unreachable for >1 minute
- VeryHighErrorRate: >10% error rate for >1 minute
- CriticalQueueBacklog: >5000 events in queue
- QueueNearCapacity: >9000 events (90% capacity)
- WorkerProcessingStalled: Worker not processing despite queue backlog
- DatabaseDown: Database unreachable for >1 minute
- CriticalMemoryUsage: >450MB memory usage
- HighErrorRate: >5% error rate for >2 minutes
- HighResponseTime: p95 >1s for >5 minutes
- QueueBacklog: >1000 events in queue for >5 minutes
- HighWorkerErrorRate: >0.1 errors/second
- HighDatabaseConnections: >80 connections
- SlowDatabaseQueries: p95 >1s
- HighMemoryUsage: >400MB memory usage
- StaleDataWarning: No events received in 5+ minutes
Edit alertmanager/alertmanager.yml:
global:
smtp_smarthost: 'smtp.gmail.com:587'
smtp_from: 'analytics-alerts@your-domain.com'
smtp_auth_username: 'your-email@gmail.com'
smtp_auth_password: 'your-app-password' # Gmail app password# Manually fire an alert for testing
curl -X POST http://localhost:9093/api/v1/alerts -d '[{
"labels": {
"alertname": "TestAlert",
"severity": "warning"
},
"annotations": {
"summary": "This is a test alert"
}
}]'# 1. Check Grafana dashboards
# Visit: http://localhost:3001
# Look for: Red panels, high error rates, growing queue
# 2. Check Prometheus targets
# Visit: http://localhost:9090/targets
# Ensure all targets are "UP"
# 3. Check Alertmanager
# Visit: http://localhost:9093
# Look for: Active alerts
# 4. Run health check script
./scripts/health-check.sh-
Check API Health Dashboard
- Identify which endpoint has errors
- Check if error rate correlates with traffic spike
-
Query Prometheus for Details
# Errors by route sum by (route) (rate(http_requests_total{status_code=~"5.."}[5m])) -
Check Application Logs
docker compose logs api | grep ERROR -
Verify Database Health
- Check connection pool on Database dashboard
- Look for slow queries
-
Check Worker & Queue Dashboard
- Is queue depth growing?
- Is worker processing events?
- Are there worker errors?
-
Check Worker Status
docker compose logs worker
-
Check Database Performance
- Slow inserts could cause backup
- Check Database dashboard
-
Scale Worker if Needed
# Temporarily scale to 2 workers docker compose up -d --scale worker=2
-
Check All Dashboards
- API Health: High response time?
- Database: Slow queries?
- Infrastructure: High CPU/memory?
-
Query Prometheus
# Slowest endpoints topk(5, histogram_quantile(0.95, sum by (route) (rate(http_request_duration_seconds_bucket[5m])) )) -
Check Database Indexes
# Connect to database docker compose exec postgres psql -U analytics -d analytics # Check slow queries SELECT * FROM pg_stat_statements ORDER BY mean_time DESC LIMIT 10;
Symptoms: No data in Grafana, targets down in Prometheus
Solutions:
- Check Prometheus targets: http://localhost:9090/targets
- Verify API is exposing /metrics endpoint
- Check docker network connectivity
- Review Prometheus logs:
docker compose logs prometheus
Symptoms: Dashboards load but show no data
Solutions:
- Check Prometheus datasource in Grafana
- Settings → Data Sources → Prometheus
- Click "Test" button
- Verify time range (top-right in Grafana)
- Check if metrics exist in Prometheus directly
- Review Grafana logs:
docker compose logs grafana
Symptoms: Metrics show issues but no alerts
Solutions:
- Check Alertmanager is running:
docker compose ps alertmanager
- Verify alert rules in Prometheus:
- Check Alertmanager configuration:
docker compose exec alertmanager amtool check-config /etc/alertmanager/alertmanager.yml - Review Alertmanager logs:
docker compose logs alertmanager
Symptoms: Alerts firing but no emails received
Solutions:
- Check Alertmanager configuration (SMTP settings)
- Verify email credentials are correct
- Check spam folder
- Test SMTP connection:
telnet smtp.gmail.com 587
- Check Alertmanager logs for SMTP errors
- Check Grafana dashboards daily
- Review alerts weekly
- Analyze trends monthly
- Tune alert thresholds based on actual usage
- Use inhibition rules to prevent duplicate alerts
- Adjust repeat intervals appropriately
- Keep 30 days in Prometheus (default)
- Export long-term data if needed
- Consider remote storage for >30 days
- Clone and modify dashboards as needed
- Add panels for your specific needs
- Share dashboards with team
- Document custom metrics
- Update alert runbooks
- Keep this guide current
- Prometheus Documentation: https://prometheus.io/docs/
- Grafana Documentation: https://grafana.com/docs/
- PromQL Tutorial: https://prometheus.io/docs/prometheus/latest/querying/basics/
- Alert Rule Examples: https://awesome-prometheus-alerts.grep.to/
Monitoring Guide Version: 1.0 Last Updated: 2025-01-13 Maintained By: Analytics Server Team