Package Products :: Package ZenRRD :: Module RRDUtil
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenRRD.RRDUtil

  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__ = """RRDUtil 
 15   
 16  Wrapper routines around the rrdtool library. 
 17  """ 
 18   
 19  import logging 
 20  log = logging.getLogger("zen.RRDUtil") 
 21   
22 -def _checkUndefined(x):
23 """ 24 Sanity check on the min, max values 25 26 @param x: RRD min or max value 27 @type x: number 28 @return: Either the number or 'U' (for undefined) 29 @rtype: number or string 30 """ 31 if x is None or x == '' or x == -1 or x == '-1': 32 return 'U' 33 return x
34 35
36 -def convertToRRDTime(val):
37 """ 38 Convert any value that is passed in to a string that is acceptable to use 39 for RRDtool's start and end parameters. Raises ValueError if this is not 40 possible. 41 42 See the AT-STYLE TIME SPECIFICATION and TIME REFERENCE SPECIFICATION 43 sections of the following document. 44 45 http://oss.oetiker.ch/rrdtool/doc/rrdfetch.en.html 46 47 Note: Currently this method is only fixing floats by turning them into 48 strings with no decimal places. 49 """ 50 # Integers are ok. This will also strip decimal precision. 51 try: 52 result = int(val) 53 return str(result) 54 except ValueError: 55 pass 56 57 return str(val)
58 59
60 -class RRDUtil:
61 """ 62 Wrapper class around rrdtool 63 """ 64
65 - def __init__(self, defaultRrdCreateCommand, defaultCycleTime):
66 """ 67 Initializer 68 69 The RRD creation command is only used if the RRD file doesn't 70 exist and no rrdCommand was specified with the save() method. 71 72 @param defaultRrdCreateCommand: RRD creation command 73 @type defaultRrdCreateCommand: string 74 @param defaultCycleTime: expected time to periodically collect data 75 @type defaultCycleTime: integer 76 """ 77 self.defaultRrdCreateCommand = defaultRrdCreateCommand 78 self.defaultCycleTime = defaultCycleTime 79 self.dataPoints = 0 80 self.cycleDataPoints = 0
81 82
83 - def endCycle(self):
84 """ 85 Report on the number of data points collected in a cycle, 86 and reset the counter for a new cycle. 87 88 @return: number of data points collected during the cycle 89 @rtype: number 90 """ 91 result = self.cycleDataPoints 92 self.cycleDataPoints = 0 93 return result
94 95
96 - def performancePath(self, path):
97 """ 98 Given a path, return its location from $ZENHOME and the 99 perf/ directories. 100 101 @param path: name for a datapoint in a path (eg device/component/datasource_datapoint) 102 @type path: string 103 @return: absolute path 104 @rtype: string 105 """ 106 from Products.ZenModel.PerformanceConf import performancePath 107 return performancePath(path)
108 109
110 - def getStep(self, cycleTime):
111 """ 112 Return the step value for the provided cycleTime. This is a hook for 113 altering the default step calculation. 114 """ 115 return int(cycleTime)
116 117
118 - def getHeartbeat(self, cycleTime):
119 """ 120 Return the heartbeat value for the provided cycleTime. This is a hook 121 for altering the default heartbeat calculation. 122 """ 123 return int(cycleTime) * 3
124 125
126 - def save(self, path, value, rrdType, rrdCommand=None, cycleTime=None, 127 min='U', max='U'):
128 """ 129 Save the value provided in the command to the RRD file specified in path. 130 131 If the RRD file does not exist, use the rrdType, rrdCommand, min and 132 max parameters to create the file. 133 134 @param path: name for a datapoint in a path (eg device/component/datasource_datapoint) 135 @type path: string 136 @param value: value to store into the RRD file 137 @type value: number 138 @param rrdType: RRD data type (eg ABSOLUTE, DERIVE, COUNTER) 139 @type rrdType: string 140 @param rrdCommand: RRD file creation command 141 @type rrdCommand: string 142 @param cycleTime: length of a cycle 143 @type cycleTime: number 144 @param min: minimum value acceptable for this metric 145 @type min: number 146 @param max: maximum value acceptable for this metric 147 @type max: number 148 @return: the parameter value converted to a number 149 @rtype: number or None 150 """ 151 import rrdtool, os 152 153 if value is None: return None 154 155 self.dataPoints += 1 156 self.cycleDataPoints += 1 157 158 if cycleTime is None: 159 cycleTime = self.defaultCycleTime 160 161 filename = self.performancePath(path) + '.rrd' 162 if not rrdCommand: 163 rrdCommand = self.defaultRrdCreateCommand 164 if not os.path.exists(filename): 165 log.debug("Creating new RRD file %s", filename) 166 dirname = os.path.dirname(filename) 167 if not os.path.exists(dirname): 168 os.makedirs(dirname, 0750) 169 170 min, max = map(_checkUndefined, (min, max)) 171 dataSource = 'DS:%s:%s:%d:%s:%s' % ( 172 'ds0', rrdType, self.getHeartbeat(cycleTime), min, max) 173 rrdtool.create(str(filename), "--step", 174 str(self.getStep(cycleTime)), 175 str(dataSource), *rrdCommand.split()) 176 177 if rrdType in ('COUNTER', 'DERIVE'): 178 try: 179 value = long(value) 180 except (TypeError, ValueError): 181 return None 182 else: 183 value = float(value) 184 try: 185 rrdtool.update(str(filename), 'N:%s' % value) 186 log.debug('%s: %r', str(filename), value) 187 except rrdtool.error, err: 188 # may get update errors when updating too quickly 189 log.error('rrdtool reported error %s %s', err, path) 190 191 if rrdType in ('COUNTER', 'DERIVE'): 192 startStop, names, values = \ 193 rrdtool.fetch(filename, 'AVERAGE', 194 '-s', 'now-%d' % (cycleTime*2), 195 '-e', 'now') 196 values = [ v[0] for v in values if v[0] is not None ] 197 if values: value = values[-1] 198 else: value = None 199 return value
200