← Week 3: Log Aggregation & Analysis

Day 15: Structured Logging

Phase 6 · Sep 16, 2026

← Week 3: Log Aggregation & Analysis

Agenda (2–3 hours)

  • Read (45 min): tracing-subscriber fmt layer and JSON format; serde_json structured logging patterns; Twelve-Factor App logging guidelines
  • Study (45 min): Compare println!("{}", msg) vs JSON structured logs vs tracing events. What is lost at each level?
  • Practice (45 min): Configure tracing-subscriber with JSON output; add structured fields to every log event; verify log lines are parseable by CloudWatch Logs Insights
  • Challenge (30 min): A log line contains a SQL query with user data embedded as a string. What are the compliance risks, and how do you redesign the instrumentation?
← Week 3: Log Aggregation & Analysis

Why Structured Logs?

Unstructured:

[INFO] 2026-09-16T10:00:00Z Request completed in 45ms with status 200

Structured (JSON):

{"timestamp":"2026-09-16T10:00:00Z","level":"INFO","message":"request completed",
 "http.method":"GET","http.route":"/tasks","http.status":200,"duration_ms":45,
 "trace_id":"abc123","user_id":"alice","service":"task-svc"}

Structured logs are queryable, parseable, and aggregatable — without regex.

← Week 3: Log Aggregation & Analysis

tracing-subscriber JSON Layer

use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

tracing_subscriber::registry()
    .with(EnvFilter::from_default_env())
    .with(
        fmt::layer()
            .json()
            .with_current_span(true)      // include span fields in every event
            .with_span_list(false)        // don't repeat parent spans
            .with_target(true)            // include module path
    )
    .init();

with_current_span(true) propagates all span fields (e.g., trace_id, user_id) to every log event within that span's scope.

← Week 3: Log Aggregation & Analysis

Logging Levels Strategy

Level Use case Example
ERROR Unrecoverable failures; should page DB connection lost
WARN Unexpected but handled; investigate later Retry attempt 3/3
INFO Business events; always on in production Task created, user logged in
DEBUG Diagnostic details; off in production Cache hit/miss, query plan
TRACE Extreme verbosity; dev only Every byte received

Production default: INFO for your code, WARN for dependencies.
RUST_LOG=task_svc=info,tower=warn,aws_sdk=warn

← Week 3: Log Aggregation & Analysis

Key Takeaways

  • Structured JSON logs enable SQL-like queries in CloudWatch Logs Insights and OpenSearch
  • with_current_span(true) propagates span fields to nested log events automatically
  • Log at INFO for business events; use metrics for throughput/latency — don't log per-request in a hot path
  • Treat log content as potentially public data: no secrets, no raw user input, no PII without masking

Tomorrow: CloudWatch Logs — log groups, retention, Logs Insights queries.