Mine the logs of a batch job, bot, crawler, scraper, ETL or any pipeline that works through many units of work grouped into batches, to find where time goes and how to meet a time budget per group...
A pipeline processes units (the smallest piece of work) in groups (a batch, region, tenant, customer, file) and the owner wants each group done within a budget. The job is to turn logs into numbers, numbers into a bottleneck, and the bottleneck into a change whose effect can be re-measured. Opinions about speed are cheap; the same CSV analysed before and after is not.
Analysis is read-only. Recommend changes; apply them only when asked. Speed-ups must respect the other side's limits: never recommend evading rate limits, bans or bot protection. Slow down or spread out instead.
Ask for anything not stated, in one message. If nobody can answer right now, state your assumptions up front, carry on, and put the open questions at the end of the report.
Compute what the budget implies. With N units per group and mean unit time W (waiting included), the average number of units that must be in flight is L = N Γ W / budget (Little's Law). If L is 4 and the pipeline runs 1 at a time, concurrency is the lever; if L is below 1, the pipeline is already fast enough on average and the problem is outliers or waste. Beware: past a point, more concurrency queues work and raises W instead of lowering it.
Produce a CSV with a header group,unit,start,duration_s,status: start as ISO 8601,
status as ok or anything else for a failure. Write a throwaway extraction script for the
log format at hand (grep start and end lines, pair them by unit id, subtract timestamps).
If the logs have no unit id, no timestamps, or no end marker, say so first: not being able to measure is the first finding. Recommend one structured log line per unit (JSON, one object per line, written to stdout) with timestamp, group id, unit id, status and duration, and fall back to differences between consecutive timestamps in the meantime, flagged as approximate.
python3 <this-skill-folder>/scripts/analyze_durations.py runs.csv --budget-min 20
It prints groups ranked by wall-clock time (flagging those over budget), p50 and p95 of the
successful units, failure rate and the median time of failed units, how many other groups ran
at the same time, the median group duration by start hour with a significance test, and the
slowest units. Add --tz-offset H to read hours in the target's local time and --window-h N
for wider buckets. Read it this way:
* means fewer than 20 successful units, so treat that percentile as indicative."Is this the best time to run?" has no general answer; the data decides. Off-peak is not automatically faster, and a target's limits may reset on a fixed window. Before trusting an hour:
?).First confirm the code you are reading is the code that produced the logs: do the log lines,
statuses and timings match what it writes and how long its sleeps and retries would take? If
not (a different version, a wrapper, another service), say so and ask for the right one; waste
found in the wrong code is fiction. Then read it against references/waste-patterns.md. The
usual suspects, in order of
how often they dominate:
Quantify each from the CSV (for example "units retried account for 23% of busy time") instead of asserting it.
Re-extract to the same CSV format and rerun. Success means p95 group wall-clock under budget across enough groups, not one good run. Report before and after side by side.