Structured Logging
debt(d7/e3/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints list phpstan as the tool, and the code pattern is error_log() with string interpolation instead of a structured logger. PHPStan can flag use of error_log() but detecting that the entire logging strategy is unstructured (inconsistent field names, missing correlation IDs, PII leakage) requires code review or observing broken log queries in production. Automated detection covers the surface pattern, not the systemic gap.
Closest to 'simple parameterised fix' (e3). The quick_fix is 'Use Monolog with JsonFormatter and include request_id in every log entry via a processor' — a small but non-trivial change. Swapping to Monolog+JsonFormatter is a few lines, but ensuring consistent field names across services and adding a correlation ID processor touches multiple call sites, making it slightly more than a single-line patch but well within one component scope.
Closest to 'persistent productivity tax' (b5). Applies to web, cli, and queue-worker contexts, meaning every part of the application is affected. Inconsistent logging (different field names per service, missing correlation IDs) slowly degrades observability and shapes how every future log statement is written. Not architectural, but it imposes an ongoing tax on every developer adding logging.
Closest to 'serious trap' (t7). The misconception field states 'Log messages are for humans only' — a deeply held belief that contradicts how logs actually function at scale. Developers familiar with local debug logging naturally write free-form strings and miss structured fields, PII risks, and correlation IDs. This contradicts the mental model carried from development environments into production, making the trap serious rather than merely notable.
Also Known As
TL;DR
Explanation
Structured logs include consistent fields: timestamp, level, message, request_id, user_id, duration_ms, context. JSON is the de facto format for structured logs. Tools like Elasticsearch, Datadog, and CloudWatch Logs Insights can query structured logs efficiently. PHP libraries: Monolog with JsonFormatter. Correlation IDs (request_id) thread a single request across all log entries — essential for debugging distributed systems. Never log PII (email, password, credit card) in plain text.
Common Misconception
Why It Matters
Common Mistakes
- Logging PII (email addresses, passwords, tokens) in plain text — creates compliance and security risk.
- Not including a correlation/request ID — impossible to trace a single request across multiple log entries.
- Using different field names for the same concept across services — breaks cross-service log queries.
Avoid When
- Never log sensitive values — passwords, tokens, credit card numbers, or full request bodies.
- Do not use structured logging as a debugging dump during development — use a debugger instead.
When To Use
- Use structured logging in any application that runs in production — log aggregation tools require it.
- Include a correlation ID on every log entry to trace a single request across multiple services.
Code Examples
// Unstructured — impossible to query reliably
error_log("User $userId logged in from {$_SERVER['REMOTE_ADDR']} in {$elapsed}ms");
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;
$log = new Logger('app');
$handler = new StreamHandler('php://stdout');
$handler->setFormatter(new JsonFormatter());
$log->pushHandler($handler);
// Structured context — every field is queryable
$log->info('User login', [
'user_id' => $userId,
'ip' => $request->ip(),
'request_id' => $requestId,
'duration_ms'=> $elapsed,
]);