flowtrace


Nameflowtrace JSON
Version 0.4.1 PyPI version JSON
download
home_pageNone
SummarySystem-level execution tracer for Python 3.12+ (PEP 669)
upload_time2025-11-02 14:14:57
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT
keywords python monitoring tracing pep669 async
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            > 🌐 Also available in: [Русская версия](README.ru.md)
<p align="center">
  <img src="https://raw.githubusercontent.com/Python-Fork/FlowTrace/main/logo.png" width="400" alt="FlowTrace logo">
</p>

# 🌀 FlowTrace — Visual Execution Tracing for Python 3.12+
[![PyPI version](https://img.shields.io/pypi/v/flowtrace.svg)](https://pypi.org/project/flowtrace/)
[![Python](https://img.shields.io/badge/python-3.12|3.13|3.14-blue.svg)](#)

>FlowTrace is a system-level tracer built on Python’s Monitoring API (PEP 669).
>It doesn’t “profile time by default”. Instead, it reconstructs what happened in your program — calls, returns,
>structure — with minimal overhead and zero monkey-patching.

> **Status**: experimental alpha. Python 3.12+ only.

---
## Installation
```
pip install flowtrace
```
---
## Quick Start
### 1) One-line decorator
```python
from flowtrace import trace

@trace
def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)

fib(3)
```

Output:

```
→ fib(3)
  → fib(2)
    → fib(1) → 1
    → fib(0) → 0
  ← fib(2) → 1
  → fib(1) → 1
← fib(3) → 2
```
---
## 2) Timing when you need it
```python
from flowtrace import trace

@trace(show_timing=True)
def compute(a, b):
    return a * b

compute(6, 7)
```

Output:

```
→ compute(6, 7) [0.000265s] → 42
```
---
## 3) Manual session
```python
from flowtrace import start_tracing, stop_tracing, print_tree

def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)

start_tracing()
fib(3)
events = stop_tracing()
print_tree(events)
```

Output:
```
→ fib()
  → fib()
    → fib()  → 1
    → fib()  → 0
  ← fib()  → 1
  → fib()  → 1
← fib()  → 2
```
---
## Global configuration
```python
import flowtrace
flowtrace.config(show_args=False, show_result=True, show_timing=True)
```
Controls which information is collected globally.
All flags default to True.

| Flag          | Description                           |
| ------------- | ------------------------------------- |
| `show_args`   | capture and display call arguments    |
| `show_result` | capture and display return values     |
| `show_timing` | measure and display function duration |

## Function-level overrides
```python
@flowtrace.trace(show_args=True)
def foo(x): ...
```

Local flags temporarily override global ones for this function only;
child calls inherit the global configuration.

Example
```python
import flowtrace

flowtrace.config(show_args=False, show_result=True, show_timing=True)

@flowtrace.trace
def a(x): return b(x) + 1

@flowtrace.trace(show_args=True)
def b(y): return y * 2

a(10)
```
Output:
```
→ a() [0.000032s] → 21
  → b(y=10) [0.000010s] → 20
  ← b(y=10)
← a()
```
---
## Why FlowTrace?

- **Not a profiler**: profilers answer “how long”. FlowTrace answers “what, in which order, and why”.

- **Direct line to the VM**: listens to bytecode-level events via sys.monitoring (PEP 669).

- **No code intrusion**: no sys.settrace, no monkey-patching, no stdout noise.

---

## API (current)
```python
from flowtrace import trace, config, start_tracing, stop_tracing, get_trace_data, print_tree
```

-  ```@trace(measure_time: bool = True)```
Decorate a function to include its calls in the trace.
When ```measure_time=True```, durations for this function’s calls are recorded.

- ```start_tracing()``` / ```stop_tracing() -> list[CallEvent]```
Start/stop a process-wide tracing session. By default no timing is recorded here — only structure.

- ```get_trace_data() -> list[CallEvent]```
Access the last recorded events.

- ```print_tree(events)```
Pretty-print a hierarchical call tree.
    
### Event model (```CallEvent```):
``` python
id: int
kind: str
func_name: str
parent_id: int | None
args_repr: str | None
result_repr: str | None
duration: float | None
collect_args: bool
collect_result: bool
collect_timing: bool
```
---
## Design choices (snapshot)

- **Only ```PY_START``` / ```PY_RETURN```**: we do not listen to ```CALL``` to keep the core lean.
Argument strings are provided by the decorator right before the call starts.

- **Exception lifecycle tracing**: FlowTrace now listens to exception-related
  signals (`RAISE`, `RERAISE`, `EXCEPTION_HANDLED`, `PY_UNWIND`).
  Each function frame produces at most one exception event, labeled as
  `[caught]` (handled locally) or `[propagated]` (escaped outward).

- **Timing is opt-in**: ```perf_counter()``` is used only when ```measure_time=True```.
Starting/stopping a session alone does not add timing overhead.

- **Filter user code**: internal modules and site-packages are excluded from the default output.
---
## Design notes

- Zero-overhead when disabled: arguments, results, and timing are gathered only if their flags are True.

- Named argument binding: readable form like a=5, b=2 via inspect.signature, cached at decoration time.

- No cascades: per-function flags affect only that decorated function.
---
## Roadmap

- **Async/coroutine transitions.**

- **JSON export for post-processing.**

- **Include/exclude filters & colorized output.**

- **Minimal CLI helpers.**

---
## Contributing

We welcome small, surgical PRs. The codebase is intentionally compact to be an approachable learning tool for exploring Python 3.12+ internals.

## Development

```bash
python -m pip install -U pip
pip install -e .  # editable install
pip install -U ruff mypy pytest pre-commit
pre-commit install
pytest -q
ruff format .
ruff check .
mypy flowtrace

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "flowtrace",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "python, monitoring, tracing, PEP669, async",
    "author": null,
    "author_email": "Alexandr153 <boss191105@bk.ru>",
    "download_url": "https://files.pythonhosted.org/packages/5a/28/7dfb72f3766ae96e6bbb7426d8cbca40954b42a2b40be53d70f1e849d2dd/flowtrace-0.4.1.tar.gz",
    "platform": null,
    "description": "> \ud83c\udf10 Also available in: [\u0420\u0443\u0441\u0441\u043a\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f](README.ru.md)\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/Python-Fork/FlowTrace/main/logo.png\" width=\"400\" alt=\"FlowTrace logo\">\n</p>\n\n# \ud83c\udf00 FlowTrace \u2014 Visual Execution Tracing for Python 3.12+\n[![PyPI version](https://img.shields.io/pypi/v/flowtrace.svg)](https://pypi.org/project/flowtrace/)\n[![Python](https://img.shields.io/badge/python-3.12|3.13|3.14-blue.svg)](#)\n\n>FlowTrace is a system-level tracer built on Python\u2019s Monitoring API (PEP 669).\n>It doesn\u2019t \u201cprofile time by default\u201d. Instead, it reconstructs what happened in your program \u2014 calls, returns,\n>structure \u2014 with minimal overhead and zero monkey-patching.\n\n> **Status**: experimental alpha. Python 3.12+ only.\n\n---\n## Installation\n```\npip install flowtrace\n```\n---\n## Quick Start\n### 1) One-line decorator\n```python\nfrom flowtrace import trace\n\n@trace\ndef fib(n):\n    return n if n < 2 else fib(n-1) + fib(n-2)\n\nfib(3)\n```\n\nOutput:\n\n```\n\u2192 fib(3)\n  \u2192 fib(2)\n    \u2192 fib(1) \u2192 1\n    \u2192 fib(0) \u2192 0\n  \u2190 fib(2) \u2192 1\n  \u2192 fib(1) \u2192 1\n\u2190 fib(3) \u2192 2\n```\n---\n## 2) Timing when you need it\n```python\nfrom flowtrace import trace\n\n@trace(show_timing=True)\ndef compute(a, b):\n    return a * b\n\ncompute(6, 7)\n```\n\nOutput:\n\n```\n\u2192 compute(6, 7) [0.000265s] \u2192 42\n```\n---\n## 3) Manual session\n```python\nfrom flowtrace import start_tracing, stop_tracing, print_tree\n\ndef fib(n):\n    return n if n < 2 else fib(n-1) + fib(n-2)\n\nstart_tracing()\nfib(3)\nevents = stop_tracing()\nprint_tree(events)\n```\n\nOutput:\n```\n\u2192 fib()\n  \u2192 fib()\n    \u2192 fib()  \u2192 1\n    \u2192 fib()  \u2192 0\n  \u2190 fib()  \u2192 1\n  \u2192 fib()  \u2192 1\n\u2190 fib()  \u2192 2\n```\n---\n## Global configuration\n```python\nimport flowtrace\nflowtrace.config(show_args=False, show_result=True, show_timing=True)\n```\nControls which information is collected globally.\nAll flags default to True.\n\n| Flag          | Description                           |\n| ------------- | ------------------------------------- |\n| `show_args`   | capture and display call arguments    |\n| `show_result` | capture and display return values     |\n| `show_timing` | measure and display function duration |\n\n## Function-level overrides\n```python\n@flowtrace.trace(show_args=True)\ndef foo(x): ...\n```\n\nLocal flags temporarily override global ones for this function only;\nchild calls inherit the global configuration.\n\nExample\n```python\nimport flowtrace\n\nflowtrace.config(show_args=False, show_result=True, show_timing=True)\n\n@flowtrace.trace\ndef a(x): return b(x) + 1\n\n@flowtrace.trace(show_args=True)\ndef b(y): return y * 2\n\na(10)\n```\nOutput:\n```\n\u2192 a() [0.000032s] \u2192 21\n  \u2192 b(y=10) [0.000010s] \u2192 20\n  \u2190 b(y=10)\n\u2190 a()\n```\n---\n## Why FlowTrace?\n\n- **Not a profiler**: profilers answer \u201chow long\u201d. FlowTrace answers \u201cwhat, in which order, and why\u201d.\n\n- **Direct line to the VM**: listens to bytecode-level events via sys.monitoring (PEP 669).\n\n- **No code intrusion**: no sys.settrace, no monkey-patching, no stdout noise.\n\n---\n\n## API (current)\n```python\nfrom flowtrace import trace, config, start_tracing, stop_tracing, get_trace_data, print_tree\n```\n\n-  ```@trace(measure_time: bool = True)```\nDecorate a function to include its calls in the trace.\nWhen ```measure_time=True```, durations for this function\u2019s calls are recorded.\n\n- ```start_tracing()``` / ```stop_tracing() -> list[CallEvent]```\nStart/stop a process-wide tracing session. By default no timing is recorded here \u2014 only structure.\n\n- ```get_trace_data() -> list[CallEvent]```\nAccess the last recorded events.\n\n- ```print_tree(events)```\nPretty-print a hierarchical call tree.\n    \n### Event model (```CallEvent```):\n``` python\nid: int\nkind: str\nfunc_name: str\nparent_id: int | None\nargs_repr: str | None\nresult_repr: str | None\nduration: float | None\ncollect_args: bool\ncollect_result: bool\ncollect_timing: bool\n```\n---\n## Design choices (snapshot)\n\n- **Only ```PY_START``` / ```PY_RETURN```**: we do not listen to ```CALL``` to keep the core lean.\nArgument strings are provided by the decorator right before the call starts.\n\n- **Exception lifecycle tracing**: FlowTrace now listens to exception-related\n  signals (`RAISE`, `RERAISE`, `EXCEPTION_HANDLED`, `PY_UNWIND`).\n  Each function frame produces at most one exception event, labeled as\n  `[caught]` (handled locally) or `[propagated]` (escaped outward).\n\n- **Timing is opt-in**: ```perf_counter()``` is used only when ```measure_time=True```.\nStarting/stopping a session alone does not add timing overhead.\n\n- **Filter user code**: internal modules and site-packages are excluded from the default output.\n---\n## Design notes\n\n- Zero-overhead when disabled: arguments, results, and timing are gathered only if their flags are True.\n\n- Named argument binding: readable form like a=5, b=2 via inspect.signature, cached at decoration time.\n\n- No cascades: per-function flags affect only that decorated function.\n---\n## Roadmap\n\n- **Async/coroutine transitions.**\n\n- **JSON export for post-processing.**\n\n- **Include/exclude filters & colorized output.**\n\n- **Minimal CLI helpers.**\n\n---\n## Contributing\n\nWe welcome small, surgical PRs. The codebase is intentionally compact to be an approachable learning tool for exploring Python 3.12+ internals.\n\n## Development\n\n```bash\npython -m pip install -U pip\npip install -e .  # editable install\npip install -U ruff mypy pytest pre-commit\npre-commit install\npytest -q\nruff format .\nruff check .\nmypy flowtrace\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "System-level execution tracer for Python 3.12+ (PEP 669)",
    "version": "0.4.1",
    "project_urls": {
        "Documentation": "https://github.com/Python-Fork/FlowTrace/blob/main/README.md",
        "Homepage": "https://github.com/Python-Fork/FlowTrace",
        "Issues": "https://github.com/Python-Fork/FlowTrace/issues"
    },
    "split_keywords": [
        "python",
        " monitoring",
        " tracing",
        " pep669",
        " async"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "63d5508f3fdf2261973a47e463ed84cbd0acbb56c237e2320db10224c28ba721",
                "md5": "2251ac17f552fff44065d402d79f7e6d",
                "sha256": "4da71eb78d113c5187a93da942aeb4514203ded71bb118ce2b6ff3d333d33a3f"
            },
            "downloads": -1,
            "filename": "flowtrace-0.4.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2251ac17f552fff44065d402d79f7e6d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 14090,
            "upload_time": "2025-11-02T14:14:56",
            "upload_time_iso_8601": "2025-11-02T14:14:56.345766Z",
            "url": "https://files.pythonhosted.org/packages/63/d5/508f3fdf2261973a47e463ed84cbd0acbb56c237e2320db10224c28ba721/flowtrace-0.4.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5a287dfb72f3766ae96e6bbb7426d8cbca40954b42a2b40be53d70f1e849d2dd",
                "md5": "9ba05ca2c7a4c15207ef3a3928dfcbce",
                "sha256": "237206860b48c3cb87fa71b9a25d855674d7c6f03296a6e8d47f58a2f0a99202"
            },
            "downloads": -1,
            "filename": "flowtrace-0.4.1.tar.gz",
            "has_sig": false,
            "md5_digest": "9ba05ca2c7a4c15207ef3a3928dfcbce",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 16532,
            "upload_time": "2025-11-02T14:14:57",
            "upload_time_iso_8601": "2025-11-02T14:14:57.378617Z",
            "url": "https://files.pythonhosted.org/packages/5a/28/7dfb72f3766ae96e6bbb7426d8cbca40954b42a2b40be53d70f1e849d2dd/flowtrace-0.4.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-02 14:14:57",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Python-Fork",
    "github_project": "FlowTrace",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "flowtrace"
}
        
Elapsed time: 1.81103s