Package ZenModel :: Module RRDGraph
[hide private]
[frames] | no frames]

Source Code for Module ZenModel.RRDGraph

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  __doc__="""RRDGraph 
 15   
 16  RRDGraph defines the global options for an rrdtool graph. 
 17  """ 
 18   
 19  ########################################################################### 
 20  # 
 21  # RRDGraph is deprecated.  GraphDefinition is now used in its place. 
 22  # RRDGraph.py can be removed from zenoss post 2.1 
 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   
38 -def manage_addRRDGraph(context, id, REQUEST = None):
39 """make a RRDGraph""" 40 graph = RRDGraph(id) 41 context._setObject(graph.id, graph) 42 if REQUEST is not None: 43 REQUEST['RESPONSE'].redirect(context.absolute_url()+'/manage_main')
44 45 46 addRRDGraph = DTMLFile('dtml/addRRDGraph',globals()) 47 48
49 -class RRDGraph(ZenModelRM):
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 # Screen action bindings (and tab definitions) 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
117 - def breadCrumbs(self, terminator='dmd'):
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
126 - def getGraphCmds(self, context, rrdfile, template):
127 """build the graph opts for a single rrdfile""" 128 cmds = self.graphsetup() 129 if self.custom: 130 cmds = self.buildCustomDS(cmds, rrdfile, template) 131 res = talesEval("string:"+self.custom, context) 132 cmds.extend(res.split("\n")) 133 if self.hasSummary: 134 cmds = self.addSummary(cmds) 135 else: 136 cmds = self.buildDS(cmds, rrdfile, template, self.summary) 137 cmds = self.thresholds(cmds, context, template) 138 return cmds
139 140
141 - def graphsetup(self):
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
169 - def buildCustomDS(self, gopts, rrdfile, template):
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
193 - def thresholds(self, gopts, context, template):
194 """Add the hrule commands for any thresholds in this graph. 195 """ 196 self._v_threshidx = len(self.colors) 197 threshs = [] 198 for thresh in template.thresholds(): 199 if not thresh.canGraph(self): continue 200 for dsname in thresh.dsnames: 201 if dsname in self.dsnames: 202 threshs.append(thresh) 203 break 204 if threshs: gopts.append("COMMENT:Data Thresholds\j") 205 for i, thresh in enumerate(threshs): 206 t = thresh.createThresholdInstance(context) 207 color = self.getthreshcolor() 208 gopts = t.getGraphElements(template, context, gopts, 'thresh%d' % 209 i, color) 210 import logging 211 log = logging.getLogger("debug") 212 log.error('%r' % gopts) 213 return gopts
214 215 216 gelement = re.compile("^LINE|^AREA|^STACK", re.I).search
217 - def addSummary(self, gopts):
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 #if pad: label = label.ljust(pad) 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
251 - def getthreshcolor(self):
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
258 - def gettype(self, idx):
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