← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Structured Logging

Observability PHP 8.0+ Intermediate
debt(d7/e3/b5/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

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.

e3 Effort Remediation debt — work required to fix once spotted

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.

b5 Burden Structural debt — long-term weight of choosing wrong

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.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

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.

About DEBT scoring →

Also Known As

JSON logging structured logs PHP Monolog JSON log aggregation

TL;DR

Emitting log entries as machine-parseable key-value pairs (JSON) rather than free-form strings — enabling filtering, aggregation, and alerting.

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

Log messages are for humans only. At scale, no human reads individual log lines — logs are ingested by tools that need consistent, parseable fields to surface patterns and alerts.

Why It Matters

Free-form log strings require regex parsing to extract meaning — brittle and slow at scale. Structured logs are queryable immediately: 'show all requests where duration_ms > 1000 and user_id = 42'.

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

✗ Vulnerable
// Unstructured — impossible to query reliably
error_log("User $userId logged in from {$_SERVER['REMOTE_ADDR']} in {$elapsed}ms");
✓ Fixed
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,
]);

Added 31 Mar 2026
Views 73
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 4 pings T 5 pings F 2 pings S 8 pings S 6 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 25 Perplexity 9 Amazonbot 7 Ahrefs 5 Unknown AI 2 Google 2 ChatGPT 2 Claude 1 Bing 1 Meta AI 1 PetalBot 1 SEMrush 1
crawler 55 crawler_json 2
DEV INTEL Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Use Monolog with JsonFormatter and include request_id in every log entry via a processor
📦 Applies To
PHP 8.0+ web cli queue-worker
🔍 Detection Hints
error_log() with string interpolation instead of Monolog/structured logger
Auto-detectable: ✓ Yes phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File


✓ schema.org compliant