Skip to main content

Stateful incremental reading of rotated log files with persisted inode/seek position.

Project description

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

python3 -m tailstate.example_standalone

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.

Project details


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.1.0.tar.gz (53.2 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.1.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for tailstate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 da477dcd1ceeb1c6cafccc7ab66a5ed436580626f160a8e72e65d0c400f11015
MD5 990f8a977424861694b6df765120e658
BLAKE2b-256 289084019a164ea65522d11b981b32035f3b5e4daf6de8452939dd125b4ee9f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for tailstate-0.1.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.1.0-py3-none-any.whl.

File metadata

  • Download URL: tailstate-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.5 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 53fe81519cd092209d1388f9441e06ea6461459008e5a5badfc9029cb42e03ff
MD5 c2ad4c543508691c169fe70558f49233
BLAKE2b-256 a7a6253c9d364250f9dc98a25c8d90b9136c68b091e15fe3e4542b816f00903e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tailstate-0.1.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.

Supported by

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