From bd0706e025f87db8e358bfe0471b43a8beb0cd76 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 29 Jun 2012 15:26:50 +0200 Subject: [PATCH] Take care when parsing values from the past: as we don't know the year of previous records, we have to guess it (december to january transition is dangerous). see #113 --- modoboa/extensions/stats/grapher.py | 30 +++++++------- .../stats/management/commands/logparser.py | 41 ++++++++++++++----- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/modoboa/extensions/stats/grapher.py b/modoboa/extensions/stats/grapher.py index 4237ed7d9..8d8f3f10f 100644 --- a/modoboa/extensions/stats/grapher.py +++ b/modoboa/extensions/stats/grapher.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -import os +import sys, os import time import datetime from django.utils.translation import ugettext as _ @@ -52,22 +52,24 @@ tpl = {'traffic':traffic_avg_template, 'badtraffic':badtraffic_avg_template, 'size':size_avg_template} -def str2Time(y, M, d, h ="0", m ="0", s="0"): - """str2Time +def str2Time(y, M, d, h="0", m="0", s="0"): + """Date conversion - return epoch time from Year Month Day Hour:Minute:Second time format + Returns a date and a time in seconds from the epoch. + + :return: an integer """ try: - local = time.strptime("%s %s %s %s:%s:%s" %(y, M, d, h, m, s), \ - "%Y %b %d %H:%M:%S") - except: - # try with 01-12 month format - try: - local = time.strptime("%s %s %s %s:%s:%s" %(y, M, d, h, m, s), \ - "%Y %m %d %H:%M:%S") - except: - print "[rrd] ERROR unrecognized %s time format" %(y, M, d, h, m, s) - return 0 + if not M.isdigit(): + local = time.strptime("%s %s %s %s:%s:%s" % (y, M, d, h, m, s), \ + "%Y %b %d %H:%M:%S") + else: + local = time.strptime("%s %s %s %s:%s:%s" % (y, M, d, h, m, s), \ + "%Y %m %d %H:%M:%S") + except ValueError: + print >>sys.stderr, "Error: failed to convert date and time" + return 0 + return int(time.mktime(local)) class Grapher(object): diff --git a/modoboa/extensions/stats/management/commands/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py index 92045ec6a..657f80526 100644 --- a/modoboa/extensions/stats/management/commands/logparser.py +++ b/modoboa/extensions/stats/management/commands/logparser.py @@ -46,16 +46,16 @@ class LogParser(object): print "%s" % errno sys.exit(1) self.workdir = workdir - self.year = year + self.__year = year self.debug = options["debug"] self.verbose = options["verbose"] self.cfs = ['AVERAGE', 'MAX'] - self.last_month = None - if not self.year: - self.year = time.localtime().tm_year - if self.debug: - print "[rrd] Dealing with year %s" %self.year + curtime = time.localtime() + if not self.__year: + self.__year = curtime.tm_year + self.curmonth = curtime.tm_mon + self.data = {} domains = Domain.objects.all() self.domains = [] @@ -176,6 +176,29 @@ class LogParser(object): self.initcounters("global", cur_t) self.data["global"][cur_t][counter] += val + def year(self, month): + """Return the appropriate year + + Date used in log files don't always embark the year so we need + to guess it :p + + This method tries to deal with year changes in a simply + (ugly?) way: if we currently are in january and the given + month is different, return the current year -1. Otherwise, + return the current year. + + Obviously, this method only works for year to year + 1 + changes. + + :param month: the month of the current record beeing parsed + :return: an integer + """ + month = time.strptime(month, "%b").tm_mon if not month.isdigit() \ + else int(month) + if self.curmonth == 1 and month != self.curmonth: + return self.__year - 1 + return self.__year + def process(self): id_expr = re.compile("(\w{9,18}): (.*)") prev_se = -1 @@ -189,7 +212,7 @@ class LogParser(object): se = int(int(se) / rrdstep) # rrd step is one-minute => se = 0 if prev_se != se or prev_mi != mi or prev_ho != ho: - cur_t = grapher.str2Time(self.year, mo, da, ho, mi, se) + cur_t = grapher.str2Time(self.year(mo), mo, da, ho, mi, se) cur_t = cur_t - cur_t % rrdstep prev_mi = mi prev_ho = ho @@ -247,9 +270,7 @@ class LogParser(object): for dom, data in self.data.iteritems(): if self.debug: print "[rrd] dealing with domain %s" %dom - sortedData = {} - sortedData = [ (i, data[i]) for i in sorted(data.keys()) ] - for t, dict in sortedData: + for t in sorted(data.keys()): self.update_rrd(dom, t) G.make_defaults(dom, tpl=grapher.traffic_avg_template)