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

Source Code for Module Products.ZenModel.RRDGraph

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  __doc__="""RRDGraph 
 12   
 13  RRDGraph defines the global options for an rrdtool graph. 
 14  """ 
 15   
 16  ########################################################################### 
 17  # 
 18  # RRDGraph is deprecated.  GraphDefinition is now used in its place. 
 19  # RRDGraph.py can be removed from zenoss post 2.1 
 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   
35 -def manage_addRRDGraph(context, id, REQUEST = None):
36 """make a RRDGraph""" 37 graph = RRDGraph(id) 38 context._setObject(graph.id, graph) 39 if REQUEST is not None: 40 REQUEST['RESPONSE'].redirect(context.absolute_url()+'/manage_main')
41 42 43 addRRDGraph = DTMLFile('dtml/addRRDGraph',globals()) 44 45
46 -class RRDGraph(ZenModelRM):
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 # Screen action bindings (and tab definitions) 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
114 - def breadCrumbs(self, terminator='dmd'):
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
123 - def getGraphCmds(self, context, rrdfile, template):
124 """build the graph opts for a single rrdfile""" 125 cmds = self.graphsetup() 126 if self.custom: 127 cmds = self.buildCustomDS(cmds, rrdfile, template) 128 res = talesEval("string:"+self.custom, context) 129 cmds.extend(res.split("\n")) 130 if self.hasSummary: 131 cmds = self.addSummary(cmds) 132 else: 133 cmds = self.buildDS(cmds, rrdfile, template, self.summary) 134 cmds = self.thresholds(cmds, context, template) 135 return cmds
136 137
138 - def graphsetup(self):
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
166 - def buildCustomDS(self, gopts, rrdfile, template):
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
190 - def thresholds(self, gopts, context, template):
191 """Add the hrule commands for any thresholds in this graph. 192 """ 193 self._v_threshidx = len(self.colors) 194 threshs = [] 195 for thresh in template.thresholds(): 196 if not thresh.canGraph(self): continue 197 for dsname in thresh.dsnames: 198 if dsname in self.dsnames: 199 threshs.append(thresh) 200 break 201 if threshs: gopts.append("COMMENT:Data Thresholds\j") 202 for i, thresh in enumerate(threshs): 203 t = thresh.createThresholdInstance(context) 204 color = self.getthreshcolor() 205 gopts = t.getGraphElements(template, context, gopts, 'thresh%d' % 206 i, color) 207 import logging 208 log = logging.getLogger("debug") 209 log.error('%r' % gopts) 210 return gopts
211 212 213 gelement = re.compile("^LINE|^AREA|^STACK", re.I).search
214 - def addSummary(self, gopts):
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 #if pad: label = label.ljust(pad) 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
248 - def getthreshcolor(self):
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
255 - def gettype(self, idx):
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