<p align="center">
<img
src="https://github.com/vpcarlos/profyle/blob/main/docs/img/profyle.png?raw=true"
width="300"
alt="Profyle"
>
</p>
### Development tool for analysing and managing python traces
[![Tests](https://github.com/vpcarlos/profyle/actions/workflows/test.yml/badge.svg)](https://github.com/vpcarlos/profyle/actions/workflows/test.yml)
<a href="https://pypi.org/project/profyle" target="_blank">
<img src="https://img.shields.io/pypi/v/profyle" alt="Package version">
</a>
<a href="https://pypi.org/project/profyle" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/profyle.svg?color=%2334D058" alt="Supported Python versions">
</a>
## Why do you need Profyle?
### Bottlenecks
With Profyle you can easily detect where in your code you have a bottleneck, simply analyze the trace and see what function or operation is taking most of the execution time of the request
### Enhance performace
Analyze the traces and decide which parts of your code should be improved
## Installation
<div class="termy">
```console
$ pip install profyle
---> 100%
```
</div>
## Example
### 1. Implement
In order to track all your API requests you must implement the <code>ProfyleMiddleware</code>
#### ProfyleMiddleware
| Attribute | Required | Default | Description | ENV Variable |
| --- | --- | --- | --- | --- |
| `enabled` | No | `True` | Enable or disable Profyle | `PROFYLE_ENABLED` |
| `pattern` | No | `None` | 0nly trace those paths that match with [pattern](https://en.wikipedia.org/wiki/Glob_(programming)) | `PROFYLE_PATTERN` |
| `max_stack_depth` | No | `-1` | Limit maximum stack trace depth | `PROFYLE_MAX_STACK_DEPTH` |
| `min_duration` | No | `0` (milisecons) | Only record traces with a greather duration than the limit. | `PROFYLE_MIN_DURATION` |
<details markdown="1" open>
<summary>FastAPI</summary>
```Python
from fastapi import FastAPI
from profyle.fastapi import ProfyleMiddleware
app = FastAPI()
# Trace all requests
app.add_middleware(ProfyleMiddleware)
@app.get("/")
async def root():
return {"hello": "world"}
```
```Python
from fastapi import FastAPI
from profyle.fastapi import ProfyleMiddleware
app = FastAPI()
# Trace all requests that match that start with /users
# with a minimum duration of 100ms and a maximum stack depth of 20
app.add_middleware(
ProfyleMiddleware,
pattern="/users*",
max_stack_depth=20,
min_duration=100
)
@app.get("/users/{user_id}")
async def get_user(user_id: int):
return {"hello": "user"}
```
</details>
<details markdown="1">
<summary>Flask</summary>
```Python
from flask import Flask
from profyle.flask import ProfyleMiddleware
app = Flask(__name__)
app.wsgi_app = ProfyleMiddleware(app.wsgi_app, pattern="*/api/products*")
@app.route("/")
def root():
return "<p>Hello, World!</p>"
```
</details>
<details markdown="1">
<summary>Django</summary>
```Python
# settings.py
MIDDLEWARE = [
...
"profyle.django.ProfyleMiddleware",
...
]
```
</details>
### 2. Run
* Run the web server:
<div class="termy">
```console
$ profyle start
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
### 3. List
* List all requests tracing:
![Alt text](https://github.com/vpcarlos/profyle/blob/main/docs/img/traces.png?raw=true "Traces")
### 4. Analyze
* Profyle stands on the shoulder of giants: <a href="https://github.com/gaogaotiantian/viztracer" class="external-link" target="_blank">Viztracer</a> and <a href="https://github.com/google/perfetto" class="external-link" target="_blank">Perfetto</a>
* Detailed function entry/exit information on timeline with source code
* Super easy to use, no source code change for most features, no package dependency
* Supports threading, multiprocessing, subprocess and async
* Powerful front-end, able to render GB-level trace smoothly
* Works on Linux/MacOS/Window
![Alt text](https://github.com/vpcarlos/profyle/blob/main/docs/img/trace1.png?raw=true "Trace1")
![Alt text](https://github.com/vpcarlos/profyle/blob/main/docs/img/trace2.png?raw=true "Trace2")
## CLI Commands
### start
* Start the web server and view profile traces
| Options | Type | Default | Description |
| --- | --- | --- | --- |
| --port | INTEGER | 0 | web server port |
| --host | TEXT | 127.0.0.1 | web server host |
<div class="termy">
```console
$ profyle start --port 5432
INFO: Uvicorn running on http://127.0.0.1:5432 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
### clean
* Delete all profile traces
<div class="termy">
```console
$ profyle clean
10 traces removed
```
</div>
### check
* Check traces DB size
<div class="termy">
```console
$ profyle check
DB size: 30MB
```
</div>
Raw data
{
"_id": null,
"home_page": "https://github.com/vpcarlos/profyle",
"name": "profyle",
"maintainer": "Carlos Valdivia",
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": "vpcarlos97@gmail.com",
"keywords": "cprofile, devtool, perffeto, profyle, viztracer, fastapi, flask",
"author": "Carlos Valdivia",
"author_email": "vpcarlos97@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/b9/fa/b1f41c8537d80c77b2e734046231432a99c996c5a5b3768ca562d9afd99d/profyle-0.3.0.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <img \n src=\"https://github.com/vpcarlos/profyle/blob/main/docs/img/profyle.png?raw=true\" \n width=\"300\"\n alt=\"Profyle\"\n >\n</p>\n\n### Development tool for analysing and managing python traces\n[![Tests](https://github.com/vpcarlos/profyle/actions/workflows/test.yml/badge.svg)](https://github.com/vpcarlos/profyle/actions/workflows/test.yml)\n<a href=\"https://pypi.org/project/profyle\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/v/profyle\" alt=\"Package version\">\n</a>\n<a href=\"https://pypi.org/project/profyle\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/pyversions/profyle.svg?color=%2334D058\" alt=\"Supported Python versions\">\n</a>\n\n## Why do you need Profyle?\n### Bottlenecks\nWith Profyle you can easily detect where in your code you have a bottleneck, simply analyze the trace and see what function or operation is taking most of the execution time of the request\n\n### Enhance performace\nAnalyze the traces and decide which parts of your code should be improved\n\n\n## Installation\n\n<div class=\"termy\">\n\n```console\n$ pip install profyle\n\n---> 100%\n```\n\n</div>\n\n## Example\n\n### 1. Implement\nIn order to track all your API requests you must implement the <code>ProfyleMiddleware</code>\n#### ProfyleMiddleware\n| Attribute | Required | Default | Description | ENV Variable |\n| --- | --- | --- | --- | --- |\n| `enabled` | No | `True` | Enable or disable Profyle | `PROFYLE_ENABLED` |\n| `pattern` | No | `None` | 0nly trace those paths that match with [pattern](https://en.wikipedia.org/wiki/Glob_(programming)) | `PROFYLE_PATTERN` |\n| `max_stack_depth` | No | `-1` | Limit maximum stack trace depth | `PROFYLE_MAX_STACK_DEPTH` |\n| `min_duration` | No | `0` (milisecons) | Only record traces with a greather duration than the limit. | `PROFYLE_MIN_DURATION` |\n\n\n<details markdown=\"1\" open>\n<summary>FastAPI</summary>\n\n```Python\nfrom fastapi import FastAPI\nfrom profyle.fastapi import ProfyleMiddleware\n\napp = FastAPI()\n# Trace all requests\napp.add_middleware(ProfyleMiddleware)\n\n@app.get(\"/\")\nasync def root():\n return {\"hello\": \"world\"}\n```\n\n```Python\nfrom fastapi import FastAPI\nfrom profyle.fastapi import ProfyleMiddleware\n\napp = FastAPI()\n# Trace all requests that match that start with /users \n# with a minimum duration of 100ms and a maximum stack depth of 20\napp.add_middleware(\n ProfyleMiddleware,\n pattern=\"/users*\",\n max_stack_depth=20,\n min_duration=100\n)\n\n@app.get(\"/users/{user_id}\")\nasync def get_user(user_id: int):\n return {\"hello\": \"user\"}\n```\n</details>\n\n<details markdown=\"1\">\n<summary>Flask</summary>\n\n```Python\nfrom flask import Flask\nfrom profyle.flask import ProfyleMiddleware\n\napp = Flask(__name__)\n\napp.wsgi_app = ProfyleMiddleware(app.wsgi_app, pattern=\"*/api/products*\")\n\n@app.route(\"/\")\ndef root():\n return \"<p>Hello, World!</p>\"\n```\n</details>\n\n<details markdown=\"1\">\n<summary>Django</summary>\n\n```Python\n# settings.py\n\nMIDDLEWARE = [\n ...\n \"profyle.django.ProfyleMiddleware\",\n ...\n]\n```\n</details>\n\n### 2. Run\n* Run the web server:\n\n<div class=\"termy\">\n\n```console\n$ profyle start\n\nINFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\nINFO: Started reloader process [28720]\nINFO: Started server process [28722]\nINFO: Waiting for application startup.\nINFO: Application startup complete.\n```\n\n</div>\n\n### 3. List\n* List all requests tracing:\n\n![Alt text](https://github.com/vpcarlos/profyle/blob/main/docs/img/traces.png?raw=true \"Traces\")\n\n### 4. Analyze\n* Profyle stands on the shoulder of giants: <a href=\"https://github.com/gaogaotiantian/viztracer\" class=\"external-link\" target=\"_blank\">Viztracer</a> and <a href=\"https://github.com/google/perfetto\" class=\"external-link\" target=\"_blank\">Perfetto</a>\n* Detailed function entry/exit information on timeline with source code\n* Super easy to use, no source code change for most features, no package dependency\n* Supports threading, multiprocessing, subprocess and async\n* Powerful front-end, able to render GB-level trace smoothly\n* Works on Linux/MacOS/Window\n\n![Alt text](https://github.com/vpcarlos/profyle/blob/main/docs/img/trace1.png?raw=true \"Trace1\")\n\n![Alt text](https://github.com/vpcarlos/profyle/blob/main/docs/img/trace2.png?raw=true \"Trace2\")\n\n\n\n## CLI Commands\n### start\n* Start the web server and view profile traces\n\n| Options | Type | Default | Description |\n| --- | --- | --- | --- |\n| --port | INTEGER | 0 | web server port | \n| --host | TEXT | 127.0.0.1 | web server host | \n \n\n<div class=\"termy\">\n\n```console\n$ profyle start --port 5432\n\nINFO: Uvicorn running on http://127.0.0.1:5432 (Press CTRL+C to quit)\nINFO: Started reloader process [28720]\nINFO: Started server process [28722]\nINFO: Waiting for application startup.\nINFO: Application startup complete.\n```\n\n</div>\n\n### clean\n* Delete all profile traces\n<div class=\"termy\">\n\n```console\n$ profyle clean\n\n10 traces removed \n```\n\n</div>\n\n### check\n* Check traces DB size\n<div class=\"termy\">\n\n```console\n$ profyle check\n\nDB size: 30MB\n```\n\n</div>\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Profyle, a development tool for analysing and managing python traces",
"version": "0.3.0",
"project_urls": {
"Homepage": "https://github.com/vpcarlos/profyle",
"Repository": "https://github.com/vpcarlos/profyle"
},
"split_keywords": [
"cprofile",
" devtool",
" perffeto",
" profyle",
" viztracer",
" fastapi",
" flask"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "834ca3fcbf6d8a506acafb7b1534e6f657e56ad47496ef60f9ca57b3ea46ec86",
"md5": "8b5381913f615a6887616034ec987964",
"sha256": "43ebeb057b5522afd1448004543bd11c46fe4f33b530ecb8679be97de5a9af46"
},
"downloads": -1,
"filename": "profyle-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8b5381913f615a6887616034ec987964",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 126907,
"upload_time": "2024-04-19T14:44:48",
"upload_time_iso_8601": "2024-04-19T14:44:48.855944Z",
"url": "https://files.pythonhosted.org/packages/83/4c/a3fcbf6d8a506acafb7b1534e6f657e56ad47496ef60f9ca57b3ea46ec86/profyle-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b9fab1f41c8537d80c77b2e734046231432a99c996c5a5b3768ca562d9afd99d",
"md5": "539dd6ec50aeb00e80f22040f23d4892",
"sha256": "92d3af9b06cfdd27f5bf9313dfd9e21a6fe1172fbd7ff361af0fc6f94511a012"
},
"downloads": -1,
"filename": "profyle-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "539dd6ec50aeb00e80f22040f23d4892",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 122715,
"upload_time": "2024-04-19T14:44:51",
"upload_time_iso_8601": "2024-04-19T14:44:51.035871Z",
"url": "https://files.pythonhosted.org/packages/b9/fa/b1f41c8537d80c77b2e734046231432a99c996c5a5b3768ca562d9afd99d/profyle-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-19 14:44:51",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "vpcarlos",
"github_project": "profyle",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "profyle"
}