Filter plain-text logs by time range and minimum severity, or summarize them, from the command line.
You have a timestamped application log and want the errors from the last hour, or a quick count of
levels and the most frequent error messages, without a log server or a throwaway script.
logslice is a Python 3.11+ tool with no runtime dependencies that runs on Windows, macOS and Linux.
Using Python 3.11 or newer (use python3 if that is your command):
git clone https://github.com/Gulliby-development/logslice.git
cd logslice
python -m venv .venvActivate the environment on macOS/Linux:
source .venv/bin/activateOr in Windows PowerShell:
.venv\Scripts\Activate.ps1Then install the package:
python -m pip install .
logslice --helpAfter installation, python -m logslice also works.
Accepted log lines start with a timestamp and level:
2026-10-10 12:00:00 INFO Started
2026-10-10T12:00:00.123 warn Slow response
2026-10-10 12:01:00 ERROR Disk full
Levels are case-insensitive and ordered
DEBUG < INFO < WARNING < ERROR < CRITICAL; WARN means WARNING.
Messages may be empty. Timestamps are timezone-naive: Z and UTC offsets are not
supported. Invalid lines, including blank lines and stack-trace continuations,
are skipped.
Read one or more files in argument order:
logslice app.log worker.logFilter by time and minimum level:
logslice app.log --since "2026-10-10 12:00:00" --until 2026-10-10T13:00:00 --level warning
logslice app.log --since 2026-10-10 --level ERRORBoth bounds are inclusive. Filter values accept YYYY-MM-DD (midnight) or
YYYY-MM-DD HH:MM:SS / YYYY-MM-DDTHH:MM:SS, optionally with fractional seconds.
A date-only --until stops at midnight, not at the end of that day.
Without --summary, matching records retain their original text and input order,
with one record per output line.
Filter by message:
logslice app.log --grep Disk2026-10-10 12:01:00 ERROR Disk full
The pattern is a Python regular expression searched in the message only, not in the timestamp or level.
Drop records by message instead: add -v (--invert-match) to --grep to keep only the records whose message does not match.
logslice app.log --grep Disk -v2026-10-10 12:00:00 INFO Started
2026-10-10T12:00:00.123 warn Slow response
-v needs --grep (otherwise it is an error, exit status 2) and works with -i, the time bounds, --level and --summary; a record with an empty message is kept unless the pattern matches the empty string.
Read stdin with no file arguments or with -. On macOS/Linux:
cat app.log | logslice --level ERROR
cat app.log | logslice - --since 2026-10-10In Windows PowerShell:
Get-Content -Encoding utf8 app.log | logslice - --level ERRORSummarize instead of printing records:
logslice app.log --summary
logslice app.log --since 2026-10-10 --level warning --summaryFor the three example log lines above, --summary produces:
Level counts:
DEBUG: 0
INFO: 1
WARNING: 1
ERROR: 1
CRITICAL: 0
Top 5 error messages:
1 Disk full
Skipped lines: 0
Counts and top messages include only records passing the filters. The top list
combines ERROR and CRITICAL messages, sorts by descending frequency, and breaks
ties by first occurrence. Entries are indented by two spaces; it shows (none) if there are no error messages.
The skipped count covers all unparseable input lines, not filtered-out records.
JSON summary: add --summary-format json to print the summary as a JSON object.
logslice app.log --summary --summary-format jsonFor the three example log lines above, this prints:
{
"levels": {
"DEBUG": 0,
"INFO": 1,
"WARNING": 1,
"ERROR": 1,
"CRITICAL": 0
},
"top_errors": [
{
"count": 1,
"message": "Disk full"
}
],
"skipped_lines": 0
}The object has the keys levels, top_errors and skipped_lines.
Top N: add --top N to --summary to change how many error messages are listed
(default 5, at most 100).
For example, with this errors.log:
2026-10-10 12:00:00 ERROR Disk full
2026-10-10 12:00:05 ERROR Timeout
2026-10-10 12:00:09 ERROR Disk full
2026-10-10 12:01:00 CRITICAL Out of memory
logslice errors.log --summary --top 2 prints:
Level counts:
DEBUG: 0
INFO: 0
WARNING: 0
ERROR: 3
CRITICAL: 1
Top 2 error messages:
2 Disk full
1 Timeout
Skipped lines: 0
Count: add --count (-c) to print only the number of matching records, as a decimal number
and a newline, instead of the records. With the errors.log above, logslice errors.log --count
prints:
4
and logslice errors.log --level critical --count prints 1. --count works with the time bounds,
--level, --grep, -i and -v, adds up all input files, and prints 0 when nothing matches.
It cannot be combined with --summary (an error, exit status 2). When an input file cannot be
read, no count is printed.
Max count: add --max-count N (-m N) to stop after the first N matching records, like grep -m.
N is a whole number from 1 to 999999999. With the errors.log above,
logslice errors.log --max-count 2 prints:
2026-10-10 12:00:00 ERROR Disk full
2026-10-10 12:00:05 ERROR Timeout
Records are counted after all filters and across the files in argument order. Once N records
have matched, the rest of the input and any later files are not read, so a later unreadable
file is not reported. With --count the number printed is at most N; with --summary only
those N records are summarized and Skipped lines counts only the lines read until then.
A repeated option takes the last value. An invalid value is an error, exit status 2.
Input is processed line by line as UTF-8, replacing invalid bytes. LF and CRLF line endings are supported; output uses UTF-8. Summary mode keeps per-level and per-distinct-error-message counters rather than loading all records into memory.
Exit status is 0 on success, even with no matches, and 2 for invalid arguments
or unreadable files, including missing paths and directories. File errors name
the path on stderr without a traceback. Output from earlier files may already
have been written when a later file fails.
| Option | Description |
|---|---|
FILE ... |
Log files, read in argument order. No files or - reads stdin. |
--since DATETIME |
Inclusive lower bound: YYYY-MM-DD (midnight) or YYYY-MM-DD[ T]HH:MM:SS[.fraction], no timezone. |
--until DATETIME |
Inclusive upper bound, same formats as --since. |
--level LEVEL |
Minimum level: DEBUG, INFO, WARNING (or WARN), ERROR, CRITICAL; case-insensitive (default DEBUG). |
--grep PATTERN |
Keep only records whose message matches the Python regular expression PATTERN (searched in the message only). |
-i, --ignore-case |
Make --grep case-insensitive. |
-v, --invert-match |
With --grep, keep only records whose message does not match; an error without --grep. |
-m N, --max-count N |
Stop after the first N matching records, N from 1 to 999999999; with --count or --summary only those records count. |
--summary |
Print level counts, up to the top 5 ERROR/CRITICAL messages by default, and the skipped line count instead of records. |
--summary-format {text,json} |
Output format of --summary, default text; json prints the level counts, up to the top 5 error messages by default, and the skipped line count as a JSON object. |
--top N |
With --summary, list the N most frequent ERROR/CRITICAL messages instead of 5; N is 1 to 100. An error without --summary. |
-c, --count |
Print only the number of matching records; an error with --summary. |
-h, --help |
Show help. |
With the virtual environment activated, install the package in editable mode and the development tools:
python -m pip install -e .
python -m pip install pytest ruff
python -m pytest -q
python -m ruff check .The pytest suite covers parsing, filters, summaries and the CLI.
MIT, see LICENSE.
Built with BAKED, an open-source coding agent (bench loop round 02, BAKED ac45a9c).