`journal-analyzer` is a read-only Python CLI for reviewing exported `journalctl` text logs. It summarizes systemd, service, and system-level journal findings that require operator review during Linux incident response, post-patching validation, restart troubleshooting, and change evidence collection.
The tool analyzes exported journal text only. It does not call `journalctl` directly, does not modify host state, and does not claim root cause.
## Purpose
- Summarize which units failed and which services appear repeatedly affected.
- Disk and filesystem issues such as `no space left on device`, read-only filesystem, filesystem errors, and I/O errors.
- Service or application crash patterns such as `segfault`.
- TLS and certificate failures.
- Emergency mode findings.
Warning-oriented categories:
- Restart and repeated start request findings.
- Timeout and timed out findings.
- Connection refused and connection reset findings.
- Permission denied and denied findings.
- Authentication failure findings.
- Availability, degraded, failed, and warning findings that still require review.
The matching is practical and pattern-based. Default matching is already case-tolerant for common operational wording, and `--ignore-case` is available for explicit filter runs and predictable operator intent. The tool is intended for first-pass operational review, not for proving causality.
## Timestamp Support
The analyzer attempts to parse common journal and syslog timestamp formats:
-`May 11 10:15:30`
-`2026-05-11 10:15:30`
-`2026-05-11T10:15:30`
-`2026-05-11 10:15:30.123456`
-`2026-05-11 10:15:30,123`
If a timestamp cannot be parsed:
- the line is still analyzed
- first seen / last seen remain `UNKNOWN` where needed
- time-window filters keep the line by default rather than silently discarding it
Syslog-style timestamps without a year use the current local year internally unless `--since` provides a year context.
## Service Filtering
Use `--service SERVICE_NAME` to keep findings for a specific service, unit, or process name. Partial matches are allowed.
-`WARNING` - warning-level findings exist but no critical findings exist.
-`CRITICAL` - one or more critical findings exist.
Critical status is driven by failed units, dependency failures, OOM events, kernel panic findings, disk full or read-only filesystem symptoms, emergency mode, TLS/certificate failures, and I/O or filesystem errors.
Warning status is driven by restart-related findings, timeout patterns, connection issues, permission denied events, authentication failures, degraded messages, and generic warning/failure entries that still require review.
The report summarizes exported journal findings that require review. It does not claim root cause.
-`markdown` - incident or change ticket attachment format.
-`json` - structured output for local automation.
Use `--output <path>` to write the report to a separate file. Without `--output`, the report is printed to stdout.
## Exit Codes
-`0` - OK, no journal findings.
-`1` - Journal findings detected.
-`2` - Invalid input, unreadable file, bad argument, output write failure, or runtime error.
## Example Text Output
```text
Journal Analyzer
================
Overall status: CRITICAL
Journal findings require review; logs alone do not prove root cause.
[CRITICAL] nginx.service - failed_unit
Pattern: failed to start
Occurrences: 1
Unit: nginx.service
Process: systemd
PID: 1
First seen: May 11 10:16:11
Last seen: May 11 10:16:11
Samples:
- May 11 10:16:11 web01 systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
Operational Summary
-------------------
Overall status: CRITICAL
Total lines scanned: 17
Total findings: 13
Critical finding groups: 7
Warning finding groups: 5
Affected services/units count: 9
```
## Markdown Workflow
Generate a Markdown report from an exported journal and attach it to the incident or change ticket as supporting evidence:
```bash
python3 journal_analyzer.py \
--file examples/sample-journal.log \
--format markdown \
--output journal-report.md
```
Review the report before attaching it. Use it as a concise summary of exported journal findings, then correlate it with service status, monitoring, recent changes, package history, and runbook-specific post-checks.
## Operational Limitations
- Pattern matching is intentionally simple and predictable.
- A single line can match more than one finding when it contains more than one meaningful symptom, such as a TLS failure plus certificate expiry.
- Default matching is already case-tolerant for practical journal review; `--ignore-case` remains available when you want to force case-insensitive operator searches.
- Unit, process, and PID extraction are best-effort and may return `UNKNOWN`.
- Time filtering is best-effort because lines without parseable timestamps are retained.
- Large log files are read into memory; use scoped journal exports for very large review windows.
- The tool does not inspect structured journal fields because v1 works on exported text logs.
## Safety Notes
- The tool only reads the input journal export and optionally writes a separate report.