π‘ Logging & Telemetry Architecture
Our logging pipeline follows the Twelve-Factor App (Factor XI: Logs) specification[cite: 2]. Applications do not write logs to PostgreSQL or disk files; they emit structured JSON event streams directly to stdout/stderr[cite: 2].
πΊοΈ Telemetry Ingestion Pipeline
graph TD
subgraph Emission Layer
API[apps/api: Go log/slog] -->|JSON to stdout| DockerSocket[/var/run/docker.sock]
Worker[apps/worker: Python structlog] -->|JSON to stdout| DockerSocket
DB[(PostgreSQL Container)] -->|Stdout Stream| DockerSocket
end
subgraph Collection Tier
DockerSocket --> Vector[Vector Shipper Container]
Vector -->|NDJSON Batches :9428| VLogs[VictoriaLogs Engine]
end
subgraph Observability UI
VLogs --> WebUI[VictoriaLogs VMUI: http://localhost:9428/select/vmui]
end
1. Canonical Log Event Schema
Both Go (log/slog) and Python (structlog) emit matching JSON fields to ensure unified querying[cite: 2]:
| Field | Type | Description | Example |
|---|---|---|---|
timestamp |
string | ISO-8601 (RFC 3339) with microsecond precision | 2026-08-30T10:35:00Z[cite: 2] |
level |
string | Log severity (DEBUG, INFO, WARN, ERROR, CRITICAL) |
INFO[cite: 2] |
service |
string | Emitting service identifier (api, worker, dues_postgres) |
api[cite: 2] |
trace_id |
string | Distributed trace correlation UUID | 550e8400-e29b-41d4-a716-446655440000[cite: 2] |
message |
string | Primary description of the event | HTTP request served[cite: 2] |
2. Distributed Tracing (trace_id)
1. Client Request βββΊ Go API (Assigns X-Trace-ID)
β
βΌ
2. API writes event with trace_id to PostgreSQL outbox_events table
β
βΌ
3. Python Worker polls event, binds trace_id to structlog contextvars
β
βΌ
4. Searching trace_id in VictoriaLogs returns the full end-to-end lifecycle
- Go Implementation:
apps/api/internal/middleware/logging_middleware.gointercepts requests, extracts/generatestrace_id, and attaches it tocontext.Context[cite: 2]. - Python Implementation:
apps/worker/src/main.pyextractstrace_idfrom the outbox JSON payload and binds it viastructlog.contextvars.bind_contextvars[cite: 2].
3. Log Levels & Dynamic Configuration
| Level | Environment | Use Case |
|---|---|---|
DEBUG |
APP_ENV=development |
Detailed SQL query parameters and payload traces[cite: 2]. |
INFO |
Development / Production | Standard lifecycle events, HTTP route completions, and worker task completions[cite: 2]. |
WARN |
Production | Recoverable errors, retried worker tasks, or missed non-fatal events[cite: 2]. |
ERROR |
Production | Unhandled panics, failed database transactions, and Dead Letter Queue transitions[cite: 2]. |