Files
reverse-proxy/tasks/ops/logging.md
glm-5.1 309878c561 Decompose architecture into 23 atomic tasks across 7 parallel generations
Task graph covers all Phase 1 concerns: config system, TLS termination,
proxy handler, operations (rate limiting, logging, health check, admin
socket, signals, shutdown, body size limit), deployment artifacts, and
two review checkpoints.

No circular dependencies. Critical path length of 7. Risk distribution:
3 high-risk (ACME, TLS listener setup, startup orchestration), 7 medium,
11 low, 2 trivial.
2026-06-11 11:21:10 +00:00

3.3 KiB

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
ops/logging Implement structured logging with tracing, file output, and fail2ban-compatible format pending
setup/project-init
moderate low component implementation

Description

Implement structured logging using tracing and tracing-subscriber with dual output (file + stdout) and fail2ban-compatible log format.

Log Types

  1. Access logs (every proxied request, info level):

    REQUEST client_ip=203.0.113.50 host=git.alk.dev method=GET path=/user/repo status=200 upstream=127.0.0.1:3000 duration_ms=45
    
  2. Event logs (rate limits, TLS errors, upstream failures, config reloads):

    RATE_LIMIT client_ip=203.0.113.50 host=git.alk.dev path=/login status=429
    UPSTREAM_ERROR host=git.alk.dev upstream=127.0.0.1:3000 error="connection refused"
    CONFIG_RELOAD status=success sites=1
    

Dual Output

  • File (primary): Written to log_file_path when configured. This is the authoritative source for fail2ban.
  • stdout/stderr (always-on): For docker logs, journalctl, and development.

Use tracing-subscriber Layer composition to write to both simultaneously.

Log Levels

Level Use
error Unrecoverable failures (TLS handshake failure, config validation)
warn Rate limit exceeded, upstream unreachable, upstream timeout
info Access logs, config reloads, ACME events, startup/shutdown
debug Request/response headers, connection details
trace Detailed protocol-level information

Configurable via log_level in StaticConfig.

Configuration

  • logging.level: Log verbosity (default: "info")
  • logging.format: "text" or "json" (default: "text")
  • logging.log_file_path: Optional file path; when set, logs are written to this file in addition to stdout

File Logging and fail2ban

File logging is the primary integration point for fail2ban. In container deployments, the log directory is volume-mounted so fail2ban on the host can read it directly.

A corresponding fail2ban filter definition and jail configuration will be provided in the deployment task.

Acceptance Criteria

  • tracing and tracing-subscriber initialized with dual output (file + stdout)
  • File output enabled when log_file_path is configured
  • Stdout output always enabled
  • Custom event format with key=value pairs
  • REQUEST prefix for access logs
  • RATE_LIMIT prefix for rate limit events
  • UPSTREAM_ERROR prefix for upstream failures
  • CONFIG_RELOAD prefix for config reload events
  • Log level configurable via logging.level
  • JSON format output when logging.format = "json"
  • Text format output when logging.format = "text" (default)
  • duration_ms field in access logs for response time
  • Unit tests for log format output

References

  • docs/architecture/operations.md — logging section, log format
  • docs/architecture/decisions/007-custom-log-format.md — custom log format rationale
  • docs/architecture/decisions/020-container-deployment.md — file-primary logging rationale

Notes

The fail2ban filter and jail configuration are a separate deployment task. This task focuses on producing the correct log format.

Summary

To be filled on completion