2 # -*- coding: utf-8 -*-
4 # Server monitoring system
6 # Copyright © 2011 Rodrigo Eduardo Lazo Paz
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 """Http/html Exporter module.
25 Based on CherryPy framework, this module exposes the collected data
26 through HTTP. Data is formatted in html, which is generated based on a
27 very simple template system, based on Python's `string.Template`
28 functionality. Refer to each method of `MonitorHttpHandler` decorated
29 with `@cherry.expose` for the name of the template file used an the
30 list of variables available.
32 The intended entry point for this module is the `main` function, which
33 instantiates and configures the HTTP server. For further details,
34 refer to its docstring.
37 __author__
= "rlazo.paz@gmail.com (Rodrigo Lazo)"
40 from datetime
import datetime
43 from cherrypy
.lib
.static
import serve_fileobj
44 from jinja2
import Environment
, PackageLoader
46 from datastore
import DataStore
, DataEntry
, DataPoint
# pylint: disable=W0611
47 from datetime
import datetime
48 from extra
import plotting
50 def timestampformat(value
, format_str
='%H:%M:%S'):
51 return datetime
.fromtimestamp(value
).strftime(format_str
)
53 # TODO: (09/19) add support for custom made plots based on GET request
54 # params, providing an on-line plotting tool.
55 # TODO: (09/19) evaluate alternatives to error messages, perhaps 404?
56 # TODO: (09/19) add more variables to the templates
57 class MonitorHttpHandler(object):
58 """Custom HTTP handler class."""
59 def __init__(self
, store
, templates_path
, static_path
):
61 self
._templates
_path
= templates_path
62 self
._static
_path
= static_path
63 self
.env
= Environment(loader
=PackageLoader('monitor', 'www_templates'))
64 self
.env
.filters
["timestampformat"] = timestampformat
68 """Web system root url ('/').
71 Vars: title, timestamp, body.
73 template
= self
.env
.get_template('index.html')
74 references
= self
._get
_default
_references
()
75 references
.update({"title": "Monitoring",
76 "body": "<h1>seee</h1>"})
77 return template
.render(references
)
81 """Displays a list of collected vars.
83 Each item in the list links to a page (`var?name=varname`)
84 which displays more detailed information.
87 Vars: title, timestamp, body.
89 template
= self
.env
.get_template('vars.html')
90 references
= self
._get
_default
_references
()
91 references
.update({"title": "List of monitored vars",
92 "vars" : self
._store
.list_vars()})
93 return template
.render(references
)
97 """Displays a list of monitored hosts.
99 Each item in the list links to a page (`host?name=hostname`)
100 which displays more detailed information.
102 Template: simple.html
103 Vars: title, timestamp, body.
105 template
= self
.env
.get_template('hosts.html')
106 references
= self
._get
_default
_references
()
107 references
.update({"title": "List of monitored vars",
108 "vars" : self
._store
.list_groups()})
109 return template
.render(references
)
113 """Displays information about a single variable.
115 Shows a consolidated plotting of collected data by hosts.
118 - `name`: String, variable to display
120 Template: simple.html
121 Vars: title, timestamp, body.
123 template
= self
.env
.get_template('var.html')
124 references
= self
._get
_default
_references
()
125 references
["title"] = "Historic Values of var: %s" % name
126 data
= self
._store
.get_var(name
)
128 # filename, _ = plotting.new_multigraph(data, name, self._static_path)
129 filename
, _
= plotting
.gnuplot_new_multigraph(data
, name
, self
._static
_path
)
130 references
["filename"] = filename
131 references
["items"] = [{'hostname' : k
, 'value': v
.get_latest()} for k
, v
in data
.iteritems()]
132 return template
.render(references
)
134 def host(self
, name
):
135 """Displays information about a single host.
137 Shows a series of plots displaying each collected variable
141 - `name`: String, host to display.
143 Template: simple.html
144 Vars: title, timestamp, body.
146 template
= self
.env
.get_template('host.html')
147 references
= self
._get
_default
_references
()
148 references
["title"] = "Historic Values of host: %s" % name
149 data
= self
._store
.get_group(name
)
152 for k
, entry
in data
.iteritems():
153 values
= entry
.get_all()
154 tuples
= [x
.as_tuple() for x
in values
]
156 # filename, _ = plotting.new_graph(tuples, k, self._static_path)
157 filename
, _
= plotting
.gnuplot_new_graph(tuples
, k
, self
._static
_path
)
158 items
.append({'file': filename
, 'value': values
[-1]})
159 references
["items"] = items
160 return template
.render(references
)
163 def host(self
, name
):
164 """Displays information about a single host.
166 Shows a series of plots displaying each collected variable
170 - `name`: String, host to display.
172 Template: simple.html
173 Vars: title, timestamp, body.
175 template
= self
.env
.get_template('host.html')
176 references
= self
._get
_default
_references
()
177 references
["title"] = "Historic Values of host: %s" % name
178 references
["data"] = self
._store
.get_group(name
).items()
179 return template
.render(references
)
183 """Returns a snapshot of the state of the database."""
184 filename
= "snapshot-%s.pickle" % \
185 datetime
.strftime(datetime
.now(), "%d%m%y-%H%M")
186 return serve_fileobj(self
._store
.dump_obj(),
187 disposition
="attachment",
188 content_type
="application/octet-stream",
191 def _get_default_references(self
):
192 """Returns a dic with basic references already set.
195 - timestamp (current timestamp).
196 - is_snapshot (if current data store is a snapshot)
198 return {"timestamp": str(datetime
.now()),
199 "is_snapshot": self
._store
.is_snapshot()}
203 def main(store
, port
, templates_path
, static_path
):
204 """HTTP server starter.
206 This is a blocking function.
209 - `store`: DataStore, where to extract the data.
210 - `port`: Integer, server port.
211 - `templates_path`: String, fullpath of the templates directory
212 - `static_path`: String, fullpath of directory for generated static files
214 conf
= {"global": {'server.socket_port': port
},
215 "/static": {'tools.staticdir.on': True,
216 'tools.staticdir.dir': static_path
}}
218 cherrypy
.quickstart(MonitorHttpHandler(store
, templates_path
, static_path
),