Skip to main content

tailstate

Rotation-aware incremental reading of rotated log files with persisted state.

The importable package is tailstate, with code under src/tailstate/. The distribution name in pyproject.toml is tailstate.

It persists inode + byte offset as JSON so a later run can continue from the last fully processed line, or follow rotation to unread files with the same basename prefix.

  • Python: 3.11+
  • Runtime dependencies: standard library only
  • State format: JSON (UTF-8 text), human-readable and stable across Python versions
  • License: MIT (see LICENSE)

Docs

  • README.md: overview, install, quickstart
  • docs/development.md: dev commands, tests, layout, portability notes
  • AGENTS.md: non-obvious traps for coding agents
  • src/tailstate/: module and class docstrings define the precise behavior

Main Pieces

  • RotatedLogFileSavedState: discovers matching log files in one directory, ordered by mtime, and yields open text streams from logs()
  • LogSavedState: typed persisted inode / seek state
  • TimedLogProcessor: processes yielded files under a total SIGALRM budget
  • PersistentObj and JsonPersistentObj: generic JSON-backed persistence helpers
  • Log4jLogLineProcessor: timed processor for log4j-style %d{ISO8601} %p %m%n lines
  • ensure_dir, tmp_file, find_file_by_inode: filesystem helpers

Important Behavior

  • Matching uses a plain filename prefix in the same directory. app.log.1 and app.log-extra both match app.log.
  • logs() yields streams from inside an open-file context. The file stays open until the caller resumes the generator.
  • If byte offsets matter, use readline() or explicit tell() / seek() instead of for line in f.
  • Log streams are opened as UTF-8 with errors="replace".
  • Timed processing uses SIGALRM on Unix. Timeouts can still affect rotation state and partial progress in subtle ways.

Install

Using uv from the project root:

uv sync
uv run pytest
uv run mypy src tests
uv run black src tests

Without uv:

python3 -m venv .venv && source .venv/bin/activate
pip install -e .
pip install black mypy pytest pytest-cov
python -m pytest

Demo

Primary walkthrough:

uv run python examples/rotation_walkthrough.py

This zero-argument demo shows:

  • initial reading from offset 0
  • append-only continuation using saved inode + seek
  • incomplete trailing-line deferral with explicit readline() / seek()
  • rotation-aware continuation from app.log.1 into a fresh app.log

Optional higher-level example:

uv run python examples/log4j_metrics.py

Quickstart

Incremental rotation-aware reading:

from tailstate import RotatedLogFileSavedState

with RotatedLogFileSavedState("/var/log/app/app.log", "/var/run/app-state.json") as state:
    for log_file in state.logs():
        while True:
            line = log_file.readline()
            if not line:
                break
            ...

Timed multi-file processing:

from tailstate import RotatedLogFileSavedState, TimedLogProcessor


class MyProc(TimedLogProcessor):
    def process_log(self, log_file):
        ...  # return (value, skip_others)

    def combine_values(self, old, new):
        ...


with RotatedLogFileSavedState(log_path, state_path) as state:
    result = MyProc(max_duration=60).process(state)

log4j-style line parsing:

from tailstate import Log4jLogLineProcessor


class MyScrape(Log4jLogLineProcessor):
    def get_metrics(self):
        return {"level": {"error": 0}}

    def process_level_error(self, message):
        return {"level": {"error": 1}}

License

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tailstate-0.2.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tailstate-0.2.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file tailstate-0.2.0.tar.gz.

File metadata

  • Download URL: tailstate-0.2.0.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tailstate-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b981be7ece45d698ee336d231c9617e672b53bf85bc73e87941c32bf006a0bd2
MD5 661438d00efcde9475d7ef7750def30a
BLAKE2b-256 f7aa06be0e115334d275d11a60c8345e71b35d32694305925fa14277000a1898

See more details on using hashes here.

Provenance

The following attestation bundles were made for tailstate-0.2.0.tar.gz:

Publisher: publish.yml on dajobe/tailstate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tailstate-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: tailstate-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tailstate-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0709cb97bcc68f79e5894040a3fc2abc87923b190aae7dbd6c3db8d0c6c0f292
MD5 59537d3d7791b317fbd52f63463006af
BLAKE2b-256 a0f82057be7bfb19c54deedce12d8f232d579c85ccdec99f344861da4dd15e75

See more details on using hashes here.

Provenance

The following attestation bundles were made for tailstate-0.2.0-py3-none-any.whl:

Publisher: publish.yml on dajobe/tailstate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page