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