Step 27 of 29
logging, monitoring, configuration, graceful shutdown, rate limiting, health checks
logging, monitoring, configuration, health checks — สิ่งที่ทำให้ service รันได้จริงบน production
Structured logging means your logs are machine-readable data (usually JSON), not free-form text. Each log entry has consistent fields.
When something breaks at 3 AM, you need to search and filter logs fast. Unstructured logs require reading line by line. Structured logs let you query: "show me all errors from the payment service in the last hour with user_id=42."
Text log:
2024-01-15 10:32:01 ERROR Failed to process payment for user 42 - connection timeout
Structured log:
{
"timestamp": "2024-01-15T10:32:01.234Z",
"level": "error",
"service": "payment-service",
"message": "Failed to process payment",
"user_id": 42,
"error_type": "connection_timeout",
"request_id": "req-abc123",
"duration_ms": 5003
}
The second one is searchable, filterable, and aggregatable.
Use them consistently. They mean something specific.
| Level | When to Use |
|---|---|
| ERROR | Something failed. Needs attention. |
| WARN | Unexpected but recoverable. Deprecation. Rate limit approaching. |
| INFO | Business events. User signed up. Order placed. |
| DEBUG | Diagnostic info for development. Detailed flow. |
| TRACE | Very fine-grained. Function entry/exit. Off in production. |
Rules:
In production, logs from multiple services go to a central place:
Loading diagram...
Common stacks:
import structlog
logger = structlog.get_logger()
logger.info("order_placed", order_id=123, user_id=42, total=59.99)
slog.Info("order_placed", "order_id", 123, "user_id", 42, "total", 59.99)
log.info("order_placed").kv("order_id", 123).kv("user_id", 42).kv("total", 59.99).log();