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

# Source Code for Module Products.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 or (at your
      8  # option) any later version as published by 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