Files
motovaultpro/docs/LOGGING.md
Eric Gullickson 72275096f8
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 31s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 22s
Deploy to Staging / Verify Staging (pull_request) Successful in 2m31s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
docs: add unified logging system documentation and CI/CD integration (refs #87)
- Update staging workflow to use LOG_LEVEL=DEBUG
- Create docs/LOGGING.md with unified logging documentation
- Delete docs/UX-DEBUGGING.md (replaced by LOGGING.md)
- Update architecture to 9-container (6 app + 3 logging)
- Update CLAUDE.md, README.md, docs/README.md, docs/CLAUDE.md
- Update docs/PLATFORM-SERVICES.md deployment section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:50:20 -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
              Promtail --> Loki (30-day retention) --> Grafana

Troubleshooting

Logs not appearing in Grafana

  1. Check Promtail is running: docker logs mvp-promtail
  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.