1
2
3
4
5
6
7
8
9
10
11 __doc__="""RRDGraph
12
13 RRDGraph defines the global options for an rrdtool graph.
14 """
15
16
17
18
19
20
21
22
23 import os
24 import re
25
26 from Globals import DTMLFile
27 from Globals import InitializeClass
28 from AccessControl import ClassSecurityInfo, Permissions
29
30 from Products.ZenRelations.RelSchema import *
31 from Products.ZenUtils.ZenTales import talesEval
32
33 from ZenModelRM import ZenModelRM
34
41
42
43 addRRDGraph = DTMLFile('dtml/addRRDGraph',globals())
44
45
47
48 meta_type = 'RRDGraph'
49
50 security = ClassSecurityInfo()
51
52 dsnames = []
53 sequence = 0
54 height = 100
55 width = 500
56 threshmap = []
57 units = ""
58 log = False
59 linewidth = 1
60 base = False
61 stacked = False
62 summary = True
63 miny = -1
64 maxy = -1
65 custom = ""
66 hasSummary = True
67
68
69 _properties = (
70 {'id':'dsnames', 'type':'lines', 'mode':'w'},
71 {'id':'sequence', 'type':'int', 'mode':'w'},
72 {'id':'height', 'type':'int', 'mode':'w'},
73 {'id':'width', 'type':'int', 'mode':'w'},
74 {'id':'units', 'type':'string', 'mode':'w'},
75 {'id':'linewidth', 'type':'int', 'mode':'w'},
76 {'id':'log', 'type':'boolean', 'mode':'w'},
77 {'id':'base', 'type':'boolean', 'mode':'w'},
78 {'id':'stacked', 'type':'boolean', 'mode':'w'},
79 {'id':'summary', 'type':'boolean', 'mode':'w'},
80 {'id':'miny', 'type':'int', 'mode':'w'},
81 {'id':'maxy', 'type':'int', 'mode':'w'},
82 {'id':'colors', 'type':'lines', 'mode':'w'},
83 {'id':'custom', 'type':'text', 'mode':'w'},
84 {'id':'hasSummary', 'type':'boolean', 'mode':'w'},
85 )
86
87 _relations = (
88 ("rrdTemplate", ToOne(ToManyCont,"Products.ZenModel.RRDTemplate", "graphs")),
89 )
90
91 colors = (
92 '#00cc00', '#0000ff', '#00ffff', '#ff0000',
93 '#ff9900', '#cc0000', '#0000cc', '#0080c0',
94 '#8080c0', '#ff0080', '#800080', '#0000a0',
95 '#408080', '#808000', '#000000', '#00ff00',
96 '#fb31fb', '#0080ff', '#ff8000', '#800000',
97 )
98
99
100 factory_type_information = (
101 {
102 'immediate_view' : 'editRRDGraph',
103 'actions' :
104 (
105 { 'id' : 'edit'
106 , 'name' : 'Graph'
107 , 'action' : 'editRRDGraph'
108 , 'permissions' : ( Permissions.view, )
109 },
110 )
111 },
112 )
113
115 """Return the breadcrumb links for this object add ActionRules list.
116 [('url','id'), ...]
117 """
118 from RRDTemplate import crumbspath
119 crumbs = super(RRDGraph, self).breadCrumbs(terminator)
120 return crumbspath(self.rrdTemplate(), crumbs, -2)
121
122
136
137
139 """Setup global graph parameters.
140 """
141 gopts = ['-F', '-E']
142 if self.height:
143 gopts.append('--height=%d' % self.height)
144 if self.width:
145 gopts.append('--width=%d' % self.width)
146 if self.log:
147 gopts.append('--logarithmic')
148 if self.maxy > -1:
149 gopts.append('--upper-limit=%d' % self.maxy)
150 gopts.append('--rigid')
151 if self.miny > -1:
152 gopts.append('--lower-limit=%d' % self.miny)
153 gopts.append('--rigid')
154 if self.units:
155 gopts.append('--vertical-label=%s' % self.units)
156 if self.units == 'percentage':
157 if not self.maxy > -1:
158 gopts.append('--upper-limit=100')
159 if not self.miny > -1:
160 gopts.append('--lower-limit=0')
161 if self.base:
162 gopts.append('--base=1024')
163 return gopts
164
165
167 """Build a list of DEF statements for the dsnames in this graph.
168 Their variable name will be dsname. These can then be used in a
169 custom statement.
170 """
171 for dsname in self.dsnames:
172 dp = template.getRRDDataPoint(dsname)
173 if dp is None: continue
174 myfile = os.path.join(rrdfile, dp.name()) + ".rrd"
175 gopts.append('DEF:%s=%s:ds0:AVERAGE' % (dp.name(), myfile))
176 return gopts
177
178
179 - def buildDS(self, gopts, rrdfile, template, summary,multiid=-1):
180 """Add commands to draw data sources in this graph.
181 """
182 for dsindex, dsname in enumerate(self.dsnames):
183 dp = template.getRRDDataPoint(dsname)
184 dp.setIndex(dsindex)
185 defcolor = self.colors[dsindex]
186 deftype = self.gettype(dsindex)
187 gopts += dp.graphOpts(rrdfile, defcolor, deftype, summary, multiid)
188 return gopts
189
211
212
213 gelement = re.compile("^LINE|^AREA|^STACK", re.I).search
215 """Add summary labels for all graphed elements in gopts.
216 """
217 vars = [o.split(":",2)[1].split("#")[0] for o in gopts if self.gelement(o)]
218
219 pad = max([len(v) for v in vars] + [0])
220 for var in vars:
221 gopts = self.dataSourceSum(gopts, var, pad=pad)
222 return gopts
223
224
225 - def dataSourceSum(self, gopts, src, pad=0, format="%0.2lf%s", ongraph=1):
226 """Add the standard summary opts to a graph for variable src.
227 VDEF:src_last=src,LAST
228 GPRINT:src_last:cur\:%0.2lf%s
229 VDEF:src_avg=src,AVERAGE
230 GPRINT:src_avg:avg\:%0.2lf%s
231 VDEF:src_max=src,MAXIMUM
232 GPRINT:src_max:max\:%0.2lf%s\j
233 """
234 from Products.ZenUtils.Utils import unused
235 unused(pad)
236 funcs = (("cur\:", "LAST"), ("avg\:", "AVERAGE"), ("max\:", "MAXIMUM"))
237 for tag, func in funcs:
238 label = "%s%s" % (tag, format)
239
240 vdef = "%s_%s" % (src,func.lower())
241 gopts.append("VDEF:%s=%s,%s" % (vdef,src,func))
242 opt = ongraph and "GPRINT" or "PRINT"
243 gopts.append("%s:%s:%s" % (opt, vdef, label))
244 gopts[-1] += "\j"
245 return gopts
246
247
249 """get a threshold color by working backwards down the color list"""
250 self._v_threshidx -= 1
251 a= self.colors[self._v_threshidx]
252 return a
253
254
256 """Return the default graph type for a data source
257 first is area rest are lines
258 """
259 if idx == 0:
260 return "AREA"
261 elif self.stacked:
262 return "STACK"
263 else:
264 return "LINE%d" % self.linewidth
265
266 InitializeClass(RRDGraph)
267