Focused, opt-in runtime call tracing for a single execution context.
Project description
tracepatch
Focused, opt-in runtime call tracing for a single execution context.
tracepatch is a debugging tool. It records function calls, arguments, return values, and timing for one specific scope (a request handler, a CLI command, a background task) and produces a readable call tree. It is not a replacement for OpenTelemetry, structured logging, or APM dashboards. Think of it as a scalpel: you point it at one execution path that is misbehaving, and it tells you exactly what happened. It is recommended you leave tracepatch installed in production and have it ready to use when you need it, since it has zero overhead when not active.
Features
- Pure Python, no external dependencies.
- Zero overhead when inactive. Safe to leave installed in production; the
profiling hook is only active inside a
trace()block. - Works in synchronous and asynchronous code.
- Uses
contextvarsto isolate traces per async task. Concurrent requests on the same event loop do not interfere with each other. - Built-in safety limits (
max_depth,max_calls) that automatically disable tracing if exceeded, preventing runaway overhead. - Human-readable ASCII call tree output with timing.
- JSON export for further processing.
- Recommended to be used in production, can help diagnose issues that only occur in production environments, or issues that weren't caught in staging, they will show up in the trace and can be analyzed. Leaves no overhead when not in use, so it's safe to have it installed and ready to go when you need it.
Installation
pip install tracepatch
Or install from source:
pip install .
Quick start
Synchronous
from tracepatch import trace
def fetch_user(user_id):
return {"id": user_id, "name": "Alice"}
def handle_request():
user = fetch_user(42)
return user
with trace() as t:
handle_request()
print(t.tree())
Output:
└── __main__.handle_request() [0.03ms]
└── __main__.fetch_user(user_id=42) -> {'id': 42, 'name': 'Alice'} [0.01ms]
Asynchronous
import asyncio
from tracepatch import trace
async def fetch_user(user_id):
return {"id": user_id, "name": "Alice"}
async def handle_request():
user = await fetch_user(42)
return user
async def main():
async with trace() as t:
await handle_request()
print(t.tree())
asyncio.run(main())
JSON export
with trace() as t:
handle_request()
t.to_json("trace.json")
The JSON file contains a structured representation of the call tree with timing in milliseconds, suitable for custom analysis scripts.
Configuration
The trace() constructor accepts the following keyword arguments:
| Parameter | Default | Description |
|---|---|---|
ignore_modules |
[] |
List of module name prefixes to exclude from the trace. |
max_depth |
30 |
Maximum call nesting depth. Deeper calls are silently skipped. |
max_calls |
10000 |
Maximum total calls to record. Tracing freezes when exceeded. |
max_repr |
120 |
Maximum character length for repr() of arguments and return values. |
Filtering noise
with trace(ignore_modules=["logging", "urllib3", "ssl"]) as t:
handle_request()
print(t.tree())
Limiting scope
with trace(max_depth=5, max_calls=500) as t:
handle_request()
if t.was_limited:
print("Warning: trace was truncated due to limits")
print(t.tree())
API reference
trace(**kwargs)
Context manager (sync and async). Returns itself. Configuration via keyword arguments listed above.
t.tree() -> str
Returns a human-readable ASCII call tree string with timing information for each call.
t.to_json(path) -> None
Writes the trace to a JSON file. path can be a string, a pathlib.Path,
or a writable file object.
t.call_count -> int
Number of calls recorded.
t.was_limited -> bool
True if the trace was cut short because max_calls was exceeded.
t.roots -> list[TraceNode]
Direct access to the root TraceNode objects for programmatic traversal.
How it works
tracepatch uses sys.settrace to install a lightweight tracing callback
that fires on function call, return, and exception events in the current
thread. On a 'call' event, the global trace function checks a
contextvars.ContextVar to find the active collector for the current
execution context. If no collector is active (the common case in production),
the callback returns None immediately and Python does not trace that frame
further, so overhead is negligible.
When a trace() block is entered, a new collector is created and stored in
the ContextVar. The collector records call events into a tree of TraceNode
objects. When the block exits, the profiling hook is removed (reference
counted, so nested traces work correctly) and the ContextVar is reset.
Because isolation is done through contextvars rather than thread-locals,
concurrent asyncio tasks each get their own independent trace even though
they share a single thread.
Limitations
sys.settracecaptures Python-level calls in the thread while active. C-level functions (builtins, C extensions) are not captured.- There is measurable overhead while a trace block is active. This is a debugging tool meant for targeted use, not always-on instrumentation.
- Traces are scoped to a single thread. If your code spawns threads, only the originating thread is traced by default.
License
MIT. See LICENSE for the full text.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tracepatch-0.1.0.tar.gz.
File metadata
- Download URL: tracepatch-0.1.0.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
081147aff7d08d95b9f91ca0e307325160137fcaa2555df1ad8559859bdd41ba
|
|
| MD5 |
cfbc3eb37584d6b39e4cd35ec66d4adf
|
|
| BLAKE2b-256 |
a7a7bed6b0abade45d1b81011b5c25ad0df5527029b7c59c6eb6e61929903cb9
|
Provenance
The following attestation bundles were made for tracepatch-0.1.0.tar.gz:
Publisher:
publish.yml on levinismynameirl/tracepatch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tracepatch-0.1.0.tar.gz -
Subject digest:
081147aff7d08d95b9f91ca0e307325160137fcaa2555df1ad8559859bdd41ba - Sigstore transparency entry: 943896571
- Sigstore integration time:
-
Permalink:
levinismynameirl/tracepatch@0424253dab83247b2096d2fec3e76c940588beef -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/levinismynameirl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0424253dab83247b2096d2fec3e76c940588beef -
Trigger Event:
release
-
Statement type:
File details
Details for the file tracepatch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tracepatch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9a0cd1440952ed76d5f7ce9af8807f3a9a62b1d81eda0ff48fc75ee3b97f517
|
|
| MD5 |
5e3a44b672f5ce54c7c6d6b39f122b2f
|
|
| BLAKE2b-256 |
31d349af0e0cb7db988e0d42098c037b688215adb73e5fcebcb85cf8245cc1d8
|
Provenance
The following attestation bundles were made for tracepatch-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on levinismynameirl/tracepatch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tracepatch-0.1.0-py3-none-any.whl -
Subject digest:
b9a0cd1440952ed76d5f7ce9af8807f3a9a62b1d81eda0ff48fc75ee3b97f517 - Sigstore transparency entry: 943896574
- Sigstore integration time:
-
Permalink:
levinismynameirl/tracepatch@0424253dab83247b2096d2fec3e76c940588beef -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/levinismynameirl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0424253dab83247b2096d2fec3e76c940588beef -
Trigger Event:
release
-
Statement type: