Files
motovaultpro/docs/LOGGING.md
Eric Gullickson 1b20673ff6 chore: replace Promtail with Grafana Alloy for log collection (refs #97)
Promtail 2.9.0 embeds Docker client API v1.42 which is incompatible with
Docker Engine v29 (minimum API v1.44). Grafana Alloy v1.12.2 resolves this
by using a compatible Docker client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 19:04:41 -06:00

119 lines
3.6 KiB
Markdown

# Unified Logging System
MotoVaultPro uses a unified logging system with centralized log aggregation.
## Overview
- **Single Control**: One `LOG_LEVEL` environment variable controls all containers
- **Correlation IDs**: `requestId` field traces requests across services
- **Centralized Aggregation**: Grafana + Loki for log querying and visualization
## LOG_LEVEL Values
| Level | Frontend | Backend | PostgreSQL | Redis | Traefik |
|-------|----------|---------|------------|-------|---------|
| DEBUG | debug | debug | all queries, 0ms | debug | DEBUG |
| INFO | info | info | DDL only, 500ms | verbose | INFO |
| WARN | warn | warn | errors, 1000ms | notice | WARN |
| ERROR | error | error | errors only | warning | ERROR |
## Environment Defaults
| Environment | LOG_LEVEL | Purpose |
|-------------|-----------|---------|
| Development | DEBUG | Full debugging locally |
| Staging | DEBUG | Full debugging in staging |
| Production | INFO | Standard production logging |
## Correlation IDs
All logs include a `requestId` field (UUID v4) for tracing requests:
- **Traefik**: Forwards X-Request-Id if present
- **Backend**: Generates UUID if X-Request-Id missing, includes in all logs
- **Frontend**: Includes requestId in API call logs
### Example Log Entry
```json
{
"level": "info",
"time": "2024-01-15T10:30:00.000Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"msg": "Request processed",
"method": "GET",
"path": "/api/vehicles",
"status": 200,
"duration": 45
}
```
## Grafana Access
- URL: https://logs.motovaultpro.com
- Default credentials: admin/admin (change on first login)
### Example LogQL Queries
Query by requestId:
```
{container="mvp-backend"} |= "550e8400-e29b-41d4"
```
Query all errors:
```
{container=~"mvp-.*"} | json | level="error"
```
Query slow requests (>500ms):
```
{container="mvp-backend"} | json | duration > 500
```
## Configuration
Logging configuration is generated by `scripts/ci/generate-log-config.sh`:
```bash
# Generate DEBUG level config
./scripts/ci/generate-log-config.sh DEBUG
# Generate INFO level config
./scripts/ci/generate-log-config.sh INFO
```
This creates `.env.logging` which is sourced by docker-compose.
## Architecture
```
+-----------------------------------------------------------------------+
| CI/CD PIPELINE |
| LOG_LEVEL --> generate-log-config.sh --> .env.logging |
+-----------------------------------------------------------------------+
|
v
+-----------------------------------------------------------------------+
| APPLICATION LAYER |
| Frontend Backend OCR Postgres Redis Traefik |
| | | | | | | |
| +---------+---------+---------+---------+---------+ |
| | |
| Docker Log Driver (json-file, 10m x 3) |
+-----------------------------------------------------------------------+
|
v
Alloy --> Loki (30-day retention) --> Grafana
```
## Troubleshooting
### Logs not appearing in Grafana
1. Check Alloy is running: `docker logs mvp-alloy`
2. Check Loki is healthy: `curl http://localhost:3100/ready`
3. Verify log rotation is not too aggressive
### Invalid LOG_LEVEL
Both frontend and backend will warn and fall back to 'info' if an invalid LOG_LEVEL is provided.