]> git.ipfire.org Git - collecty.git/blame - src/collecty/plugins/interface.py
interfaces: Refactor graphs
[collecty.git] / src / collecty / plugins / interface.py
CommitLineData
f37913e8 1#!/usr/bin/python3
89b70961
MT
2###############################################################################
3# #
4# collecty - A system statistics collection daemon for IPFire #
5# Copyright (C) 2012 IPFire development team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
89b70961
MT
22import os
23
29455c5f 24from .. import util
a031204a 25from . import base
89b70961 26
a031204a 27from ..colours import *
8988e876 28from ..constants import *
89b70961 29
2a3d5c1b
MT
30class GraphTemplateInterfaceBase(base.GraphTemplate):
31 @property
32 def interface(self):
33 return self.object.interface
34
35
36class GraphTemplateInterfaceBits(GraphTemplateInterfaceBase):
bba5cf66
MT
37 name = "interface-bits"
38
39 @property
40 def rrd_graph(self):
c0ebfd25
MT
41 _ = self.locale.translate
42
bba5cf66 43 return [
8988e876
MT
44 # Headline
45 "COMMENT:%s" % EMPTY_LABEL,
46 "COMMENT:%s" % (COLUMN % _("Current")),
47 "COMMENT:%s" % (COLUMN % _("Average")),
48 "COMMENT:%s" % (COLUMN % _("Minimum")),
49 "COMMENT:%s\\j" % (COLUMN % _("Maximum")),
50
bba5cf66
MT
51 # Convert everything into bits.
52 "CDEF:bits_rx=bytes_rx,8,*",
53 "CDEF:bits_tx=bytes_tx,8,*",
54
55 # Compute 95% lines.
56 "VDEF:bits_rx_95p=bits_rx,95,PERCENT",
57 "VDEF:bits_tx_95p=bits_tx,95,PERCENT",
58
59 # Draw the received area.
8988e876
MT
60 "AREA:bits_rx%s:%s" % (
61 transparency(COLOUR_RX, AREA_OPACITY),
62 LABEL % _("Received"),
63 ),
64 "GPRINT:bits_rx_cur:%s" % BPS,
65 "GPRINT:bits_rx_avg:%s" % BPS,
66 "GPRINT:bits_rx_min:%s" % BPS,
67 "GPRINT:bits_rx_max:%s\\j" % BPS,
bba5cf66
MT
68
69 # Draw the transmitted area.
8988e876
MT
70 "AREA:bits_tx%s:%-15s" % (
71 transparency(COLOUR_TX, AREA_OPACITY),
72 LABEL % _("Transmitted"),
73 ),
74 "GPRINT:bits_tx_cur:%s" % BPS,
75 "GPRINT:bits_tx_avg:%s" % BPS,
76 "GPRINT:bits_tx_min:%s" % BPS,
77 "GPRINT:bits_tx_max:%s\\j" % BPS,
bba5cf66
MT
78
79 # Draw outlines.
03ba5630
MT
80 "LINE1:bits_rx%s" % COLOUR_RX,
81 "LINE1:bits_tx%s" % COLOUR_TX,
bba5cf66 82
8988e876
MT
83 EMPTY_LINE,
84
bba5cf66 85 # Draw the 95% lines.
8988e876
MT
86 "COMMENT:%s" % _("95th Percentile"),
87 "LINE:bits_rx_95p%s:%s:dashes" % (COLOUR_RX, LABEL % _("Received")),
88 "GPRINT:bits_rx_95p:%s\\r" % BPS,
89 "LINE:bits_tx_95p%s:%s:dashes" % (COLOUR_TX, LABEL % _("Transmitted")),
90 "GPRINT:bits_tx_95p:%s\\r" % BPS,
bba5cf66
MT
91 ]
92
93 @property
f181246a 94 def graph_title(self):
c0ebfd25 95 _ = self.locale.translate
8988e876
MT
96
97 return _("Bandwidth Usage on %s") % self.interface
f181246a
MT
98
99 @property
100 def graph_vertical_label(self):
c0ebfd25 101 _ = self.locale.translate
8988e876 102
f181246a 103 return _("Bit/s")
e9bb328f
MT
104
105
2a3d5c1b 106class GraphTemplateInterfacePackets(GraphTemplateInterfaceBase):
e9bb328f
MT
107 name = "interface-packets"
108
bba5cf66
MT
109 @property
110 def rrd_graph(self):
c0ebfd25
MT
111 _ = self.locale.translate
112
bba5cf66 113 return [
8988e876
MT
114 # Headline
115 "COMMENT:%s" % EMPTY_LABEL,
116 "COMMENT:%s" % (COLUMN % _("Current")),
117 "COMMENT:%s" % (COLUMN % _("Average")),
118 "COMMENT:%s" % (COLUMN % _("Minimum")),
119 "COMMENT:%s\\j" % (COLUMN % _("Maximum")),
120
bba5cf66 121 # Draw the received area.
8988e876
MT
122 "AREA:packets_rx%s:%s" % (
123 transparency(COLOUR_RX, AREA_OPACITY),
124 LABEL % _("Received"),
03ba5630 125 ),
8988e876
MT
126 "GPRINT:packets_rx_cur:%s" % PPS,
127 "GPRINT:packets_rx_avg:%s" % PPS,
128 "GPRINT:packets_rx_min:%s" % PPS,
129 "GPRINT:packets_rx_max:%s\\j" % PPS,
bba5cf66
MT
130
131 # Draw the transmitted area.
8988e876
MT
132 "AREA:packets_tx%s:%s" % (
133 transparency(COLOUR_TX, AREA_OPACITY),
134 LABEL % _("Transmitted"),
03ba5630 135 ),
8988e876
MT
136 "GPRINT:packets_tx_cur:%s" % PPS,
137 "GPRINT:packets_tx_avg:%s" % PPS,
138 "GPRINT:packets_tx_min:%s" % PPS,
139 "GPRINT:packets_tx_max:%s\\j" % PPS,
bba5cf66
MT
140
141 # Draw outlines of the areas on top.
03ba5630
MT
142 "LINE1:packets_rx%s" % COLOUR_RX,
143 "LINE1:packets_tx%s" % COLOUR_TX,
bba5cf66 144 ]
e9bb328f 145
bba5cf66 146 @property
f181246a 147 def graph_title(self):
c0ebfd25 148 _ = self.locale.translate
8988e876
MT
149
150 return _("Transferred Packets on %s") % self.interface
f181246a
MT
151
152 @property
153 def graph_vertical_label(self):
c0ebfd25 154 _ = self.locale.translate
f181246a 155 return _("Packets/s")
e9bb328f
MT
156
157
2a3d5c1b 158class GraphTemplateInterfaceErrors(GraphTemplateInterfaceBase):
e9bb328f
MT
159 name = "interface-errors"
160
bba5cf66
MT
161 @property
162 def rrd_graph(self):
c0ebfd25
MT
163 _ = self.locale.translate
164
bba5cf66 165 return [
8988e876
MT
166 # Headline
167 "COMMENT:%s" % EMPTY_LABEL,
168 "COMMENT:%s" % (COLUMN % _("Current")),
169 "COMMENT:%s" % (COLUMN % _("Average")),
170 "COMMENT:%s" % (COLUMN % _("Minimum")),
171 "COMMENT:%s\\j" % (COLUMN % _("Maximum")),
172
bba5cf66
MT
173 # Invert the transmitted packets to create upside down graph.
174 "CDEF:errors_tx_inv=errors_tx,-1,*",
175 "CDEF:dropped_tx_inv=dropped_tx,-1,*",
176
177 # Draw the receive errors.
03ba5630 178 "AREA:errors_rx%s:%-15s" % (
8988e876
MT
179 transparency(COLOUR_RX, AREA_OPACITY),
180 LABEL % _("Receive Errors"),
03ba5630 181 ),
8988e876
MT
182 "GPRINT:errors_rx_cur:%s" % PPS,
183 "GPRINT:errors_rx_avg:%s" % PPS,
184 "GPRINT:errors_rx_min:%s" % PPS,
185 "GPRINT:errors_rx_max:%s\\j" % PPS,
03ba5630 186 "LINE1:errors_rx%s" % COLOUR_RX,
bba5cf66
MT
187
188 # Draw the transmit errors.
03ba5630 189 "AREA:errors_tx_inv%s:%-15s" % (
8988e876
MT
190 transparency(COLOUR_TX, AREA_OPACITY),
191 LABEL % _("Transmit Errors"),
03ba5630 192 ),
8988e876
MT
193 "GPRINT:errors_tx_cur:%s" % PPS,
194 "GPRINT:errors_tx_avg:%s" % PPS,
195 "GPRINT:errors_tx_min:%s" % PPS,
196 "GPRINT:errors_tx_max:%s\\j" % PPS,
03ba5630 197 "LINE1:errors_tx_inv%s" % COLOUR_TX,
bba5cf66
MT
198
199 # Draw the receive drops.
03ba5630 200 "LINE2:dropped_rx%s:%-15s" % (
8988e876
MT
201 transparency(AMBER, AREA_OPACITY),
202 LABEL % _("Receive Drops"),
03ba5630 203 ),
8988e876
MT
204 "GPRINT:dropped_rx_cur:%s" % PPS,
205 "GPRINT:dropped_rx_avg:%s" % PPS,
206 "GPRINT:dropped_rx_min:%s" % PPS,
207 "GPRINT:dropped_rx_max:%s\\j" % PPS,
bba5cf66
MT
208 "LINE1:dropped_rx#228B22",
209
210 # Draw the transmit drops.
03ba5630 211 "LINE2:dropped_tx%s:%-15s" % (
8988e876
MT
212 transparency(TEAL, AREA_OPACITY),
213 LABEL % _("Transmit Drops"),
03ba5630 214 ),
8988e876
MT
215 "GPRINT:dropped_tx_cur:%s" % PPS,
216 "GPRINT:dropped_tx_avg:%s" % PPS,
217 "GPRINT:dropped_tx_min:%s" % PPS,
218 "GPRINT:dropped_tx_max:%s\\j" % PPS,
03ba5630 219 "LINE1:dropped_tx%s" % TEAL,
bba5cf66 220
8988e876
MT
221 EMPTY_LINE,
222
bba5cf66 223 # Draw the collisions as a line.
8988e876
MT
224 "LINE2:collisions%s:%s" % (
225 COLOUR_CRITICAL,
226 LABEL % _("Collisions"),
227 ),
228 "GPRINT:collisions_cur:%s" % PPS,
229 "GPRINT:collisions_avg:%s" % PPS,
230 "GPRINT:collisions_min:%s" % PPS,
231 "GPRINT:collisions_max:%s\\j" % PPS,
bba5cf66 232 ]
e9bb328f 233
bba5cf66 234 @property
f181246a 235 def graph_title(self):
c0ebfd25 236 _ = self.locale.translate
8988e876
MT
237
238 return _("Errors/Dropped Packets on %s") % self.interface
f181246a
MT
239
240 @property
241 def graph_vertical_label(self):
c0ebfd25 242 _ = self.locale.translate
8988e876 243
f181246a 244 return _("Packets/s")
e9bb328f
MT
245
246
72364063 247class InterfaceObject(base.Object):
89b70961
MT
248 rrd_schema = [
249 "DS:bytes_rx:DERIVE:0:U",
250 "DS:bytes_tx:DERIVE:0:U",
251 "DS:collisions:DERIVE:0:U",
252 "DS:dropped_rx:DERIVE:0:U",
253 "DS:dropped_tx:DERIVE:0:U",
254 "DS:errors_rx:DERIVE:0:U",
255 "DS:errors_tx:DERIVE:0:U",
256 "DS:multicast:DERIVE:0:U",
257 "DS:packets_rx:DERIVE:0:U",
258 "DS:packets_tx:DERIVE:0:U",
259 ]
260
72364063
MT
261 def __repr__(self):
262 return "<%s %s>" % (self.__class__.__name__, self.interface)
bba5cf66 263
72364063
MT
264 def init(self, interface):
265 self.interface = interface
89b70961
MT
266
267 @property
268 def id(self):
72364063 269 return self.interface
89b70961 270
72364063 271 def collect(self):
29455c5f 272 interface_path = os.path.join("/sys/class/net", self.interface)
bba5cf66
MT
273
274 # Check if the interface exists.
275 if not os.path.exists(interface_path):
276 self.log.debug(_("Interface %s does not exists. Cannot collect.") \
277 % self.interface)
278 return
279
89b70961
MT
280 files = (
281 "rx_bytes", "tx_bytes",
282 "collisions",
283 "rx_dropped", "tx_dropped",
284 "rx_errors", "tx_errors",
285 "multicast",
286 "rx_packets", "tx_packets",
287 )
bba5cf66 288 ret = []
89b70961
MT
289
290 for file in files:
bba5cf66 291 path = os.path.join(interface_path, "statistics", file)
89b70961 292
6f79bea5
MT
293 ret.append(
294 self.read_file_integer(path),
295 )
bba5cf66 296
f648421a 297 return ret
72364063
MT
298
299
300class InterfacePlugin(base.Plugin):
301 name = "interface"
302 description = "Interface Statistics Plugin"
303
304 templates = [
305 GraphTemplateInterfaceBits,
306 GraphTemplateInterfacePackets,
307 GraphTemplateInterfaceErrors,
308 ]
309
b064255e 310 interval = 30
72364063 311
72364063
MT
312 @property
313 def objects(self):
29455c5f 314 for interface in util.get_network_interfaces():
72364063 315 yield InterfaceObject(self, interface=interface)