/
graphics.py
161 lines (129 loc) · 4.53 KB
/
graphics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import os
import inspect
from lxml import etree
from django.utils.translation import ugettext_lazy
from modoboa.lib import parameters
from modoboa.lib.sysutils import exec_cmd
class Curve(object):
"""Graphic curve.
Simple way to represent a graphic curve.
"""
def __init__(self, dsname, color, legend, cfunc="AVERAGE"):
"""Constructor.
"""
self.dsname = dsname
self.color = color
self.legend = legend.encode("utf-8")
self.cfunc = cfunc
def to_rrd_command_args(self, rrdfile):
"""Convert this curve to the approriate RRDtool command.
:param str rrdfile: RRD file name
:return: a list
"""
rrdfile = os.path.join(
parameters.get_admin("RRD_ROOTDIR"), "%s.rrd" % rrdfile
)
return [
'DEF:%s=%s:%s:%s' %
(self.dsname, rrdfile, self.dsname, self.cfunc),
'CDEF:%(ds)spm=%(ds)s,60,*' % {"ds": self.dsname},
'XPORT:%spm:"%s"' % (self.dsname, self.legend.decode("utf-8"))
]
class Graphic(object):
"""Graphic.
"""
def __init__(self):
"""Constructor.
"""
self._curves = []
try:
order = getattr(self, "order")
except AttributeError:
for member in inspect.getmembers(self):
if isinstance(member[1], Curve):
self._curves += [member[1]]
else:
for name in order:
try:
curve = getattr(self, name)
except AttributeError:
continue
if not isinstance(curve, Curve):
continue
self._curves += [curve]
@property
def display_name(self):
return self.__class__.__name__.lower()
def export(self, rrdfile, start, end):
"""
"""
result = []
cmdargs = []
for curve in self._curves:
result += [{
"name": curve.legend, "color": curve.color, "data": []
}]
cmdargs += curve.to_rrd_command_args(rrdfile)
cmd = "rrdtool xport --start %s --end %s " % (str(start), str(end))
cmd += " ".join(cmdargs)
if isinstance(cmd, unicode):
cmd = cmd.encode("utf-8")
code, output = exec_cmd(cmd)
if code:
return []
tree = etree.fromstring(output)
for row in tree.xpath('/xport/data/row'):
timestamp = int(row.find('t').text)
for vindex, value in enumerate(row.findall('v')):
if value.text == 'NaN':
result[vindex]['data'].append({'x': timestamp, 'y': 0})
else:
result[vindex]['data'].append(
{'x': timestamp, 'y': float(value.text)}
)
return result
class AverageTraffic(Graphic):
"""Average traffic.
"""
title = ugettext_lazy('Average traffic (msgs/min)')
# Curve definitions
sent = Curve("sent", "lawngreen", ugettext_lazy("sent messages"))
recv = Curve("recv", "steelblue", ugettext_lazy("received messages"))
bounced = Curve("bounced", "yellow", ugettext_lazy("bounced messages"))
reject = Curve("reject", "tomato", ugettext_lazy("rejected messages"))
order = ['reject', 'bounced', 'recv', 'sent']
class AverageTrafficSize(Graphic):
"""Average traffic size.
"""
title = ugettext_lazy('Average normal traffic size (bytes/min)')
# Curve definitions
size_recv = Curve("size_recv", "orange", ugettext_lazy("received size"))
size_sent = Curve(
"size_sent", "mediumturquoise", ugettext_lazy("sent size")
)
class GraphicSet(object):
title = None
_graphics = []
def __init__(self):
self.__ginstances = []
@property
def html_id(self):
return self.__class__.__name__.lower()
@property
def graphics(self):
if not self.__ginstances:
self.__ginstances = [graphic() for graphic in self._graphics]
return self.__ginstances
def get_graphic_names(self):
return [graphic.display_name for graphic in self._graphics]
def export(self, rrdfile, start, end):
result = {}
for graph in self.graphics:
result[graph.display_name] = {
"title": graph.title.encode("utf-8"),
"curves": graph.export(rrdfile, start, end)
}
return result
class MailTraffic(GraphicSet):
title = ugettext_lazy('Mail traffic')
_graphics = [AverageTraffic, AverageTrafficSize]