Package ZenHub :: Package services :: Module RRDImpl
[hide private]
[frames] | no frames]

Source Code for Module ZenHub.services.RRDImpl

  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__ = """RRDImpl 
 15   
 16  Implementation of basic RRD services for zenhub 
 17  """ 
 18   
 19  import os.path 
 20  import logging 
 21  import time 
 22   
 23  from Products.ZenRRD.RRDUtil import RRDUtil 
 24  from Products.ZenEvents.ZenEventClasses import Critical, Status_Perf 
 25   
 26   
 27  log = logging.getLogger("zenhub") 
 28   
 29   
 30   
31 -class RRDImpl:
32 """ 33 RRDUtil wrapper class for zenhub 34 """ 35 36 # list of RRD types that only accept long or integer values (no floats!) 37 LONG_RRD_TYPES = ['COUNTER', 'DERIVE'] 38
39 - def __init__(self, dmd):
40 """ 41 Initializer 42 43 @param dmd: Device Management Database (DMD) reference 44 @type dmd: dmd object 45 """ 46 # RRD is a dictionary of RRDUtil instances 47 self.rrd = {} 48 # counts is a dictionary of integers tracking how many times 49 # each threshold has been exceeded sequentially. 50 self.counts = {} 51 52 self.dmd = dmd 53 self.zem = dmd.ZenEventManager
54 55
56 - def writeRRD(self, devId, compType, compId, dpName, value):
57 """ 58 Write the given data to its RRD file. 59 Also check any thresholds and send events if value is out of bounds. 60 Note that if the write does not succeed, a None value is returned. 61 62 @param devId: device name (as known by DMD) 63 @type devId: string 64 @param compType: component type (found in objects meta_type field) 65 @type compType: string 66 @param compId: name of the component 67 @type compId: string 68 @param dpName: name of the data point 69 @type dpName: string 70 @param value: performance metric to store 71 @type value: number 72 @return: valid value (ie long or float) or None 73 @rtype: number or None 74 """ 75 log.debug('Writing %s %s' % (dpName, value)) 76 dev = self.getDeviceOrComponent(devId, compType, compId) 77 dp = dev.getRRDDataPoint(dpName) 78 if not dp: 79 log.warn('Did not find datapoint %s on device %s', dpName, devId) 80 return None 81 rrdKey = (dev.getPrimaryPath(), dp.getPrimaryPath()) 82 rrdCreateCmd = dp.createCmd or self.getDefaultRRDCreateCommand(dev) 83 if self.rrd.has_key(rrdKey): 84 rrd = self.rrd[rrdKey] 85 else: 86 rrd = RRDUtil(rrdCreateCmd, dp.datasource.cycletime) 87 self.rrd[rrdKey] = rrd 88 89 # convert value to a long if our data point uses a long type 90 if dp.rrdtype in RRDImpl.LONG_RRD_TYPES: 91 try: 92 value = long(value) 93 except ValueError: 94 log.warn("Value '%s' received for data point '%s' that " \ 95 "could not be converted to a long" % \ 96 (value, dp.rrdtype)) 97 98 path = os.path.join(dev.rrdPath(), dp.name()) 99 try: 100 value = rrd.save( path, 101 value, 102 dp.rrdtype, 103 rrdCreateCmd, 104 dp.datasource.cycletime, 105 dp.rrdmin, 106 dp.rrdmax) 107 108 except Exception, ex: 109 summary= "Unable to save data in zenhub for RRD %s" % \ 110 path 111 log.critical( summary ) 112 113 message= "Data was value= %s, type=%s, min=%s, max=%s" % \ 114 ( value, dp.rrdtype, dp.rrdmin, dp.rrdmax, ) 115 log.critical( message ) 116 log.exception( ex ) 117 118 import traceback 119 trace_info= traceback.format_exc() 120 121 evid= self.zem.sendEvent(dict( 122 dedupid="%s|%s" % (devId, 'RRD write failure'), 123 severity=Critical, 124 device=devId, 125 eventClass=Status_Perf, 126 component="RRD", 127 compType=compType, 128 compId=compId, 129 datapoint=dpName, 130 message=message, 131 traceback=trace_info, 132 summary=summary)) 133 134 # Skip thresholds 135 return 136 137 self.checkThresholds(dev, dp, value) 138 return value
139 140
141 - def getDefaultRRDCreateCommand(self, device):
142 """ 143 Get the overridable create command for new RRD files. 144 145 @param device: device object from in DMD 146 @type device: device object 147 @return: RRD create command 148 @rtype: string 149 """ 150 return device.perfServer().getDefaultRRDCreateCommand()
151 152
153 - def getDeviceOrComponent(self, devId, compId, compType):
154 """ 155 If a compId is given then try to return that component. If unable 156 to find it or if compId is not specified then try to return the 157 given device. If unable to find then return None. 158 159 @param devId: device name (as known by DMD) 160 @type devId: string 161 @param compId: name of the component 162 @type compId: string 163 @param compType: component type (found in objects meta_type field) 164 @type compType: string 165 @return: device or component object 166 @rtype: object 167 """ 168 d = None 169 device = self.dmd.Devices.findDevice(devId) 170 if device: 171 if compId: 172 for comp in device.getDeviceComponents(): 173 if comp.meta_type == compType and comp.id == compId: 174 d = comp 175 break 176 else: 177 d = device 178 return d
179 180
181 - def checkThresholds(self, dev, dp, value):
182 """ 183 Check the given value against any thresholds. Count the number of 184 times a dp has exceeded a given threshold in self.counts. Send events 185 as appropriate. 186 187 @param dev: device or component object 188 @type dev: object 189 @param dp: datapoint 190 @type dp: RRD datapoint object 191 @param value: performance metric to compare 192 @type value: number 193 """ 194 if value is None: 195 return 196 197 # Loop through the enabled thresholds on the template containing 198 # this datapoint. 199 for t in [t for t in dp.datasource.rrdTemplate.thresholds() 200 if t.enabled and dp.name() in t.dsnames]: 201 log.debug('Checking %s value of %s against threshold %s: %s:%s' % 202 (dp.name(), value, t.id, t.getMinval(dev), t.getMaxval(dev))) 203 inst = t.createThresholdInstance(dev) 204 # storing the count external to the instances is a little 205 # broken, but I don't want to cache the instances 206 countKey = inst.countKey('dp_ds') 207 inst.count[countKey] = self.counts.get(countKey, None) 208 for evt in inst.checkRaw(dp.name(), time.time(), value): 209 self.zem.sendEvent(evt) 210 self.counts[countKey] = inst.countKey('dp_ds')
211