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

Source Code for Module 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 save(self, path, value, rrdType, rrdCommand=None, cycleTime=None, 111 min='U', max='U'):
112 """ 113 Save the value provided in the command to the RRD file specified in path. 114 115 If the RRD file does not exist, use the rrdType, rrdCommand, min and 116 max parameters to create the file. 117 118 @param path: name for a datapoint in a path (eg device/component/datasource_datapoint) 119 @type path: string 120 @param value: value to store into the RRD file 121 @type value: number 122 @param rrdType: RRD data type (eg ABSOLUTE, DERIVE, COUNTER) 123 @type rrdType: string 124 @param rrdCommand: RRD file creation command 125 @type rrdCommand: string 126 @param cycleTime: length of a cycle 127 @type cycleTime: number 128 @param min: minimum value acceptable for this metric 129 @type min: number 130 @param max: maximum value acceptable for this metric 131 @type max: number 132 @return: the parameter value converted to a number 133 @rtype: number or None 134 """ 135 import rrdtool, os 136 137 if value is None: return None 138 139 self.dataPoints += 1 140 self.cycleDataPoints += 1 141 142 if cycleTime is None: 143 cycleTime = self.defaultCycleTime 144 145 filename = self.performancePath(path) + '.rrd' 146 if not rrdCommand: 147 rrdCommand = self.defaultRrdCreateCommand 148 if not os.path.exists(filename): 149 log.debug("Creating new RRD file %s", filename) 150 dirname = os.path.dirname(filename) 151 if not os.path.exists(dirname): 152 os.makedirs(dirname, 0750) 153 154 min, max = map(_checkUndefined, (min, max)) 155 dataSource = 'DS:%s:%s:%d:%s:%s' % ('ds0', rrdType, 156 3*cycleTime, min, max) 157 rrdtool.create(filename, 158 "--step", str(cycleTime), 159 str(dataSource), *rrdCommand.split()) 160 161 if rrdType in ('COUNTER', 'DERIVE'): 162 try: 163 value = long(value) 164 except (TypeError, ValueError): 165 return None 166 else: 167 value = float(value) 168 try: 169 rrdtool.update(filename, 'N:%s' % value) 170 log.debug('%s: %r', filename, value) 171 except rrdtool.error, err: 172 # may get update errors when updating too quickly 173 log.error('rrdtool reported error %s %s', err, path) 174 175 if rrdType in ('COUNTER', 'DERIVE'): 176 startStop, names, values = \ 177 rrdtool.fetch(filename, 'AVERAGE', 178 '-s', 'now-%d' % (cycleTime*2), 179 '-e', 'now') 180 values = [ v[0] for v in values if v[0] is not None ] 181 if values: value = values[-1] 182 else: value = None 183 return value
184