Package flumotion :: Package component :: Package plugs :: Module rrd
[hide private]

Source Code for Module flumotion.component.plugs.rrd

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  import os 
 19   
 20  # FIXME: use a variable like HAS_RRDTOOL like we do in similar code 
 21  try: 
 22      import rrdtool 
 23  except ImportError: 
 24      rrdtool = None 
 25   
 26  from flumotion.component.plugs import base 
 27  from flumotion.common import messages, i18n, log 
 28  from flumotion.common.poller import Poller 
 29   
 30  from flumotion.common.i18n import N_ 
 31  T_ = i18n.gettexter() 
 32   
 33  _DEFAULT_POLL_INTERVAL = 60 # in seconds 
 34  _DEFAULT_STEP_SIZE = 300 # in seconds 
 35   
 36  __version__ = "$Rev: 7162 $" 
 37   
 38   
39 -class ComponentRRDPlug(base.ComponentPlug):
40 """Class to create or update a RRD file with statistics""" 41 42 ### ComponentPlug methods 43
44 - def start(self, component):
45 self._rrdpoller = None 46 47 self._component = component 48 49 if not self._hasImport(): 50 return 51 52 properties = self.args['properties'] 53 self._clientsPath = properties['clients-connected-file'] 54 self._bytesPath = properties['bytes-transferred-file'] 55 self._stepSize = properties.get('step-size', _DEFAULT_STEP_SIZE) 56 self._RRDPaths = self._getRRDPaths() 57 # call to update_rrd with a poll interval 58 timeout = properties.get('poll-interval', _DEFAULT_POLL_INTERVAL) 59 self._rrdpoller = Poller(self._updateRRD, timeout)
60
61 - def stop(self, component):
62 if self._rrdpoller: 63 self._rrdpoller.stop()
64
65 - def _hasImport(self):
66 """Check rrdtool availability""" 67 if not rrdtool: 68 m = messages.Warning(T_(N_( 69 "Cannot import module '%s'.\n"), 'rrdtool'), 70 mid='rrdtool-import-error') 71 m.add(T_(N_( 72 "The RRD plug for this component is disabled."))) 73 self._component.addMessage(m) 74 return False 75 76 return True
77
78 - def _updateRRD(self):
79 """Update data in RRD file""" 80 for path in self._RRDPaths: 81 value = None 82 if path == self._clientsPath: 83 value = self._component.getClients() 84 elif path == self._bytesPath: 85 value = self._component.getBytesSent() 86 87 try: 88 rrdtool.update(path, 'N:%i' % value) 89 self.debug('RRD file [%s] updated with value: %r', 90 path, value) 91 except rrdtool.error, e: 92 # We could get an error from rrdtool on converting the 93 # value to a double or from not finding the file 94 self.warning('RRD error: %r', 95 log.getExceptionMessage(e))
96
97 - def _getRRDPaths(self):
98 """Create the RRD file using the CACTI standard configuration 99 if it doesn't exist""" 100 paths = [] 101 rrds = ( 102 (self._clientsPath, 'clients', 'GAUGE'), 103 (self._bytesPath, 'bytes', 'DERIVE'), 104 ) 105 106 for path, name, counterType in rrds: 107 if not os.path.exists(path): 108 try: 109 DAY = 60 * 60 * 24 110 count = [ 111 8 * DAY // self._stepSize, 112 56 * DAY // (self._stepSize * 6), 113 250 * DAY // (self._stepSize * 24), 114 3000 * DAY // (self._stepSize * 288), 115 ] 116 117 rrdtool.create(path, 118 '-s %d' % self._stepSize, 119 'DS:%s:%s:600:0:U' % (name, counterType), 120 'RRA:AVERAGE:0.5:1:%d' % count[0], 121 'RRA:AVERAGE:0.5:6:%d' % count[1], 122 'RRA:AVERAGE:0.5:24:%d' % count[2], 123 'RRA:AVERAGE:0.5:288:%d' % count[3], 124 'RRA:MAX:0.5:1:%d' % count[0], 125 'RRA:MAX:0.5:6:%d' % count[1], 126 'RRA:MAX:0.5:24:%d' % count[2], 127 'RRA:MAX:0.5:288:%d' % count[3]) 128 paths.append(path) 129 self.info("Created RRD file: '%s'", path) 130 except Exception, e: 131 self.warning("Error creating RRD file '%s': %s", 132 path, log.getExceptionMessage(e)) 133 m = messages.Warning(T_(N_( 134 "Could not create RRD file '%s'.\n"), path), 135 debug=log.getExceptionMessage(e), 136 mid='rrd-create-error-%s' % path) 137 self._component.addMessage(m) 138 else: 139 paths.append(path) 140 self.info("Using existing RRD file: '%s'", path) 141 142 return paths
143