From df7f8bbcaf1034d674ea6013b2df91b4ec7873ab Mon Sep 17 00:00:00 2001 From: Ilan Date: Wed, 12 Aug 2015 12:39:14 +0200 Subject: [PATCH] Adds more stats to the `qinfo` command * Average execution time * Tasks per day/hour/minute/second * Number of schedules --- django_q/monitor.py | 46 +++++++++++++++++++++++++++++++++- django_q/tests/test_monitor.py | 18 ++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/django_q/monitor.py b/django_q/monitor.py index f009cf9..3cbb23d 100644 --- a/django_q/monitor.py +++ b/django_q/monitor.py @@ -1,9 +1,12 @@ +from datetime import timedelta import socket # external from blessed import Terminal # django +from django.db import connection +from django.db.models import Sum, F from django.utils import timezone from django.utils.translation import ugettext as _ @@ -193,12 +196,42 @@ def info(r=redis_client): term = Terminal() ping_redis(r) stat = Stat.get_all(r) + # general stats clusters = len(stat) workers = 0 reincarnations = 0 for cluster in stat: workers += len(cluster.workers) reincarnations += cluster.reincarnations + # calculate tasks pm and avg exec time + tasks_per = 0 + per = _('day') + exec_time = 0 + last_tasks = models.Success.objects.filter(stopped__gte=timezone.now() - timedelta(hours=24)) + tasks_per_day = last_tasks.count() + if tasks_per_day > 0: + # average execution time over the last 24 hours + if not connection.vendor == 'sqlite': + exec_time = last_tasks.aggregate(time_taken=Sum(F('stopped') - F('started'))) + exec_time = exec_time['time_taken'].total_seconds() / tasks_per_day + else: + # can't sum timedeltas on sqlite + for t in last_tasks: + exec_time += t.time_taken() + exec_time = exec_time / tasks_per_day + # tasks per second/minute/hour/day in the last 24 hours + if tasks_per_day > 24 * 60 * 60: + tasks_per = tasks_per_day / (24 * 60 * 60) + per = _('second') + elif tasks_per_day > 24 * 60: + tasks_per = tasks_per_day / (24 * 60) + per = _('minute') + elif tasks_per_day > 24: + tasks_per = tasks_per_day / 24 + per = _('hour') + else: + tasks_per = tasks_per_day + # print to terminal term.clear_eos() col_width = int(term.width / 6) print(term.black_on_green(term.center(_('-- {} summary --').format(Conf.PREFIX)))) @@ -226,6 +259,18 @@ def info(r=redis_client): term.move_x(5 * col_width) + term.white(str(models.Failure.objects.count())) ) + print(term.cyan(_('Schedules')) + + term.move_x(1 * col_width) + + term.white(str(models.Schedule.objects.count())) + + term.move_x(2 * col_width) + + term.cyan(_('Tasks/{}'.format(per))) + + term.move_x(3 * col_width) + + term.white('{0:.2f}'.format(tasks_per)) + + term.move_x(4 * col_width) + + term.cyan(_('Avg time')) + + term.move_x(5 * col_width) + + term.white('{0:.4f}'.format(exec_time)) + ) return True @@ -237,4 +282,3 @@ def ping_redis(r): print(term.red('Can not connect to Redis server.')) logger.exception(e) raise e - diff --git a/django_q/tests/test_monitor.py b/django_q/tests/test_monitor.py index 797a5a0..9a266b0 100644 --- a/django_q/tests/test_monitor.py +++ b/django_q/tests/test_monitor.py @@ -1,10 +1,12 @@ import pytest import redis +from django_q import async from django_q.cluster import Cluster -from django_q.monitor import monitor, Stat, ping_redis +from django_q.monitor import monitor, Stat, ping_redis, info +@pytest.mark.django_db def test_monitor(): assert Stat.get(0).sentinel == 0 c = Cluster() @@ -22,6 +24,20 @@ def test_monitor(): assert found_c is True +@pytest.mark.django_db +def test_info(): + info() + do_sync() + info() + for _ in range(24): + do_sync() + info() + + +def do_sync(): + async('django_q.tests.tasks.countdown', 1, sync=True, save=True) + + @pytest.mark.django_db def test_ping_redis(): r = redis.StrictRedis(port=6388)