Dear Adler,
Thanks again for sharing your code with us.
Do you think it would be possible to use asyncio to defer the
computation of the active connections from the view or middleware ?
Best regards,
Etienne
Le 2017-12-08 à 11:19, Adler Neves a écrit :
forgot mentioning:
the number of active requests is given by "Threads busy" progress bar
and in "Busy threads" line of the table of the previous reply.
Em sexta-feira, 8 de dezembro de 2017 14:07:42 UTC-2, Adler Neves
escreveu:
Hello again, Etienne!
The way you coded that, you are counting how many requests the
server has replied before your request has been processed.
A bit differently than you, I implemented it as a view (which is
not hard to convert into middleware component) that uses
bootstrap, so some small changes are needed.
Let me paste some code from my *views.py*:
"""
import json
from urllib.request import urlopen
class ServerStatsView(TemplateView):
template_name = 'server-stats.html'
def get(self, request):
stats =
json.loads(ServerStatsJsonGetter(request).content.decode())
processed_stats = dict()
processed_stats['workers_total'] = 0
processed_stats['workers_busy'] = 0
processed_stats['workers_accepting_connections'] = 0
processed_stats['threads_total'] = 0
processed_stats['threads_busy'] = 0
processed_stats['requests_processed'] = 0
processed_stats['requests_processing'] = 0
for worker in stats['workers']:
processed_stats['workers_total']+=1
processed_stats['workers_accepting_connections']+=
int(bool(worker['accepting']))
processed_stats['workers_busy']+=int(worker['status']=='busy')
for thread in worker['cores']:
processed_stats['threads_total']+=1
processed_stats['threads_busy']+=int(bool(thread['in_request']))
processed_stats['requests_processed']+=worker['requests']
processed_stats['requests_processing']=processed_stats['threads_busy']
processed_stats['workers_busy_pct'] =
100*processed_stats['workers_busy']/processed_stats['workers_total']
processed_stats['workers_avail_pct'] =
100*processed_stats['workers_accepting_connections']/processed_stats['workers_total']
processed_stats['threads_busy_pct'] =
100*processed_stats['threads_busy']/processed_stats['threads_total']
return render(request, self.template_name, {
'stats':processed_stats,
})
def ServerStatsJsonGetter(request):
with urlopen('http://127.0.0.1:14549
<http://127.0.0.1:14549>') as urlstream:
return HttpResponse(
json.dumps(
json.loads(urlstream.read().decode()),
indent=4
),
content_type='application/json'
)
"""
and now the template *server-stats.html*:
"""
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<h5>
{% trans "Workers available for new connections" %}
</h5>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width:
{{stats.workers_avail_pct}}%"
aria-valuenow="{{stats.workers_accepting_connections}}"
aria-valuemax="{{stats.workers_total}}" aria-valuemin="0">
{{stats.workers_accepting_connections}}
{% trans "of" %}
{{stats.workers_total}}
</div>
</div>
<hr>
<h5>
{% trans "Workers busy" %}
</h5>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width:
{{stats.workers_busy_pct}}%"
aria-valuenow="{{stats.workers_busy}}"
aria-valuemax="{{stats.workers_total}}" aria-valuemin="0">
{{stats.workers_busy}}
{% trans "of" %}
{{stats.workers_total}}
</div>
</div>
<hr>
<h5>
{% trans "Threads busy" %}
</h5>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width:
{{stats.threads_busy_pct}}%"
aria-valuenow="{{stats.threads_busy}}"
aria-valuemax="{{stats.threads_total}}" aria-valuemin="0">
{{stats.threads_busy}}
{% trans "of" %}
{{stats.threads_total}}
</div>
</div>
<hr>
<h5>
Table
</h5>
<div>
<table class="table">
<thead>
<tr>
<th>Aspect</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>
{% trans "Total workers" %}
</td>
<td>
{{stats.workers_total}}
</td>
</tr>
<tr>
<td>
{% trans "Busy workers" %}
</td>
<td>
{{stats.workers_busy}}
</td>
</tr>
<tr>
<td>
{% trans "Workers accepting connections" %}
</td>
<td>
{{stats.workers_accepting_connections}}
</td>
</tr>
<tr>
<td>
{% trans "Total threads" %}
</td>
<td>
{{stats.threads_total}}
</td>
</tr>
<tr>
<td>
{% trans "Busy threads" %}
</td>
<td>
{{stats.threads_busy}}
</td>
</tr>
<tr>
<td>
{% trans "Total processed requests" %}
</td>
<td>
{{stats.requests_processed}}
</td>
</tr>
</tbody>
</table>
</div>
{% endblock content %}
"""
A request dispatched while ApacheBench was generating some load
(concurrency = 15) into the server rendered the image you can find
attached to this message.
Sincerely,
Adler
Em sexta-feira, 8 de dezembro de 2017 10:09:41 UTC-2, Etienne
Robillard escreveu:
Hi Ádler,
Thank you for your reply.
Can you please review this code before I commit?
"""uWSGIController API Version 0.8.3
Middleware for storing uWSGI statistics into the environ object.
"""
import sys
import os
import logging
import demjson
import urllib
logger = logging.getLogger(__name__)
from notmm.controllers.wsgi import WSGIController
__all__ = ('uWSGIController',)
class uWSGIController(WSGIController):
def __init__(self, wsgi_app,
stats_url='http://localhost:9001 <http://localhost:9001>'):
self.wsgi_app = wsgi_app
self.stats_url = stats_url
super(uWSGIController, self).__init__() # hack
def init_request(self, request):
logger.debug('In uWSGIController.init_request...')
request.environ['uwsgi.requests'] =
self.connections(self.stats_url)
self._request = request
self._environ = request.environ
return self._request
def connections(self, url):
"""Return the amount of live connections (requests)
for all workers"""
fp = urllib.urlopen(url)
json = demjson.decode(fp.read())
connections = 0
for worker in json['workers']:
connections += worker['requests']
fp.close()
return connections
Best regards,
Etienne
Le 2017-12-07 à 13:29, Ádler Oliveira Silva Neves a écrit :
Sounds like you want retrieving statistics from uWSGI's stats
server.
http://uwsgi-docs.readthedocs.io/en/latest/StatsServer.html
<http://uwsgi-docs.readthedocs.io/en/latest/StatsServer.html>
In order to get that JSON via HTTP requests, your server
".ini" should receive extra arguments to start an stats
server listening to the specified port and application must
be somehow aware of such port number, which has a side-effect
of increasing coupling.
Sincerely,
Adler
On 07/12/2017 13:13, Etienne Robillard wrote:
Hi,
I would like to access the uWSGI stats API from within
Django by creating a custom WSGI middleware.
Could it be possible to compute the number of requests
currently being used by uWSGI workers in Python/Django ?
Ideally, i could then retrieve the active connections in use
in a standard Django view:
def someview(request):
# retrieve the number of active requests (connections)
connections = request.environ['uwsgi.requests']
What do you think?
Etienne
--
You received this message because you are subscribed to the
Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from
it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at
https://groups.google.com/group/django-users
<https://groups.google.com/group/django-users>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/c6d79973-28b8-5236-a64e-4c24ed3c30a7%40gmail.com
<https://groups.google.com/d/msgid/django-users/c6d79973-28b8-5236-a64e-4c24ed3c30a7%40gmail.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.
--
Etienne Robillard
tka...@yandex.com
https://www.isotopesoftware.ca/ <https://www.isotopesoftware.ca/>
--
You received this message because you are subscribed to the Google
Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to django-users+unsubscr...@googlegroups.com
<mailto:django-users+unsubscr...@googlegroups.com>.
To post to this group, send email to django-users@googlegroups.com
<mailto:django-users@googlegroups.com>.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/c7a78364-e980-4144-ac1e-d0601a1de51c%40googlegroups.com
<https://groups.google.com/d/msgid/django-users/c7a78364-e980-4144-ac1e-d0601a1de51c%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.
--
Etienne Robillard
tkad...@yandex.com
https://www.isotopesoftware.ca/
--
You received this message because you are subscribed to the Google Groups "Django
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/2c959c23-13ad-869f-b40e-2cae40515180%40yandex.com.
For more options, visit https://groups.google.com/d/optout.