Log Analyzer
Overview
Log viewers filter lines. This skill finds patterns.
Use it when an agent runtime, tool process, gateway, scheduler, or other service
has produced enough log output that individual
hits no longer explain the
system behavior. The analyzer parses standard log lines, normalizes repeated
messages, groups errors by component and tool, and produces a structured anomaly
report that is suitable for debugging sessions or cron digests.
The script is intentionally lightweight and portable: it uses only Python's
standard library and works on any text log with timestamp, level, optional
component, and message fields. It also has a best-effort fallback for
unstructured logs.
Quick Start
bash
cd agent-ops/log-analyzer
python scripts/analyze_logs.py scan --log-file agent.log --since 24h
To write JSON for later Markdown rendering:
bash
python scripts/analyze_logs.py scan --log-file agent.log --since 24h --output scan.json
python scripts/analyze_logs.py report --scan scan.json --output report.md
For cron-compatible anomaly detection:
bash
python scripts/analyze_logs.py scan --log-file agent.log --since 24h --quiet
exits 0 and prints nothing when no anomalies are found. If anomalies
exist, it prints the JSON report so the scheduler can deliver the digest.
What It Detects
- Error clusters — the same normalized error message repeated 3+ times
within the selected time window. URLs, IP addresses, and numbers are replaced
with placeholders before grouping so repeated failures with changing IDs still
cluster.
- Rate limit hits — HTTP , , , , and patterns. The analyzer groups them by
provider when it can detect a provider name.
- Timeout patterns — , , , and
. Results are grouped by detected tool name and include
example URLs where present.
- Tool failures — error lines grouped by tool name extracted from patterns
such as , , , or
lines emitted by a component.
- Session crashes — fatal errors, unhandled exceptions, stack traces,
, , and markers. Multiline stack traces are
grouped as one crash entry with nearby context.
- Component breakdown — error and warning counts by component such as
, , , , or .
- Error timeline — error counts bucketed by hour to reveal spikes and
regressions after deploys or scheduled jobs.
See
references/anomaly-types.md
for detection criteria and interpretation.
Log Format Support
The parser handles standard log lines shaped like:
text
2026-07-06 12:30:45 ERROR [gateway] Connection refused
2026-07-06T12:30:45Z ERROR gateway: Connection refused
12:30:45 ERROR Connection refused
It recognizes
,
,
,
,
,
, and
levels. Components may appear in square brackets after the level or as
after the level. Time-only lines are anchored to the current day (or
to the supplied default date when called as a library). Unstructured lines fall
back to best-effort line-by-line scanning, so obvious
/
strings are
still counted even when the timestamp cannot be parsed.
See
references/log-formats.md
for examples and guidance on adding custom
patterns.
CLI Commands
— analyze a log file for patterns
bash
python scripts/analyze_logs.py scan --log-file LOGFILE [--since TIME] [--output report.json] [--quiet]
Options:
- — required path to the log file.
- — optional time window: minutes/hours/days/weeks, e.g. ,
, , , ; default is all lines.
- — write JSON to a file instead of stdout.
- — cron mode: suppress output when no anomalies are found.
— render Markdown from scan JSON
bash
python scripts/analyze_logs.py report --scan scan.json [--output report.md]
The report contains overview counts, one section per anomaly type, a component
breakdown table, and an hourly error timeline.
— smart tail for recent lines
bash
python scripts/analyze_logs.py tail --log-file LOGFILE [--lines N] [--since TIME]
The smart tail prints plain text with markers suitable for chat delivery:
- normal lines: no marker
- warnings:
- errors:
- repeated recent errors: when the same normalized error is seen 3+ times
Output Format
emits JSON with these top-level fields:
converts that JSON into Markdown:
markdown
# Log Analysis Report
## Overview
- Log file: agent.log
- Lines analyzed: 1542
- Time window: 24h
- Total errors: 12 | warnings: 20
- Anomalies detected: 5 types
Scheduled Summary Integration
For a scheduled digest, run
in quiet mode and include the output only when
it is non-empty:
bash
python scripts/analyze_logs.py scan --log-file /var/log/agent.log --since 24h --quiet --output /tmp/log-scan.json
if [ -s /tmp/log-scan.json ]; then
python scripts/analyze_logs.py report --scan /tmp/log-scan.json
fi
A
job can append the Markdown output under a "Log anomalies"
heading. Keep the analysis window aligned with the summary window (for example,
24 hours for a daily digest) so counts do not overlap or disappear.
Common Pitfalls
- Log rotation breaks time windows. If yesterday's file was rotated out, a
scan over only the current file may miss early-window failures.
Point the scheduler at the active file plus rotated file, or concatenate the
relevant files before scanning.
- Multiline stack traces need the first line. The parser groups indented
stack-trace continuation lines under the preceding parsed log line. If a log
collector strips the first or line, the remaining stack
frames become unstructured context.
- Expected errors can be false positives. Retries, probing, and health
checks may intentionally emit warnings or connection failures. Treat clusters
as "investigate" signals, not automatic incidents.
- First run on a large historical log can overwhelm output. Start with
, inspect the report, then widen the window if needed.
- Changing message formats can split clusters. If an application changes an
error string during a deploy, pre- and post-deploy failures may appear as two
clusters even when the root cause is the same.
- Time-only logs depend on the scan date. lines do not
contain a date. For historical files, prefer full timestamps.
- The error timeline buckets by hour-of-day, not date. On a multi-day
window (), errors from 08:00 on different days merge into one
bar. Use the clusters (which carry full timestamps) for multi-day
forensics; treat the timeline as a time-of-day profile.
- Crash detection is substring-based. The crash regex matches words like
or anywhere in a line, so mentions inside INFO lines
(e.g. "retry succeeded after TimeoutException", "non-fatal warning") count
as crash signals and can set . Treat crash counts as leads
to eyeball, and tune the regex if your logs legitimately chat about
exceptions at INFO level.
What This Skill Is NOT
- Not a log viewer: use , , or a log UI when you need raw line
inspection.
- Not a log shipper: it does not forward logs to storage or observability
systems.
- Not a SIEM: it does not correlate identities, networks, or security events.
- Not real-time monitoring: is a recent-line analyzer, not a daemon or
alerting service.
- Not a root-cause oracle: it highlights patterns so an agent or operator can
investigate faster.
Verification Checklist