structured loggingjson logslog formattingobservabilitydebuggingdeveloper tools

Format and Parse Structured Logs Like a Pro

Learn how structured logging works, how to read JSON logs, nginx logs, and other common formats, and how to use a log formatter to make them readable.

8 min read

Related Tool

Log Formatter

Open tool

Application logs are your window into what happened, when it happened, and why something went wrong. Raw logs from production systems — especially structured JSON logs — are notoriously difficult to read in their raw form. A single JSON log line can be 500 characters of minified text with dozens of fields.

A log formatter takes raw log output and renders it in a readable, structured way — expanding JSON, colorizing levels, and making it easy to scan for errors.

Structured Logging vs. Plain Text Logs

Traditional log lines look like this:

2024-03-15 14:23:01 ERROR Failed to connect to database host=db.internal port=5432 retry=3

Structured logs encode the same information as JSON:

{"timestamp":"2024-03-15T14:23:01.234Z","level":"ERROR","message":"Failed to connect to database","host":"db.internal","port":5432,"retry":3,"service":"user-api","traceId":"abc123"}

Structured logs are harder to read by eye but much easier to query, filter, and aggregate in log management systems like Datadog, Elastic, Loki, or CloudWatch.

Common Log Formats

JSON logs (Bunyan, Pino, Winston, structlog)

Most modern Node.js, Python, and Go services emit JSON logs. Each line is a valid JSON object with standard fields like timestamp, level, message, and arbitrary additional fields for context.

nginx / Apache access logs

192.168.1.1 - alice [15/Mar/2024:14:23:01 +0000] "GET /api/users HTTP/1.1" 200 1234 "-" "curl/7.81.0"

Fields (by position): remote IP, ident, user, time, request line, status code, bytes sent, referer, user agent.

Logfmt

time=2024-03-15T14:23:01Z level=error msg="connection failed" host=db.internal retries=3

Key=value pairs separated by spaces. Common in Go applications (Logrus, zerolog).

Java / Python stack traces

Multi-line log entries with an exception type, message, and stack trace. The formatter collapses these into a single readable block.

Using the DevHexLab Log Formatter

Paste your raw log output into the input panel. The formatter auto-detects the format (JSON, nginx, logfmt, or plain text) and renders a readable table or structured view.

JSON log features

  • Pretty-print — expands minified JSON with indentation
  • Level colorization — ERROR in red, WARN in yellow, INFO in blue, DEBUG in grey
  • Timestamp formatting — converts epoch milliseconds and ISO 8601 timestamps to local time
  • Field filtering — hide common noisy fields (traceId, spanId, processId) to focus on what matters
  • Search — filter log lines by level, message substring, or field value

Reading a formatted JSON log entry

14:23:01.234  ERROR  user-api
  message:  Failed to connect to database
  host:     db.internal
  port:     5432
  retry:    3
  traceId:  abc123

Much more readable than the raw JSON line.

Log Level Reference

| Level | When to use |

|-------|------------|

| DEBUG | Detailed diagnostic information, disabled in production |

| INFO | Normal operational events (startup, config loaded, request received) |

| WARN | Something unexpected that did not cause a failure (slow query, deprecated usage) |

| ERROR | A failure that requires attention (request failed, database unreachable) |

| FATAL / CRITICAL | The application is unable to continue |

Best Practices for Structured Logging

Include a trace ID on every request. Generate a UUID at the entry point of each request and attach it to every log line in that request's lifecycle. This lets you filter all log lines for a specific request from a sea of logs.

Log at the right level. Overuse of ERROR drowns out real errors. Use WARN for recoverable problems, ERROR for failures that need investigation.

Log structured data, not formatted strings. Instead of "User 123 logged in from 1.2.3.4", log {"event":"user_login","userId":123,"ip":"1.2.3.4"}. Structured fields are filterable; embedded strings are not.

Include duration on every operation. Log how long database queries, HTTP calls, and queue operations take. This makes performance regressions visible in logs before they trigger alerts.

Conclusion

Readable logs dramatically reduce the time it takes to diagnose problems. The DevHexLab Log Formatter turns raw production logs into structured, scannable output so you can find the information you need quickly.