Finished one part of stats (adding counters and querying them)

This commit is contained in:
Adolfo Gómez 2013-02-07 14:54:52 +00:00
parent e9ff77728f
commit 837e9a6b6a
2 changed files with 42 additions and 20 deletions

View File

@ -104,10 +104,14 @@ class StatsManager(object):
Nothing Nothing
''' '''
from uds.models import getSqlDatetime from uds.models import getSqlDatetime
import time
if stamp is None: if stamp is None:
stamp = getSqlDatetime() stamp = getSqlDatetime()
# To Unix epoch
stamp = int(time.mktime(stamp.timetuple()))
try: try:
(owner_type, owner_id) = self.__getOwner(toWhat) (owner_type, owner_id) = self.__getOwner(toWhat)
except: except:

View File

@ -40,15 +40,17 @@ from uds.core.util.State import State
from uds.core.util import log from uds.core.util import log
from uds.core.services.Exceptions import InvalidServiceException from uds.core.services.Exceptions import InvalidServiceException
from datetime import datetime, timedelta from datetime import datetime, timedelta
from time import mktime
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
NEVER = datetime(1972, 7, 1) NEVER = datetime(1972, 7, 1)
NEVER_UNIX = int(mktime(NEVER.timetuple()))
def getSqlDatetime(): def getSqlDatetime(unix=False):
''' '''
Returns the current date/time of the database server. Returns the current date/time of the database server.
@ -63,9 +65,11 @@ def getSqlDatetime():
cursor = con.cursor() cursor = con.cursor()
if con.vendor == 'mysql': if con.vendor == 'mysql':
cursor.execute('SELECT NOW()') cursor.execute('SELECT NOW()')
return cursor.fetchone()[0] date = cursor.fetchone()[0]
return datetime.now() # If not know how to get database datetime, returns local datetime (this is fine for sqlite, which is local) else:
date = datetime.now() # If not know how to get database datetime, returns local datetime (this is fine for sqlite, which is local)
return int(mktime(date.timetuple()))
# Services # Services
@ -1567,7 +1571,7 @@ class StatsCounters(models.Model):
owner_id = models.IntegerField(db_index=True, default=0) owner_id = models.IntegerField(db_index=True, default=0)
owner_type = models.SmallIntegerField(db_index=True, default=0) owner_type = models.SmallIntegerField(db_index=True, default=0)
counter_type = models.SmallIntegerField(db_index=True, default=0) counter_type = models.SmallIntegerField(db_index=True, default=0)
stamp = models.DateTimeField(db_index=True) stamp = models.IntegerField(db_index=True, default=0)
value = models.IntegerField(db_index=True, default=0) value = models.IntegerField(db_index=True, default=0)
class Meta: class Meta:
@ -1578,47 +1582,61 @@ class StatsCounters(models.Model):
@staticmethod @staticmethod
def get_grouped(owner_type, **kwargs): def get_grouped(owner_type, counter_type, **kwargs):
''' '''
Returns the average stats grouped by interval for owner_type and owner_id (optional) Returns the average stats grouped by interval for owner_type and owner_id (optional)
Note: if someone cant get this more optimized, please, contribute it!
''' '''
filt = 'owner_type='+str(owner_type) filt = 'owner_type'
if type(owner_type) in (list, tuple):
filt += ' in (' + ','.join((str(x) for x in owner_type)) + ')'
else:
filt += '='+str(owner_type)
owner_id = None owner_id = None
if kwargs.has_key('owner_id'): if kwargs.has_key('owner_id'):
owner_id = kwargs['owner_id'] owner_id = kwargs['owner_id']
filt = ' AND owner_id='+str(owner_id) filt = ' AND owner_id='+str(owner_id)
filt += ' AND counter_type='+str(counter_type)
since = kwargs.get('since', NEVER) since = int(kwargs.get('since', NEVER_UNIX))
to = kwargs.get('to', getSqlDatetime()) to = int(kwargs.get('to', getSqlDatetime(True)))
interval = 600 # By default, group items in ten minutes interval (600 seconds) interval = 600 # By default, group items in ten minutes interval (600 seconds)
if kwargs.has_key('elements'): if kwargs.has_key('limit'):
elements = kwargs['elements'] elements = kwargs['limit']
# Protect for division a few lines below... :-)
if elements < 2:
elements = 2
if owner_id is None: if owner_id is None:
q = StatsCounters.objects.filter(owner_type=owner_type,stamp__gte=since, stamp__lte=to) q = StatsCounters.objects.filter(stamp__gte=since, stamp__lte=to)
else: else:
q = StatsCounters.objects.filter(owner_type=owner_type, owner_id=owner_id, stamp__gte=since, stamp__lte=to) q = StatsCounters.objects.filter(owner_id=owner_id, stamp__gte=since, stamp__lte=to)
if type(owner_type) in (list, tuple):
q = q.filter(owner_type__in=owner_type)
else:
q = q.filter(owner_type=owner_type)
if q.count() > elements: if q.count() > elements:
first = q.order_by('stamp')[0].stamp first = q.order_by('stamp')[0].stamp
last = q.order_by('stamp').reverse()[0].stamp last = q.order_by('stamp').reverse()[0].stamp
interval = int(((last-first)/elements).total_seconds()) interval = int((last-first)/(elements-1))
filt += ' AND stamp>=\'{0}\' AND stamp<=\'{1}\' GROUP BY CEIL(UNIX_TIMESTAMP(stamp)/{2}) ORDER BY stamp'.format( filt += ' AND stamp>={0} AND stamp<={1} GROUP BY CEIL(stamp/{2}) ORDER BY stamp'.format(
since.strftime('%Y-%m-%d %H:%M:%S'), to.strftime('%Y-%m-%d %H:%M:%S'), interval) since, to, interval)
query = ('SELECT id,-1 as owner_id,owner_type,counter_type,stamp,' query = ('SELECT -1 as id,-1 as owner_id,-1 as owner_type,-1 as counter_type,stamp,'
'CEIL(AVG(value)) AS value ' 'CEIL(AVG(value)) AS value '
'FROM {0} WHERE {1}').format(StatsCounters._meta.db_table, filt) 'FROM {0} WHERE {1}').format(StatsCounters._meta.db_table, filt)
# We use result as an iterator # We use result as an iterator
for n in StatsCounters.objects.raw(query): return StatsCounters.objects.raw(query)
yield n
def __unicode__(self): def __unicode__(self):
return u"Log of {0}({1}): {2} - {3} - {4}".format(self.owner_type, self.owner_id, self.stamp, self.counter_type, self.value) return u"Log of {0}({1}): {2} - {3} - {4}".format(self.owner_type, self.owner_id, self.stamp, self.counter_type, self.value)
@ -1632,7 +1650,7 @@ class StatsEvents(models.Model):
owner_id = models.IntegerField(db_index=True, default=0) owner_id = models.IntegerField(db_index=True, default=0)
owner_type = models.SmallIntegerField(db_index=True, default=0) owner_type = models.SmallIntegerField(db_index=True, default=0)
event_type = models.SmallIntegerField(db_index=True, default=0) event_type = models.SmallIntegerField(db_index=True, default=0)
stamp = models.DateTimeField(db_index=True) stamp = models.IntegerField(db_index=True, default=0)
class Meta: class Meta:
''' '''