{"id":28185369,"url":"https://github.com/anuran-roy/pymetrix","last_synced_at":"2025-05-16T06:12:08.888Z","repository":{"id":43058674,"uuid":"427596273","full_name":"anuran-roy/pymetrix","owner":"anuran-roy","description":"A simple Plug and Play Library for getting analytics. See website for docs.","archived":false,"fork":false,"pushed_at":"2022-01-12T21:20:32.000Z","size":42342,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-04-26T08:54:19.042Z","etag":null,"topics":["analytics","metrics","metrics-library","networkx","plugnplay","python","python3","time-series","tortoise-orm","web"],"latest_commit_sha":null,"homepage":"https://anuran-roy.github.io/pymetrix/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anuran-roy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-13T07:18:45.000Z","updated_at":"2022-07-16T21:45:48.000Z","dependencies_parsed_at":"2022-09-06T04:12:35.567Z","dependency_job_id":null,"html_url":"https://github.com/anuran-roy/pymetrix","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anuran-roy%2Fpymetrix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anuran-roy%2Fpymetrix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anuran-roy%2Fpymetrix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anuran-roy%2Fpymetrix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anuran-roy","download_url":"https://codeload.github.com/anuran-roy/pymetrix/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254478120,"owners_count":22077678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","metrics","metrics-library","networkx","plugnplay","python","python3","time-series","tortoise-orm","web"],"created_at":"2025-05-16T06:11:57.938Z","updated_at":"2025-05-16T06:12:08.878Z","avatar_url":"https://github.com/anuran-roy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pymetrix-Python\n\n[![Docs](https://img.shields.io/website?color=whi\u0026down_color=red\u0026down_message=Offline\u0026label=Docs\u0026logo=readthedocs\u0026logoColor=white\u0026style=for-the-badge\u0026up_color=green\u0026up_message=Online\u0026url=https%3A%2F%2Fanuran-roy.github.io%2Ftags%2Fpymetrix%2F)](https://anuran-roy.github.io/tags/pymetrix/)\n## What is Pymetrix?\n\n**Pymetrix** (previously known as **Analyx**) is a plug-and-play analytics library written in Python.\n\n## How to use it\n\nPymetrix is really easy to integrate with your projects. Here's an example:\n\nLet's say you want to monitor a method ``foo()`` defined as:\n\n```python\nfrom random import randint\n\ndef foo():\n    print(f\"Hello world {randint(0,1000000)}!\")\n```\n\nAfter adding the required lines, the code will look something like this:\n\n```python\nfrom random import randint\nfrom pymetrix.metrics import Metrics\n\nmetricman = Metrics(__file__)\nfoo_obj = None\n\ndef foo():\n    print(f\"Hello world {randint(0,1000000)}!\")\n    if foo_obj is None:\n        ep1 = endpoints.Endpoint(endpoint=\"/\", id=foo)\n        foo_obj = flow.FlowNode(ep1, name=\"Object1\")\n\n    metricman.add_to_analytics(foo_obj, layerName=\"foo\")\n```\n\nYou can access the metrics of ``foo()`` from the ``metricman`` object with:\n\n```python\nmetricman.display(id='foo')\n```\n\nTo get all the metrics of all the methods at once:\n\n```python\nmetricman.display()\n```\n\n## Using with various Web Frameworks\n\nPymetrix can be used in conjunction with other frameworks as well, including web frameworks. The following examples will illustrate it more clearly.\n\n### 1. Using with Django\n\n**[Django](https://www.djangoproject.com/)** is the most popular framework of choice for a vast majority of Python web developers, often dubbed as \"the framework for perfectionists with deadlines\". It is a clean, concise and opinionated framework that enforces code reusability, modularity and code readability. It has an intuitive directory structure, and a large ecosystem of plugins tailor-made for it. Besides those, the usual Python libraries that can be used in tandem with it for designing business logic as well.\n\nBeing a library, you can import Pymetrix on any file that will be executed by the server on calling the endpoints. This is usually the ``views.py`` file in a standard Django project.\n\nA sample ``views.py`` in Django with Pymetrix (Tested on Django 4.0.0):\n\n```python\nfrom django.shortcuts import render, HttpResponse\nfrom django.http import StreamingHttpResponse\n\nfrom typing import Dict, List, Any, Tuple, NewType\n\nfrom pymetrix import metrics, endpoints, flow\nimport pymetrix.visualize as vs\n# Create your views here.\n\n\nmetricman = metrics.Metrics(loc=\"Test\") # Initialize the Analyx Metrics object\n\n\ndef blog(request):\n    # Other code\n    ...\n    node2: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/blog\", id=blog), name=\"Blog\")\n    metricman.add_to_analytics(node2)  # Add the function to the graph corresponding to the metricman object\n\n    # any return stuff\n    return HttpResponse(\"\u003ch1\u003eBlog works!\u003c/h1\u003e\")\n\n\ndef about(request):\n    # Other code\n    ...\n    node3: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/about\", id=about), name=\"About\")\n    metricman.add_to_analytics(node3)  # Add the function to the graph corresponding to the metricman object\n\n    # any return stuff\n    return HttpResponse(\"\u003ch1\u003eAbout works!\u003c/h1\u003e\")\n\n\ndef contact(request):\n    # Other code\n    ...\n    node4: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/contact\", id=contact), name=\"Contact\")\n    metricman.add_to_analytics(node4)  # Add the function to the graph corresponding to the metricman object\n\n    # any return stuff\n    return HttpResponse(\"\u003ch1\u003eContact works!\u003c/h1\u003e\")\n\n\ndef collaborations(request):\n    # Other code\n    ...\n    node6: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/collaborations\", id=collaborations), name=\"Collaborations\")\n    metricman.add_to_analytics(node6)  # Add the function to the graph corresponding to the metricman object\n\n    # any return stuff\n    return HttpResponse(\"\u003ch1\u003eCollaborations works!\u003c/h1\u003e\")\n\n\ndef events(request):\n    # Other code\n    ...\n    node5: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/events\", id=events), name=\"Events\")\n    metricman.add_to_analytics(node5)  # Add the function to the graph corresponding to the metricman object\n\n    # any return stuff\n    return HttpResponse(\"\u003ch1\u003eEvents works!\u003c/h1\u003e\")\n\n\ndef home(request):\n    node1: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/home1\", id=home), name=\"Home\")\n    metricman.add_to_analytics(node1)  # Add the function to the graph corresponding to the metricman object\n\n    return HttpResponse(\"\u003ch1\u003eHome works!\u003c/h1\u003e\")\n\n\n# The methods below won't be added for metrics\n\ndef someMethod(request):\n    ...\n\nclass someClass:\n    ...\n\n\ndef anotherMethod(request):\n    ...\n\n\ndef aThirdMethod(request):\n    ...\n\n```\n\nAlthough I haven't tested it yet, owing to the nature of the ``metricman`` object, I think it can be used in the top level ``urls.py`` for being used over the entire project - one that has multiple Django Apps into it.\n\nAlso, do check out **[Pymetrix Django Dashboard](https://github.com/anuran-roy/pymetrix-dashboard-django.git)**\n\n### 2. Using with FastAPI\n\n**[FastAPI](https://fastapi.tiangolo.com/)** is a micro web framework built on top of Pydantic and Starlette. It claims to be the fastest Pythonic web framework out there for building APIs, and adheres to the OpenAPI standards. It provides two UIs for testing the APIs made through it - Redoc and SwaggerUI. It also provides a lot of functionalities out of the box, such as asynchronous calls, which speeds up API calls, sometimes tremendously. It can be used both with ASGI and WSGI.\n\nIntegrating Pymetrix with FastAPI is as easy as it is in Django, if not easier.\n\n```python\nfrom fastapi import FastAPI, status\nfrom pymetrix import metrics, endpoints, flow\n\n\napp = FastAPI()\n\n\nmetricman = metrics.Metrics(loc=\"Test\")\n\n\n@app.get('/', status_code=status.HTTP_200_OK)\nasync def home():\n    node1: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/home1\", id=home), name=\"Home\")\n    metricman.add_to_analytics(node1)\n\n    return {\n        \"response\": status.HTTP_200_OK,\n        \"message\": \"This is the home page\"\n    }\n\n\n@app.get('/blog', status_code=status.HTTP_200_OK)\nasync def blog():\n    node2: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/blog\", id=blog), name=\"Blog\")\n    metricman.add_to_analytics(node2)\n    \n    return {\n        \"response\": status.HTTP_200_OK,\n        \"message\": \"This is the blog page\"\n    }\n\n\n@app.get('/newsletter', status_code=status.HTTP_200_OK)\nasync def newsletter():\n    node3: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/newsletter\", id=newsletter), name=\"newsletter\")\n    metricman.add_to_analytics(node3)\n    \n    return {\n        \"response\": status.HTTP_200_OK,\n        \"message\": \"This is the newsletter page\"\n    }\n\n\n# The following methods won't be monitored by Pymetrix\n@app.get('/anEndpoint', status_code=status.HTTP_200_OK)\nasync def method1():\n    ...\n\n\n@app.get('/anotherEndpoint', status_code=status.HTTP_200_OK)\nasync def method2():\n    ...\n\n\n@app.get('/aThirdEndpoint', status_code=status.HTTP_200_OK)\nasync def method3():\n    ...\n\n\n@app.get('/statistics', status_code=status.HTTP_200_OK)\nasync def get_statistics():\n    return {\n        \"response\": status.HTTP_200_OK,\n        \"message\": metricman.aggregate()\n    }\n```\n\nNow we start the ``uvicorn`` server using:\n\n```sh\nuvicorn main:app --port 8000 --reload\n```\n\nNow going to ``localhost:8000/statistics`` will give you the aggregate hits on each endpoint.\n\nJust like the case with Django, you can initialize a Pymetrix object in the main.py file and then import into other scripts from there, if you want a centralized view. But you're also free to take a modular approach with your project by initializing the Pymetrix objects within each module - your skills are your limit.\n\n### 3. Using with Starlite\n\n**[Starlite](https://goldziher.github.io/starlite/)** is the new challenger in town for Web API frameworks. It's similar to FastAPI in the aspect that it's based on Starlette and Pydantic. But it has a fundamental philosophical difference - Starlite is opinionated, while FastAPI is not. \n\nAccording to the maker of Starlite, Na'aman Hirschfeld (who is also an online friend of mine 😎):\n\n\u003e The intention behind Starlite was to create a higher level opinionated API framework. I placed opinionated in bold because in my view, being opinionated regarding how certain things should be done and shouldn’t be done, and establishing best practices, is one of the most important things a framework can do.\n\nSo let's see how Pymetrix works with Starlite:\n\n```python\nfrom starlite import Starlite, get\nfrom pymetrix import metrics, endpoints, flow\nfrom typing import Dict\n\nmetricman = metrics.Metrics(loc=\"Test\")\n\n\n@get(path=\"/home\")\nasync def home() -\u003e Dict:\n    node1: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/home\", id=home), name=\"Home\")\n    metricman.add_to_analytics(node1)\n    return {\n        \"response\": 200,\n        \"message\": \"Home Page Works\"\n    }\n\n\n@get(path=\"/contact\")\nasync def contact() -\u003e Dict:\n    node2: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/contact\", id=contact), name=\"Contact\")\n    metricman.add_to_analytics(node2)\n    return {\n        \"response\": 200,\n        \"message\": \"Contact Page Works\"\n    }\n\n\n@get(path=\"/collaborations\")\nasync def collaborations() -\u003e Dict:\n    node3: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/collaborations\", id=collaborations), name=\"Collaborations\")\n    metricman.add_to_analytics(node3)\n    return {\n        \"response\": 200,\n        \"message\": \"Collaborations Page Works\"\n    }\n\n\n@get(path=\"/events\")\nasync def events() -\u003e Dict:\n    node4: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/events\", id=events), name=\"Events\")\n    metricman.add_to_analytics(node4)\n    return {\n        \"response\": 200,\n        \"message\": \"Events Page Works\"\n    }\n\n\n@get(path=\"/blog\")\nasync def blog() -\u003e Dict:\n    node5: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/blog\", id=blog), name=\"Blog\")\n    metricman.add_to_analytics(node5)\n    return {\n        \"response\": 200,\n        \"message\": \"Blog Page Works\"\n    }\n\n\n@get(path=\"/about\")\nasync def about() -\u003e Dict:\n    node6: flow.FlowNodeType = flow.FlowNode(endpoints.Endpoint(endpoint=\"/about\", id=about), name=\"About\")\n    metricman.add_to_analytics(node6)\n    return {\n        \"response\": 200,\n        \"message\": \"About Page Works\"\n    }\n\n\n@get(path=\"/statistics\")\nasync def statistics() -\u003e Dict:\n    return {\n        \"response\": 200,\n        \"message\": metricman.aggregate()\n    }\n\n\napp = Starlite(route_handlers=[home, contact, collaborations, events, blog, about, statistics])\n```\n\u003c!-- For looking into what more Pymetrix can do, head to ``tests/flow_test.py``. --\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanuran-roy%2Fpymetrix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanuran-roy%2Fpymetrix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanuran-roy%2Fpymetrix/lists"}