[![PyPI version](https://badge.fury.io/py/django-channels-prometheus.svg)](https://badge.fury.io/py/django-channels-prometheus) [![CI](https://github.com/Frodothedwarf/django-channels-prometheus/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/Frodothedwarf/django-channels-prometheus/actions/workflows/ci.yaml) [![codecov](https://codecov.io/gh/Frodothedwarf/django-channels-prometheus/branch/main/graph/badge.svg?token=UDYMWPIGRR)](https://codecov.io/gh/Frodothedwarf/django-channels-prometheus)
# Django Channels Prometheus
This project was created with the simplest problem in mind, know how many devices are connected to a websocket, and export that metric to a Prometheus endpoint. Currently the only feature this project has is counting the numbers of open connections to a given websocket inside Django Channels.
You can either choose to enable logging for multiple consumers or just one.
Currently there are plans for naming the websockets and outputting different stats, for different websockets.
At the moment all consumers will count towards the same metric.
It works by you add a decorator that redirects all calls to, connect and disconnect functions inside your consumer to proxy through a counter first, and then calls your function in your consumer. That's all it does, nothing fancy, but I really needed the functionallity and decided to publish my work.
## Important
This project only support 1 worker at a time.
If you have installed versions before 1.0.0, you need to make changes to your consumers.
This project has switched to a decorator approach, instead of mocking the consumer class.
## Documentation
Firstly you need to have Django Channels installed, and configured correctly. The project is currently only tested with Daphne and Uvicorn, but other ASGI web servers can be added to tests if the community deems so and or helps with it.
Then install the package via pip:
```
pip install django-channels-prometheus
```
Inside your installed apps in settings.py add the package:
```
INSTALLED_APPS = [
...
'channels_prometheus',
...
]
```
Inside your consumer you need to add either the 'ensure_prometheus_connect_async' decorator if you are using the async version, or 'ensure_prometheus_connect' if you are using the sync version.
See example:
```
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels_prometheus.decorators import ensure_prometheus_connect_async
@ensure_prometheus_connect_async
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
self.room_group_name = f"chat_{self.room_name}"
# Join room group
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name, {"type": "chat.message", "message": message}
)
# Receive message from room group
async def chat_message(self, event):
message = event["message"]
# Send message to WebSocket
await self.send(text_data=json.dumps({"message": message}))
```
After that you will need to add the urls to the Prometheus endpoint to your projects urls like so:
```
from django.urls import path, include
from channels_prometheus import urls as channels_prometheus_urls
from . import views
urlpatterns = [
path('', views.home),
path('metrics/', include(channels_prometheus_urls))
]
```
Also make sure that you are pointing to the Djangos ASGI version inside your `asgi.py`:
```
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings")
# Initialize Django ASGI application early to ensure the AppRegistry
# is populated before importing code that may import ORM models.
django_asgi_app = get_asgi_application()
from tests.routing import websocket_urlpatterns
application = ProtocolTypeRouter(
{
"http": django_asgi_app,
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
),
}
)
```
When all of that is configured you will be able to find your endpoint metrics at the defined url route.
## TODO
* Create documentation
* Seperate different consumers to their own metrics.
* Known issue if the websockets are running on more than one worker, it will give inconsistent results.
## Contributing
Contributions are always welcome!
Read through the `contributing.md` to know how to get started.
Please adhere to this project's `code of conduct`.
## License
[MIT](https://choosealicense.com/licenses/mit/)
Raw data
{
"_id": null,
"home_page": "https://github.com/Frodothedwarf/django-channels-prometheus",
"name": "django-channels-prometheus",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "prometheus, channels, webhook, webhooks, django",
"author": "Frederich Pedersen",
"author_email": "frodo@hobbits.dk",
"download_url": "https://files.pythonhosted.org/packages/ec/11/04948328d6c00a30bf99db095c3112cd49c5a33a8ee7f659ba527025c47d/django_channels_prometheus-1.0.0.tar.gz",
"platform": null,
"description": "[![PyPI version](https://badge.fury.io/py/django-channels-prometheus.svg)](https://badge.fury.io/py/django-channels-prometheus) [![CI](https://github.com/Frodothedwarf/django-channels-prometheus/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/Frodothedwarf/django-channels-prometheus/actions/workflows/ci.yaml) [![codecov](https://codecov.io/gh/Frodothedwarf/django-channels-prometheus/branch/main/graph/badge.svg?token=UDYMWPIGRR)](https://codecov.io/gh/Frodothedwarf/django-channels-prometheus)\n\n# Django Channels Prometheus\n\nThis project was created with the simplest problem in mind, know how many devices are connected to a websocket, and export that metric to a Prometheus endpoint. Currently the only feature this project has is counting the numbers of open connections to a given websocket inside Django Channels.\n\nYou can either choose to enable logging for multiple consumers or just one.\n\nCurrently there are plans for naming the websockets and outputting different stats, for different websockets.\n\nAt the moment all consumers will count towards the same metric.\n\nIt works by you add a decorator that redirects all calls to, connect and disconnect functions inside your consumer to proxy through a counter first, and then calls your function in your consumer. That's all it does, nothing fancy, but I really needed the functionallity and decided to publish my work.\n\n\n## Important\nThis project only support 1 worker at a time.\n\nIf you have installed versions before 1.0.0, you need to make changes to your consumers.\nThis project has switched to a decorator approach, instead of mocking the consumer class.\n\n## Documentation\n\nFirstly you need to have Django Channels installed, and configured correctly. The project is currently only tested with Daphne and Uvicorn, but other ASGI web servers can be added to tests if the community deems so and or helps with it.\n\nThen install the package via pip:\n\n```\npip install django-channels-prometheus\n```\n\nInside your installed apps in settings.py add the package:\n\n```\nINSTALLED_APPS = [\n ...\n 'channels_prometheus',\n ...\n]\n```\n\nInside your consumer you need to add either the 'ensure_prometheus_connect_async' decorator if you are using the async version, or 'ensure_prometheus_connect' if you are using the sync version.\n\nSee example:\n\n```\nimport json\n\nfrom channels.generic.websocket import AsyncWebsocketConsumer\nfrom channels_prometheus.decorators import ensure_prometheus_connect_async\n\n@ensure_prometheus_connect_async\nclass ChatConsumer(AsyncWebsocketConsumer):\n async def connect(self):\n self.room_name = self.scope[\"url_route\"][\"kwargs\"][\"room_name\"]\n self.room_group_name = f\"chat_{self.room_name}\"\n\n # Join room group\n await self.channel_layer.group_add(self.room_group_name, self.channel_name)\n\n await self.accept()\n\n async def disconnect(self, close_code):\n # Leave room group\n await self.channel_layer.group_discard(self.room_group_name, self.channel_name)\n\n # Receive message from WebSocket\n async def receive(self, text_data):\n text_data_json = json.loads(text_data)\n message = text_data_json[\"message\"]\n\n # Send message to room group\n await self.channel_layer.group_send(\n self.room_group_name, {\"type\": \"chat.message\", \"message\": message}\n )\n\n # Receive message from room group\n async def chat_message(self, event):\n message = event[\"message\"]\n\n # Send message to WebSocket\n await self.send(text_data=json.dumps({\"message\": message}))\n```\n\nAfter that you will need to add the urls to the Prometheus endpoint to your projects urls like so:\n\n```\nfrom django.urls import path, include\nfrom channels_prometheus import urls as channels_prometheus_urls\nfrom . import views\n\nurlpatterns = [\n path('', views.home),\n path('metrics/', include(channels_prometheus_urls))\n]\n```\n\nAlso make sure that you are pointing to the Djangos ASGI version inside your `asgi.py`:\n\n```\nimport os\n\nfrom channels.auth import AuthMiddlewareStack\nfrom channels.routing import ProtocolTypeRouter, URLRouter\nfrom channels.security.websocket import AllowedHostsOriginValidator\nfrom django.core.asgi import get_asgi_application\n\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"tests.settings\")\n# Initialize Django ASGI application early to ensure the AppRegistry\n# is populated before importing code that may import ORM models.\ndjango_asgi_app = get_asgi_application()\n\nfrom tests.routing import websocket_urlpatterns\n\napplication = ProtocolTypeRouter(\n {\n \"http\": django_asgi_app,\n \"websocket\": AllowedHostsOriginValidator(\n AuthMiddlewareStack(URLRouter(websocket_urlpatterns))\n ),\n }\n)\n```\n\nWhen all of that is configured you will be able to find your endpoint metrics at the defined url route.\n\n## TODO\n\n* Create documentation\n* Seperate different consumers to their own metrics.\n* Known issue if the websockets are running on more than one worker, it will give inconsistent results.\n\n## Contributing\n\nContributions are always welcome!\n\nRead through the `contributing.md` to know how to get started.\n\nPlease adhere to this project's `code of conduct`.\n\n\n## License\n\n[MIT](https://choosealicense.com/licenses/mit/)\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Very simple package that enables a Prometheus endpoint, to check how many websocket connections are currently open.",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/Frodothedwarf/django-channels-prometheus",
"Repository": "https://github.com/Frodothedwarf/django-channels-prometheus"
},
"split_keywords": [
"prometheus",
" channels",
" webhook",
" webhooks",
" django"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "5cbf328af5aeb0cdbaa19416ffa802f618c01dc81e2e587c0b7e6ec1c2d208c3",
"md5": "a513a6f0ec9e6b742b5499c52405d315",
"sha256": "f5598b09281bedaba54219af37d7e174a7302f15d459e07a980195dcdb32d293"
},
"downloads": -1,
"filename": "django_channels_prometheus-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a513a6f0ec9e6b742b5499c52405d315",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 6194,
"upload_time": "2024-09-04T15:53:28",
"upload_time_iso_8601": "2024-09-04T15:53:28.659358Z",
"url": "https://files.pythonhosted.org/packages/5c/bf/328af5aeb0cdbaa19416ffa802f618c01dc81e2e587c0b7e6ec1c2d208c3/django_channels_prometheus-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ec1104948328d6c00a30bf99db095c3112cd49c5a33a8ee7f659ba527025c47d",
"md5": "202b423cae2824021ffec9ead31b4961",
"sha256": "2740d61ab4871d0bc56baadfc531218c6f4d055d3011cbe3ffee72aada32abb8"
},
"downloads": -1,
"filename": "django_channels_prometheus-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "202b423cae2824021ffec9ead31b4961",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 4765,
"upload_time": "2024-09-04T15:53:30",
"upload_time_iso_8601": "2024-09-04T15:53:30.105359Z",
"url": "https://files.pythonhosted.org/packages/ec/11/04948328d6c00a30bf99db095c3112cd49c5a33a8ee7f659ba527025c47d/django_channels_prometheus-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-04 15:53:30",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Frodothedwarf",
"github_project": "django-channels-prometheus",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "django-channels-prometheus"
}