profyle


Nameprofyle JSON
Version 0.3.0 PyPI version JSON
download
home_pagehttps://github.com/vpcarlos/profyle
SummaryProfyle, a development tool for analysing and managing python traces
upload_time2024-04-19 14:44:51
maintainerCarlos Valdivia
docs_urlNone
authorCarlos Valdivia
requires_python<4.0,>=3.9
licenseMIT
keywords cprofile devtool perffeto profyle viztracer fastapi flask
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <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"
}
        
Elapsed time: 4.40065s