2 ###############################################################################
4 # Westferry - The IPFire web user interface #
5 # Copyright (C) 2015 IPFire development team #
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. #
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. #
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/>. #
20 ###############################################################################
23 import collecty
.client
32 class AnalyticsBaseHandler(base
.BaseHandler
):
35 _
= self
.locale
.translate
37 m
= ui
.menu
.Menu(self
, _("Analytics"))
40 m
.add_handler(AnalyticsOverviewHandler
)
44 m
.add_handler(AnalyticsNetworkOverviewHandler
)
47 m
.add_handler(AnalyticsSystemOverviewHandler
)
51 def render_graphs(self
, graphs
):
52 self
.render("graphs.html", graphs
=graphs
)
55 class AnalyticsOverviewHandler(AnalyticsBaseHandler
):
57 title
= N_("Overview")
60 self
.render("base.html")
63 class AnalyticsNetworkBaseHandler(AnalyticsBaseHandler
):
66 _
= self
.locale
.translate
68 m
= ui
.menu
.Menu(self
, _("Network"))
71 m
.add_handler(AnalyticsOverviewHandler
, title
=_("Back..."))
75 m
.add_handler(AnalyticsNetworkOverviewHandler
, title
=_("Overview"))
79 m
.add_handler(AnalyticsNetworkConnectionsOverviewHandler
)
82 m
.add_handler(AnalyticsNetworkIPFragmentationHandler
)
87 class AnalyticsNetworkOverviewHandler(AnalyticsNetworkBaseHandler
):
88 url
= r
"/analytics/network"
92 self
.render("base.html")
95 class AnalyticsNetworkConnectionsBaseHandler(AnalyticsBaseHandler
):
98 _
= self
.locale
.translate
100 m
= ui
.menu
.Menu(self
, _("Connections"))
103 m
.add_handler(AnalyticsNetworkOverviewHandler
, title
=_("Back..."))
107 m
.add_handler(AnalyticsNetworkConnectionsOverviewHandler
, title
=_("Overview"))
111 s
= m
.add_submenu(_("Procotol States"))
112 s
.add_handler(AnalyticsNetworkConnectionsStatesTCPHandler
)
113 s
.add_handler(AnalyticsNetworkConnectionsStatesSCTPHandler
)
114 s
.add_handler(AnalyticsNetworkConnectionsStatesDCCPHandler
)
119 class AnalyticsNetworkConnectionsOverviewHandler(AnalyticsNetworkConnectionsBaseHandler
):
120 url
= r
"/analytics/network/connections"
121 title
= N_("Connections")
124 _
= self
.locale
.translate
127 ui
.graphs
.Graph(self
, "conntrack-layer3-protocols"),
128 ui
.graphs
.Graph(self
, "conntrack-layer4-protocols"),
131 self
.render_graphs(graphs
)
134 class AnalyticsNetworkConnectionsStatesTCPHandler(AnalyticsNetworkConnectionsBaseHandler
):
135 url
= r
"/analytics/network/connections/states/tcp"
139 _
= self
.locale
.translate
142 ui
.graphs
.Graph(self
, "conntrack-protocol-states", "tcp"),
145 self
.render_graphs(graphs
)
148 class AnalyticsNetworkConnectionsStatesSCTPHandler(AnalyticsNetworkConnectionsBaseHandler
):
149 url
= r
"/analytics/network/connections/states/sctp"
153 _
= self
.locale
.translate
156 ui
.graphs
.Graph(self
, "conntrack-protocol-states", "sctp"),
159 self
.render_graphs(graphs
)
162 class AnalyticsNetworkConnectionsStatesDCCPHandler(AnalyticsNetworkConnectionsBaseHandler
):
163 url
= r
"/analytics/network/connections/states/dccp"
167 _
= self
.locale
.translate
170 ui
.graphs
.Graph(self
, "conntrack-protocol-states", "dccp"),
173 self
.render_graphs(graphs
)
176 class AnalyticsNetworkIPFragmentationHandler(AnalyticsNetworkBaseHandler
):
177 url
= r
"/analytics/network/fragmentation"
178 title
= N_("Fragmentation")
181 _
= self
.locale
.translate
184 ui
.graphs
.Graph(self
, "ipv6-fragmentation"),
185 ui
.graphs
.Graph(self
, "ipv4-fragmentation"),
188 self
.render_graphs(graphs
)
191 class AnalyticsSystemBaseHandler(AnalyticsBaseHandler
):
194 _
= self
.locale
.translate
196 m
= ui
.menu
.Menu(self
, _("System"))
199 m
.add_handler(AnalyticsOverviewHandler
, title
=_("Back..."))
203 m
.add_handler(AnalyticsSystemOverviewHandler
, title
=_("Overview"))
206 # Most interesting items
207 m
.add_handler(AnalyticsSystemProcessorsHandler
)
208 m
.add_handler(AnalyticsSystemMemoryHandler
)
209 m
.add_handler(AnalyticsSystemTemperaturesHandler
)
212 s
= m
.add_submenu(_("More"))
213 s
.add_handler(AnalyticsSystemEntropyHandler
)
214 s
.add_handler(AnalyticsSystemContextSwitchesHandler
)
215 s
.add_handler(AnalyticsSystemInterruptsHandler
)
220 class AnalyticsSystemOverviewHandler(AnalyticsSystemBaseHandler
):
221 url
= r
"/analytics/system"
225 self
.render("base.html")
228 class AnalyticsSystemProcessorsHandler(AnalyticsSystemBaseHandler
):
229 url
= r
"/analytics/system/processors"
230 title
= N_("Processors")
233 _
= self
.locale
.translate
236 ui
.graphs
.Graph(self
, "processor"),
237 ui
.graphs
.Graph(self
, "processor-temperature"),
238 ui
.graphs
.Graph(self
, "cpufreq"),
239 ui
.graphs
.Graph(self
, "loadavg"),
242 self
.render_graphs(graphs
)
245 class AnalyticsSystemMemoryHandler(AnalyticsSystemBaseHandler
):
246 url
= r
"/analytics/system/memory"
250 _
= self
.locale
.translate
253 ui
.graphs
.Graph(self
, "memory"),
256 self
.render_graphs(graphs
)
259 class AnalyticsSystemTemperaturesHandler(AnalyticsSystemBaseHandler
):
260 url
= r
"/analytics/system/temperatures"
261 title
= N_("Temperatures")
264 _
= self
.locale
.translate
267 ui
.graphs
.Graph(self
, "sensors-temperature"),
268 ui
.graphs
.Graph(self
, "processor-temperature"),
271 self
.render_graphs(graphs
)
274 class AnalyticsSystemEntropyHandler(AnalyticsSystemBaseHandler
):
275 url
= r
"/analytics/system/entropy"
276 title
= N_("Entropy")
279 _
= self
.locale
.translate
282 ui
.graphs
.Graph(self
, "entropy"),
285 self
.render_graphs(graphs
)
288 class AnalyticsSystemContextSwitchesHandler(AnalyticsSystemBaseHandler
):
289 url
= r
"/analytics/system/context-switches"
290 title
= N_("Context Switches")
293 _
= self
.locale
.translate
296 ui
.graphs
.Graph(self
, "context-switches"),
299 self
.render_graphs(graphs
)
302 class AnalyticsSystemInterruptsHandler(AnalyticsSystemBaseHandler
):
303 url
= r
"/analytics/system/interrupts"
304 title
= N_("Interrupts")
307 _
= self
.locale
.translate
310 ui
.graphs
.Graph(self
, "system-interrupts"),
313 self
.render_graphs(graphs
)
316 class GraphExportHandler(base
.BaseHandler
):
317 VALID_INTERVALS
= ("hour", "day", "month", "week", "year")
318 DEFAULT_INTERVAL
= "day"
320 SUPPORTED_FORMATS
= ("pdf", "png", "svg")
322 url
= r
"/graph/([\w\-]+)(?:/([\w\d\.]+))?\.(%s)" % "|".join(SUPPORTED_FORMATS
)
324 def get(self
, template_name
, object_id
, format
):
325 # Get the requested dimensions of the image
326 height
= self
.get_argument_int("height", None)
327 width
= self
.get_argument_int("width", None)
329 # Get the requested interval
330 interval
= self
.get_argument("interval", self
.DEFAULT_INTERVAL
)
331 if interval
and not interval
in self
.VALID_INTERVALS
:
332 raise tornado
.web
.HTTPError(400, _("Invalid interval: %s") % interval
)
334 # Create the graph object
335 g
= ui
.graphs
.Graph(self
, template_name
, object_id
=object_id
)
337 # Generate the graph image
339 "format" : format
.upper(),
340 "interval" : interval
,
344 # Include the title in the PDF exports
345 "with_title" : format
== "pdf",
347 image
= g
.generate_graph(**kwargs
)
349 # Set the HTTP headers
350 self
._make
_headers
(format
, template_name
, object_id
)
352 # Deliver the content
353 self
.finish(image
.get("image"))
355 def _make_headers(self
, extension
, template_name
, object_id
):
356 # Determine the mime type
357 mimetype
= mimetypes
.types_map
.get(".%s" % extension
, "application/octet-stream")
358 self
.set_header("Content-Type", mimetype
)
360 # Add the timestamp when this graph was generated
361 now
= datetime
.datetime
.now()
363 # Put together the filename (for downloads)
364 filename
= [self
.backend
.system
.hostname
, template_name
, object_id
, now
.isoformat()]
365 filename
= "%s.%s" % ("-".join((e
for e
in filename
if e
)), extension
)
367 if extension
== "pdf":
368 self
.set_header("Content-Disposition", "attachment; filename=%s" % filename
)
370 self
.set_header("Content-Disposition", "inline; filename=%s" % filename
)
373 class GraphHandler(base
.BaseHandler
):
374 url
= r
"/graph/([\w\-]+)(?:/([\w\d\.]+))?"
376 def get(self
, template
, object_id
):
377 graph
= ui
.graphs
.Graph(self
, template
, object_id
=object_id
)
379 self
.render("graph.html", graph
=graph
)