--- a/rrdweb/graph.py Tue Jan 25 01:19:40 2011 +0200
+++ b/rrdweb/graph.py Tue Jan 25 01:28:06 2011 +0200
@@ -42,21 +42,21 @@
def overview_opts () :
"""
- Common options for the overview graph
+ Graph statements for a single-source overview graph
"""
return dict(
width = 600,
height = 50,
), [
- "CDEF:all=in,out,+",
+ "CDEF:all=in0,out0,+",
"VDEF:max=all,MAXIMUM",
"VDEF:avg=all,AVERAGE",
"VDEF:min=all,MINIMUM",
- "LINE1:in#0000FF:In",
- "LINE1:out#00CC00:Out",
+ "LINE1:in0#0000FF:In",
+ "LINE1:out0#00CC00:Out",
"GPRINT:max:%6.2lf %Sbps max",
"GPRINT:avg:%6.2lf %Sbps avg",
@@ -65,7 +65,7 @@
def detail_opts () :
"""
- Common options for the detail graph
+ Common options for a single-source detail graph
"""
return dict(
@@ -74,14 +74,14 @@
height = 200,
), [
# values
- 'VDEF:in_max=in,MAXIMUM',
- 'VDEF:in_avg=in,AVERAGE',
- 'VDEF:in_min=in,MINIMUM',
- 'VDEF:in_cur=in,LAST',
- 'VDEF:out_max=out,MAXIMUM',
- 'VDEF:out_avg=out,AVERAGE',
- 'VDEF:out_min=out,MINIMUM',
- 'VDEF:out_cur=out,LAST',
+ 'VDEF:in_max=in0,MAXIMUM',
+ 'VDEF:in_avg=in0,AVERAGE',
+ 'VDEF:in_min=in0,MINIMUM',
+ 'VDEF:in_cur=in0,LAST',
+ 'VDEF:out_max=out0,MAXIMUM',
+ 'VDEF:out_avg=out0,AVERAGE',
+ 'VDEF:out_min=out0,MINIMUM',
+ 'VDEF:out_cur=out0,LAST',
# legend/graph
"COMMENT:%4s" % "",
@@ -90,13 +90,13 @@
"COMMENT:%11s" % "Minimum",
"COMMENT:%11s\\l" % "Current",
- "LINE1:in#0000FF:%4s" % "In",
+ "LINE1:in0#0000FF:%4s" % "In",
'GPRINT:in_max:%6.2lf %Sbps',
'GPRINT:in_avg:%6.2lf %Sbps',
'GPRINT:in_min:%6.2lf %Sbps',
'GPRINT:in_cur:%6.2lf %Sbps\\l',
- "LINE1:out#00CC00:%4s" % "Out",
+ "LINE1:out0#00CC00:%4s" % "Out",
'GPRINT:out_max:%6.2lf %Sbps',
'GPRINT:out_avg:%6.2lf %Sbps',
'GPRINT:out_min:%6.2lf %Sbps',
@@ -106,11 +106,84 @@
"COMMENT:Generated %s\\r" % timestamp().replace(':', '\\:'),
]
+# set of line colors used for a multi-source graph, in rgb hex form (no prefix)
+MULTI_COLORS = (
+ '00cc00',
+ '0000ff',
+ 'cc0000',
+)
+
+def multi_graph_source_defs (idx, name, color) :
+ """
+ Render graph and legend summary for a single source in a multi-source graph.
+ """
+
+ params = dict(
+ idx = idx, name = name, color = color
+ )
+
+ return [stmt.format(**params) for stmt in (
+ "CDEF:all{idx}=in{idx},out{idx},+",
+
+ "VDEF:max{idx}=all{idx},MAXIMUM",
+ "VDEF:avg{idx}=all{idx},AVERAGE",
+ "VDEF:cur{idx}=all{idx},LAST",
+
+ "LINE1:all{idx}#{color}: ",
+
+ "GPRINT:max{idx}:%6.2lf %Sbps",
+ "GPRINT:avg{idx}:%6.2lf %Sbps",
+ "GPRINT:cur{idx}:%6.2lf %Sbps",
+ "COMMENT:\t{name}\\l",
+ )]
+
+
+def multi_graph (sources) :
+ """
+ Graph definition for a multi-source overview graph.
+
+ Uses combined in/out totals, giving a single line per source.
+ """
+
+ # defs for each source
+ sources_defs = [multi_graph_source_defs(idx, name, color) for (idx, name), color in zip(sources, MULTI_COLORS)]
+
+ return dict(
+ # dimensions
+ width = 600,
+ height = 200,
+
+ ), [
+ # legend header
+ "COMMENT: ",
+ "COMMENT:%11s" % "Maximum",
+ "COMMENT:%11s" % "Average",
+ "COMMENT:%11s" % "Current",
+ "COMMENT:\t%s\\l" % "",
+
+ ] + [
+ # each source
+ stmt for defs in sources_defs for stmt in defs
+ ]
+
STYLE_DEFS = {
'overview': overview_opts,
'detail': detail_opts,
}
+def hourly_opts (title) :
+
+ return dict(
+ # labels
+ x_grid = None,
+
+ # general info
+ title = "Hourly %s" % (title, ),
+
+ # interval
+ start = "-1h",
+ )
+
def daily_opts (title) :
"""
Common options for the 'daily' view
@@ -153,52 +226,99 @@
INTERVAL_DEFS = {
+ 'hourly': hourly_opts,
'daily': daily_opts,
'weekly': weekly_opts,
'yearly': yearly_opts,
}
-def mrtg_data (rrd_path) :
+def data_defs (idx, rrd, ds_in, ds_out, bytes=True, cf='AVERAGE') :
"""
- Data sources for network in/out from an MRTG rrd
+ Generate the DEF/CDEF statements for the in{idx}/out{idx} data sources for the given RRD and DS names.
+
+ If bytes is given, convert the value into bits.
"""
- return [
+ params = dict(
+ ds_in=ds_in, ds_out=ds_out, cf=cf,
+ idx=idx, rrd=rrd,
+ )
+
+ if bytes :
# data sources, bytes/s
- r'DEF:in0=%s:ds0:AVERAGE' % rrd_path,
- r'DEF:out0=%s:ds1:AVERAGE' % rrd_path,
-
+ yield 'DEF:in_raw{idx}={rrd}:{ds_in}:{cf}'.format(**params)
+ yield 'DEF:out_raw{idx}={rrd}:{ds_out}:{cf}'.format(**params)
+
# data, bits/s
- 'CDEF:in=in0,8,*',
- 'CDEF:out=out0,8,*',
+ yield 'CDEF:in{idx}=in_raw{idx},8,*'.format(**params)
+ yield 'CDEF:out{idx}=out_raw{idx},8,*'.format(**params)
+
+ else :
+ # data sources, bits/s
+ yield 'DEF:in{idx}={rrd}:{ds_in}:{cf}'.format(**params)
+ yield 'DEF:out{idx}={rrd}:{ds_out}:{cf}'.format(**params)
- ]
-def collectd_data (rrd_path) :
+def mrtg_data (idx, rrd) :
+ """
+ Generate the in{idx}/out{idx} data sources fro the given MRTG rrd.
+ """
+
+ return data_defs(idx, rrd, 'ds0', 'ds1')
+
+def collectd_data (idx, rrd) :
"""
Data sources for if_octets from a collectd rrd
"""
-
- return [
- # data sources, bytes/s
- r'DEF:in0=%s:rx:AVERAGE' % rrd_path,
- r'DEF:out0=%s:tx:AVERAGE' % rrd_path,
+
+ return data_defs(idx, rrd, 'rx', 'tx')
- # data, bits/s
- 'CDEF:in=in0,8,*',
- 'CDEF:out=out0,8,*',
+def pmacct_data (idx, rrd) :
+ """
+ Data sources for in/out bytes from a pmacct rrd
+ """
+
+ return data_defs(idx, rrd, 'in', 'out')
- ]
-
-def _graph (style, interval, title, data_func, rrd_path, out_path) :
+def graph_single (style, interval, title, data_func, rrd_path, out_path) :
+ """
+ Render graph.
+
+ Returns a (width, height, print_lines, graph_file) tuple.
+ """
+
style_opts, style_vars = STYLE_DEFS[style]()
interval_opts = INTERVAL_DEFS[interval](title)
opts = rrd.merge_opts(common_opts(), style_opts, interval_opts)
- data = data_func(rrd_path) + style_vars
+ data = list(data_func(0, rrd_path)) + style_vars
return rrd.graph(out_path, *data, **opts)
+def graph_multi (interval, title, rrd_list, data_func, out) :
+ """
+ Render a multi-source graph.
+
+ interval - the name of the time interval to use
+ title - graph title
+ rrd_list - sequence of (rrd, name) tuples for each source to draw
+ data_func - the data source definition to use
+ out - output path for graph
+ """
+
+ # data sources
+ data_defs = [stmt for idx, (path, name) in enumerate(rrd_list) for stmt in data_func(idx, path)]
+
+ # options
+ graph_opts, graph_defs = multi_graph([(idx, name) for idx, (path, name) in enumerate(rrd_list)])
+ interval_opts = INTERVAL_DEFS[interval](title)
+
+ # combine
+ opts = rrd.merge_opts(common_opts(), graph_opts, interval_opts)
+ defs = data_defs + graph_defs
+
+ # graph
+ return rrd.graph(out, *defs, **opts)
def mrtg (style, interval, title, rrd_path, out_path) :
return _graph(style, interval, title, mrtg_data, rrd_path, out_path)
@@ -206,3 +326,7 @@
def collectd_ifoctets (style, interval, title, rrd_path, out_path) :
return _graph(style, interval, title, collectd_data, rrd_path, out_path)
+def pmacct_bytes (style, interval, title, rrd_path, out_path) :
+ return _graph(style, interval, title, pmacct_data, rrd_path, out_path)
+
+