Skip to main content

Dependency-free Python failure capture, fingerprinting and assisted replay

Project description

TraceSeed

Turn Python failures into verifiable, reproducible diagnostic packages.

TraceSeed is a modular library with zero runtime dependencies. It captures an exception, collects useful context, removes sensitive information, generates a stable fingerprint, and saves a .tseed package with integrity hashes.

Status: initial release 0.1.0, ready for study, controlled use, and further development. Replay is assisted and should only be used with trusted packages.


Features

  • Small API: @capture, guard(), and capture_exception().
  • Synchronous and asynchronous support.
  • Chained exceptions, notes, and ExceptionGroup.
  • Arguments, locals, traceback, runtime info, threads, and breadcrumbs.
  • Deep sanitization by field name, regex, and custom function.
  • Stable fingerprinting that normalizes IDs, numbers, UUIDs, long tokens, and hex addresses.
  • .tseed packages in ZIP format with a manifest and SHA-256 hashes.
  • Atomic writes to prevent incomplete packages.
  • File, directory, and in-memory storage backends.
  • Extensible collectors and serializers.
  • CLI for viewing, verifying, listing, comparing, and replaying packages.
  • Global hooks for sys, threading, and asyncio.
  • Over 330 regression tests, with lint and static type checking.

Requirements

  • Python 3.11 or higher.
  • No external runtime dependencies.

Quick start (no install)

From the project root:

PYTHONPATH=src python examples/basic.py
PYTHONPATH=src python -m traceseed --version

On Windows PowerShell:

$env:PYTHONPATH = "src"
python examples/basic.py

Installation

python -m pip install .

No runtime dependencies are declared.


Basic example

from traceseed import capture


@capture(operation="process-payment")
def process_payment(order_id: int, token: str) -> None:
    raise ValueError(f"payment rejected for order {order_id}")


process_payment(123, token="secret-token")

The original exception is re-raised. A package is created under .traceseeds/:

.traceseeds/
└── process-payment-traceseed-9c41...-2ac39f10.tseed

The token is redacted before persistence.


Context manager

from traceseed import guard

with guard("import-customers", metadata={"file": "customers.csv"}):
    import_customers()

Manual capture

from traceseed import capture_exception

try:
    execute_job()
except Exception as error:
    result = capture_exception(
        error,
        operation="background-job",
        metadata={"job_id": 42},
    )
    raise

By default, an internal TraceSeed failure never replaces the original exception. Use strict=True in tests or admin tools to surface capture errors explicitly.


Configuration

from pathlib import Path
from traceseed import TraceSeedConfig, configure

configure(
    TraceSeedConfig(
        output_directory=Path("var/traceseeds"),
        capture_arguments=True,
        capture_locals=True,
        capture_argv=False,        # disabled by default — argv may contain secrets
        capture_threads=False,
        max_depth=6,
        max_collection_items=80,
        max_operation_length=256,
        max_exception_depth=20,
        max_exception_children=32,
    ).with_redact_fields({"cpf", "session_id"})
)

Security-relevant defaults

Field Default Notes
capture_argv False sys.argv may contain secrets; opt in explicitly
capture_cwd True working directory is low-risk; disable if needed
max_exception_depth 20 limits chained-exception recursion
max_exception_children 32 limits ExceptionGroup children
max_operation_length 256 operation name is truncated to this length
max_replay_payload_size 1 MB replay payloads larger than this are rejected

Context and breadcrumbs

from traceseed import breadcrumb, context

with context(request_id="req-123", tenant="company-a"):
    breadcrumb("database", "customer loaded", customer_id=42)
    breadcrumb("payment", "gateway request sent")
    process_payment()

Context uses contextvars and stays isolated across async tasks.


Logs as breadcrumbs

import logging
from traceseed import BreadcrumbHandler

handler = BreadcrumbHandler()
logging.getLogger().addHandler(handler)

Storage backends

from traceseed import TraceSeedConfig
from traceseed.serialization import SafeSerializer
from traceseed.storage import ArchiveStorage, DirectoryStorage, MemoryStorage

config = TraceSeedConfig()
serializer = SafeSerializer(config)

archive = ArchiveStorage(config, serializer)   # .tseed ZIP files
directory = DirectoryStorage(config, serializer)  # unpacked directory
memory = MemoryStorage()                       # in-memory, useful in tests

Pass a storage per capture:

@capture(storage=memory)
def operation():
    ...

A custom storage only needs to implement:

class MyStorage:
    name = "my-storage"

    def save(self, record, extra=None):
        ...

Custom collectors

from traceseed import register_collector


class TenantCollector:
    name = "tenant"

    def collect(self, exception, context, config):
        return {"tenant_runtime": read_current_tenant()}


register_collector(TenantCollector())

A failing collector is recorded in collector_errors and does not block the others.


Assisted replay

@capture(operation="calculate-tax", replayable=True)
def calculate_tax(amount, rate):
    return amount * rate

Replay is generated only when the callable is importable and all arguments are reconstructable. If any argument was redacted or could not be serialized, replay.json contains {"replayable": false} and the runner refuses to execute.

traceseed replay failure.tseed --allow-code-execution

Warning: replay imports modules and executes application code. Never replay a package received from an untrusted source.


CLI

traceseed show error.tseed
traceseed show error.tseed --json
traceseed verify error.tseed
traceseed list .traceseeds
traceseed compare first.tseed second.tseed
traceseed replay error.tseed --allow-code-execution

Without installation:

PYTHONPATH=src python -m traceseed show error.tseed

Development

TraceSeed has zero runtime dependencies. Development, testing, linting, and type checking use pytest, Ruff, and mypy.

python -m ruff format --check .
python -m ruff check .
python -m mypy src
python -m pytest

The test suite covers over 330 scenarios, including package corruption, ZIP bomb protection, exception cycles, broken repr(), async concurrency, global hooks, collector failures, and replay.


Project layout

src/traceseed/
├── api.py              public API and hooks
├── engine.py           capture orchestration
├── config.py           immutable configuration
├── context.py          context and breadcrumbs
├── fingerprint.py      stable failure grouping
├── redaction.py        secret removal
├── serialization.py    safe JSON codec
├── collectors/         independent data collectors
├── storage/            file, directory, and memory backends
├── replay/             assisted reproduction
└── cli.py              administrative commands

See also:


Known limitations

  • Replay does not automatically recreate databases, network, external files, or global state.
  • Arbitrary objects are represented for diagnostic purposes but are not automatically reconstructed.
  • Replay isolation is not a security sandbox.
  • Capturing locals may record sensitive data — maintain proper sanitization and limits.

License

MIT.

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

traceseed-0.1.0.tar.gz (64.1 kB view details)

Uploaded Source

Built Distribution

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

traceseed-0.1.0-py3-none-any.whl (40.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for traceseed-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dc30be5f252bc0fe0ff34ca9b3074b38792cb67ab918592f821ad256b5d2d6f4
MD5 58c329cb2b9c47fe1b122cb59c36f9eb
BLAKE2b-256 17b0cd804820e2bd277865e1e38dcef690b4ffd87e1c5f8ced6704d63cd4c6b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for traceseed-0.1.0.tar.gz:

Publisher: publish.yml on igors93/traceseed

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

File details

Details for the file traceseed-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for traceseed-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87ce9aa4c1a81674f3298b058cca6de6bc04739c97194cfad0a6ddfc63f313f3
MD5 69655812c6aebf52bb9bba25e4dc6bef
BLAKE2b-256 c2b207ed0589751cd05bcac234c3463d35d427fb714838dc748be679609fcd28

See more details on using hashes here.

Provenance

The following attestation bundles were made for traceseed-0.1.0-py3-none-any.whl:

Publisher: publish.yml on igors93/traceseed

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