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

3.6 KiB

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

{
  "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

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:

# 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.