Some work about statistics plugin. It is almost finished (for a basic version)

This commit is contained in:
tonio
2009-11-02 18:27:23 +01:00
parent 2b30c46c0d
commit 53df75f045
5 changed files with 119 additions and 35 deletions
+76
View File
@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
import os
import time
import datetime
import rrdtool
from mailng.lib import getoption
default_avg_template = {
'width' : '540',
'height' : '100',
'title' : 'average message flow per minute',
'vertlabel' : 'msgs/min',
'cf' : 'AVERAGE',
'vars' : {
'sent' : { "type" : "AREA", "color" : "#00FF00", "legend" : "sent messages" },
'recv' : { "type" : "AREA", "color" : "#0000FF", "legend" : "received messages" },
# 'bounced' : { "color" : "#FFFF00", "legend" : "bounced messages" },
# 'reject' : { "color" : "#FF0000", "legend" : "rejected messages" },
}
}
class Grapher(object):
def __init__(self):
self.rrd_rootdir = getoption("RRD_ROOTDIR", "/tmp")
self.img_rootdir = getoption("IMG_ROOTDIR", "/tmp")
def process(self, target, suffix, start, end, tpl=default_avg_template):
rrdfile = "%s/%s.rrd" % (self.rrd_rootdir, target)
if not os.path.exists(rrdfile):
return
ext = "png"
path = "%s/%s_%s_%s.%s" % (self.img_rootdir, target, tpl['cf'], suffix, ext)
start = str(start)
end = str(end)
defs = []
lines = []
for v, d in tpl["vars"].iteritems():
defs += ['DEF:%s=%s:%s:%s' % (v, rrdfile, v, tpl['cf']),
'CDEF:%spm=%s,60,*' % (v, v)]
type = d.has_key("type") and d["type"] or "LINE"
lines += ["%s:%spm%s:%s" % (type, v, d["color"], d["legend"])]
params = defs + lines
rrdtool.graph(path,
"--imgformat", "PNG",
"--width", tpl["width"],
"--height", tpl["height"],
"--start", start,
"--end", end,
"--vertical-label", tpl["vertlabel"],
"--title", tpl["title"],
"--lower-limit", "0",
"--slope-mode",
*params)
def make_defaults(self, target):
#now = int(time.time())
#start = now - (now % 86400)
#end = start + 86400
end = "now"
self.process(target, "day", "-1day", end)
#today = datetime.date.today()
#day = today.day - today.weekday()
#weekbegin = datetime.date(today.year, today.month, day)
#start = weekbegin.strftime("%Y%m%d")
#end = "+1week"
self.process(target, "week", "-1week", end)
# monthbegin = datetime.date(today.year, today.month, 1)
# start = monthbegin.strftime("%Y%m%d")
# end = "+1month"
self.process(target, "month", "-1month", end)
self.process(target, "year", "-1year", end)
+17 -14
View File
@@ -6,8 +6,9 @@ import os
import re
import rrdtool
from optparse import OptionParser
from django.conf import settings
from mailng.lib import getoption
from mailng.admin.models import Domain
import grapher
"""
Postfix log parser.
@@ -85,7 +86,7 @@ class LogParser(object):
# Set up data sources for our RRD
params = []
for v in ["sent", "recv", "bounced", "reje"]:
for v in ["sent", "recv", "bounced", "reject"]:
params += ['DS:%s:%s:%s:0:U' % (v, ds_type, rrdstep * 2)]
# Set up RRD to archive data
@@ -137,25 +138,25 @@ class LogParser(object):
if self.verbose:
print "[rrd] VERBOSE update %s:%s:%s:%s:%s" \
%(m, self.data[dom][m]['sent'], self.data[dom][m]['recv'],\
self.data[dom][m]['bounced'], self.data[dom][m]['reje'])
self.data[dom][m]['bounced'], self.data[dom][m]['reject'])
rrdtool.update(fname, "%s:%s:%s:%s:%s" \
% (m, self.data[dom][m]['sent'],
self.data[dom][m]['recv'],
self.data[dom][m]['bounced'],
self.data[dom][m]['reje']))
self.data[dom][m]['reject']))
self.lupdates[fname] = m
return True
def inc_counter(self, dom, cur_t, counter):
if not self.data[dom].has_key(cur_t):
self.data[dom][cur_t] = \
{'sent' : 0, 'recv' : 0, 'bounced' : 0, 'reje' : 0}
{'sent' : 0, 'recv' : 0, 'bounced' : 0, 'reject' : 0}
self.data[dom][cur_t][counter] += 1
if not self.data["global"].has_key(cur_t):
self.data["global"][cur_t] = \
{'sent' : 0, 'recv' : 0, 'bounced' : 0, 'reje' : 0}
{'sent' : 0, 'recv' : 0, 'bounced' : 0, 'reject' : 0}
self.data["global"][cur_t][counter] += 1
def process(self):
@@ -188,21 +189,23 @@ class LogParser(object):
self.inc_counter(addrto.group(2), cur_t, 'recv')
else:
self.inc_counter(addrto.group(2), cur_t, m.group(3))
continue
m = re.search("NOQUEUE: reject: .*from=<(.*)> to=<([^>]*)>", log)
if m:
addrto = re.match("([^@]+)@(.+)", m.group(2))
if addrto and addrto.group(2) in self.domains:
self.inc_counter(addrto.group(2), cur_t, 'reject')
continue
# Sort everything by time
G = grapher.Grapher()
for dom, data in self.data.iteritems():
sortedData = {}
sortedData = [ (i, data[i]) for i in sorted(data.keys()) ]
for t, dict in sortedData:
self.update_rrd(dom, t)
def getoption(name, default=None):
res = None
try:
res = getattr(settings, name)
except AttributeError:
res = default
return res
G.make_defaults(dom)
if __name__ == "__main__":
log_file = getoption("LOGFILE", "/var/log/maillog")
+5 -3
View File
@@ -13,7 +13,7 @@ from django.conf.urls.defaults import *
from mailng.lib import events, _render
from mailng.admin.views import is_superuser
from mailng.admin.models import Domain, Mailbox
from mailng.extensions.stats.mailrrd import parser
#from mailng.extensions.stats.mailrrd import parser
from django.contrib.auth.decorators \
import login_required
import pdb
@@ -88,7 +88,7 @@ def index(request, dom_id=None):
domains = []
errors = []
domain = None
if not is_superuser(request.user):
if dom_id:
if request.user.has_perm("admin.view_mailboxes"):
domain = Domain.objects.get(pk=dom_id)
if domain:
@@ -102,4 +102,6 @@ def index(request, dom_id=None):
errors.append(_("No Domain defined"))
return _render(request, 'stats/index.html', {
"page" : "Statistics",
"domain" : domain, "domains": domains, "messages" : errors ,"types" : graph_types})
"domain" : domain, "domains": domains, "messages" : errors ,
"periods" : ["day", "week", "month", "year"]
})
+13 -18
View File
@@ -38,29 +38,24 @@
{% domain_menu domain.id "stats" perms %}
{% endif %}
{% endblock %}
{% block middletitle %}
{{ page }}
{% if domain %}
{% trans "Statistics for" %} {{ domain.name }}
{% else %}
{% trans "Global statistics" %}
{% endif %}
{% endblock %}
{% block content %}
<div id="graphcontent">
<table>
{% if graph %}
{% for d in domains %}
{% for g in graph %}
{% for t in types %}
<tr>
<th class="{% cycle 'odd' 'even' %}">{{ d }} > {{ t|lower }} > {{ g }}</th>
</tr>
<tr>
<td>
<img src="/{{ tmp_path }}/{{ g }}_{{ t }}_{{ d }}_postfix.png" alt="No statistics available"/>
</td>
</tr>
{% endfor %}
{% endfor %}
{% endfor %}
{% if domain %}
{% for p in periods %}
<tr>
<td>
<img src="/static/graphs/{{ domain.name }}_AVERAGE_{{ p }}.png" alt="No statistics available" />
</td>
</tr>
{% endfor %}
{% else %}
{% if domains %}
<tr>
+8
View File
@@ -70,3 +70,11 @@ def decode(s, encodings=('ascii', 'utf8', 'latin1')):
except UnicodeDecodeError:
pass
return s.decode('ascii', 'ignore')
def getoption(name, default=None):
res = None
try:
res = getattr(settings, name)
except AttributeError:
res = default
return res