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

Source Code for Module Products.ZenModel.ThresholdInstance

  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  import os 
 12   
 13  import Globals 
 14  import rrdtool 
 15  from Products.ZenModel.PerformanceConf import PerformanceConf, performancePath 
 16  from Products.ZenModel.MonitorClass import MonitorClass 
 17  from Products.ZenUtils.Utils import unused, rrd_daemon_args, rrd_daemon_retry 
 18   
 19  from twisted.spread import pb 
 20   
 21  import logging 
 22  log = logging.getLogger('zen.ThresholdInstance') 
 23   
 24  unused(Globals) 
25 26 -class ThresholdContext(pb.Copyable, pb.RemoteCopy):
27 """Remember all the little details about a specific data point 28 within a context. This is useful for error messages and path 29 information in the collectors. It's a copy of the key bits of 30 information from the Model.""" 31
32 - def __init__(self, context):
33 if isinstance(context, MonitorClass): 34 self.deviceName = "{context.id} hub".format(context=context) 35 self.componentName = '' 36 self.deviceUrl = 'zport/dmd/Monitors/Hub/{context.id}/viewHubPerformance'.format(context=context) 37 self.devicePath = 'Monitors/Hub/{context.id}'.format(context=context) 38 if isinstance(context, PerformanceConf): 39 self.deviceName = "{context.id} collector".format(context=context) 40 self.componentName = '' 41 self.deviceUrl = 'zport/dmd/Monitors/Performance/{context.id}/viewDaemonPerformance'.format(context=context) 42 self.devicePath = 'Monitors/Performance/{context.id}'.format(context=context) 43 else: 44 self.deviceName = context.device().id 45 self.componentName = context.id 46 if self.componentName == self.deviceName: 47 self.componentName = '' 48 49 self.rrdPath = context.rrdPath()
50 51
52 - def key(self):
53 "Unique data that refers this context" 54 return self.deviceName, self.componentName
55 56
57 - def fileKey(self, dataPoint):
58 "Unique base filename for this context and given dataPoint" 59 return os.path.join(self.rrdPath, dataPoint)
60 61
62 - def path(self, dataPoint):
63 "The full pathname to RRD file that uses a dataPoint" 64 return performancePath(os.path.join(self.rrdPath, dataPoint)) + '.rrd'
65 66 pb.setUnjellyableForClass(ThresholdContext, ThresholdContext)
67 68 -class ThresholdInstance(pb.Copyable, pb.RemoteCopy):
69 """A ThresholdInstance is a threshold to be evaluated in a 70 collector within a given context.""" 71 72 # count is unknown if None 73 count = None 74
75 - def name(self):
76 "return the name of this threshold (from the ThresholdClass)"
77
78 - def context(self):
79 "Return the ThresholdContext for this ThresholdInstance"
80
81 - def key(self):
82 "Unique data that refers to this object within a collector" 83 return self.name(), self.context().key()
84
85 - def dataPoints(self):
86 "Returns the names of the datapoints used to compute the threshold"
87
88 - def check(self, dataPoints):
89 """The given datapoints have been updated, so re-evaluate. 90 returns events or an empty sequence"""
91
92 - def checkRaw(self, dataPoint, timeOf, value):
93 """A new datapoint has been collected, use the given _raw_ 94 value to re-evalue the threshold. 95 returns a sequence of events. 96 """ 97 unused(timeOf, value) 98 return self.check([dataPoint])
99
100 - def getGraphElements(self, template, context, gopts, namespace, color, 101 legend, relatedGps):
102 """Produce a visual indication on the graph of where the 103 threshold applies.""" 104 unused(template, context, gopts, namespace, color, legend, relatedGps) 105 return []
106 107 108 pb.setUnjellyableForClass(ThresholdInstance, ThresholdInstance)
109 110 -class RRDThresholdInstance(ThresholdInstance):
111
112 - def __init__(self, id, context, dpNames, eventClass, severity):
113 self._context = context 114 self.id = id 115 self.eventClass = eventClass 116 self.severity = severity 117 self.dataPointNames = dpNames 118 self._rrdInfoCache = {}
119
120 - def name(self):
121 "return the name of this threshold (from the ThresholdClass)" 122 return self.id
123
124 - def context(self):
125 "Return an identifying context (device, or device and component)" 126 return self._context
127
128 - def dataPoints(self):
129 "Returns the names of the datapoints used to compute the threshold" 130 return self.dataPointNames
131
132 - def check(self, dataPoints):
133 """The given datapoints have been updated, so re-evaluate. 134 returns events or an empty sequence""" 135 unused(dataPoints) 136 result = [] 137 for dp in self.dataPointNames: 138 cycleTime, rrdType = self._getRRDType(dp) 139 result.extend(self._checkImpl( 140 dp, self._fetchLastValue(dp, cycleTime))) 141 return result
142
143 - def checkRaw(self, dataPoint, timeOf, value):
144 """A new datapoint has been collected, use the given _raw_ 145 value to re-evalue the threshold.""" 146 unused(timeOf) 147 result = [] 148 if value is None: return result 149 try: 150 cycleTime, rrdType = self._getRRDType(dataPoint) 151 except Exception: 152 log.exception('Unable to read RRD file for %s' % dataPoint) 153 return result 154 if rrdType != 'GAUGE' and value is None: 155 value = self._fetchLastValue(dataPoint, cycleTime) 156 result.extend(self._checkImpl(dataPoint, value)) 157 return result
158
159 - def _getRRDType(self, dp):
160 """ 161 get and cache rrd type inforomation 162 """ 163 if dp in self._rrdInfoCache: 164 return self._rrdInfoCache[dp] 165 166 @rrd_daemon_retry 167 def rrdtool_fn(): 168 return rrdtool.info(self.context().path(dp), *rrd_daemon_args())
169 data = rrdtool_fn() 170 171 # handle both old and new style RRD versions 172 try: 173 # old style 1.2.x 174 value = data['step'], data['ds']['ds0']['type'] 175 except KeyError: 176 # new style 1.3.x 177 value = data['step'], data['ds[ds0].type'] 178 self._rrdInfoCache[dp] = value 179 return value
180 181
182 - def _fetchLastValue(self, dp, cycleTime):
183 """ 184 Fetch the most recent value for a data point from the RRD file. 185 """ 186 @rrd_daemon_retry 187 def rrdtool_fn(): 188 return rrdtool.fetch(self.context().path(dp), 189 'AVERAGE', '-s', 'now-%d' % (cycleTime*2), '-e', 'now', 190 *rrd_daemon_args())
191 startStop, names, values = rrdtool_fn() 192 values = [ v[0] for v in values if v[0] is not None ] 193 if values: return values[-1] 194 195
196 - def _checkImpl(self, dataPoint, value):
197 raise NotImplementedError()
198 199 pb.setUnjellyableForClass(RRDThresholdInstance, RRDThresholdInstance) 200