]>
Commit | Line | Data |
---|---|---|
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 |
22 | import os |
23 | ||
29455c5f | 24 | from .. import util |
a031204a | 25 | from . import base |
89b70961 | 26 | |
a031204a | 27 | from ..colours import * |
8988e876 | 28 | from ..constants import * |
89b70961 | 29 | |
2a3d5c1b MT |
30 | class GraphTemplateInterfaceBase(base.GraphTemplate): |
31 | @property | |
32 | def interface(self): | |
33 | return self.object.interface | |
34 | ||
35 | ||
36 | class 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 | 106 | class 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 | 158 | class 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 | 247 | class 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 | ||
300 | class 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) |