Package zephir :: Package monitor :: Package agentmanager :: Module rrd
[hide private]
[frames] | no frames]

Source Code for Module zephir.monitor.agentmanager.rrd

  1  # -*- coding: UTF-8 -*- 
  2  ########################################################################### 
  3  # Eole NG - 2007 
  4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon) 
  5  # Licence CeCill  cf /root/LicenceEole.txt 
  6  # eole@ac-dijon.fr 
  7  ########################################################################### 
  8   
  9  """ 
 10  Interface orientée objet aux commandes RRDtool. 
 11   
 12  Il est conseillé de consulter la documentation des outils RRDtool: 
 13  L{http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/manual/index.html}. 
 14  """ 
 15   
 16  try: _ # localized string fetch function 
 17  except NameError: _ = str 
 18   
 19  from datetime import datetime, timedelta 
 20   
 21  import rrdtool, os 
 22  from twisted.python import log 
 23   
 24  from zephir.monitor.agentmanager import util 
 25   
 26  DATASOURCE_TYPES = ['GAUGE', 'COUNTER', 'DERIVE', 'ABSOLUTE'] 
 27  CONSOLIDATION_FUNCTIONS = ['AVERAGE', 'MIN', 'MAX', 'LAST'] 
 28   
 29   
 30   
 31   
32 -def rrd_date_from_datetime(date):
33 if date is None: 34 timestamp = 'N' 35 else: 36 delta = date - util.TIME_ORIGIN 37 timestamp = '%d' % (delta.days*24*3600 + delta.seconds) 38 return timestamp
39 40 41 42
43 -class Database:
44 """Round-Robin Database (fichier C{.rrd}) 45 """ 46
47 - def __init__(self, rrdfile, step=60):
48 self.rrdfile = rrdfile # TODO path + basename without .rrd extension 49 self.step = step 50 self.datasources = [] 51 self.archives = [] 52 self.graphs = []
53 54
55 - def new_datasource(self, name, ds_type='GAUGE', heartbeat=None, 56 min_bound=None, max_bound=None):
57 """Ajoute une nouvelle I{datasource} (DS) à la base de données 58 """ 59 if heartbeat is None: 60 heartbeat = 2 * self.step 61 ds = Datasource(name, ds_type, heartbeat, min_bound, max_bound) 62 self.datasources.append(ds)
63 64
65 - def new_archive(self, rows, consolidation='AVERAGE', 66 steps=1, xfiles_factor=0):
67 """Ajoute une nouvelle archive I{round-robin} (RRA) à la base 68 de données. 69 """ 70 rra = Archive(rows, consolidation, steps, xfiles_factor) 71 self.archives.append(rra)
72 73
74 - def new_graph(self, pngname, vnamedefs, options):
75 """Ajoute un nouveau graphe à la base de données. 76 77 @param vnamedefs: {vname: (ds_name, CF)} 78 """ 79 #TODO default options 80 defs = [ "DEF:%s=%s:%s:%s" % (vname, self.rrdfile, ds, cf) 81 for vname, (ds, cf) in vnamedefs.items() ] 82 graph = Graph(pngname, defs, *options) 83 self.graphs.append(graph)
84 85
86 - def create(self):
87 """Crée le fichier C{.rrd} une fois que les datasources, 88 archives et graphes ont été configurés. 89 """ 90 #TODO check if already created ? 91 if not os.path.exists(self.rrdfile): 92 begin = rrd_date_from_datetime(util.utcnow()) # - timedelta(seconds=10)) 93 args = [self.rrdfile, 94 "-b%s" % begin, 95 "-s%d" % self.step] 96 args += map(str, self.datasources) 97 args += map(str, self.archives) 98 #log.msg('RRDtool create: %s' % ' '.join(args)) 99 rrdtool.create(*args)
100 101
102 - def update(self, values, date=None): #values = list | dict
103 """Insère une nouvelle valeur dans la base de données. 104 105 @param values: soit une liste de valeurs (données dans l'ordre 106 de déclaration des champs), soit un dictionnaire C{{champ: 107 valeur}}. 108 """ 109 if date is None: 110 date = util.utcnow() 111 args = [self.rrdfile] 112 if type(values) is dict: 113 items = values.items() 114 args.append('-t' + ':'.join([ str(i[0]) for i in items])) 115 values = [ str(i[1]) for i in items] 116 args.append(rrd_date_from_datetime(date)+ ':' + ':'.join(values)) 117 #log.msg(' '.join(args)) 118 try: 119 rrdtool.update(*args) 120 except rrdtool.error, e: 121 log.msg(_('RRDtool warning: ') + str(e))
122 123
124 - def graph_all(self, additional_args = None):
125 """Génère ou met à jour tous les graphes de cette base de 126 données. 127 """ 128 for g in self.graphs: 129 g.graph(additional_args)
130 131 132 133
134 -class Datasource:
135
136 - def __init__(self, name, ds_type, heartbeat, 137 min_bound=None, max_bound=None):
138 assert not name is "" 139 assert ds_type in DATASOURCE_TYPES 140 assert not heartbeat is None 141 self.name = name 142 self.type = ds_type 143 self.heartbeat = heartbeat 144 self.min_bound = min_bound 145 self.max_bound = max_bound
146
147 - def __str__(self):
148 minb, maxb = "U", "U" 149 if self.min_bound is not None: minb = str(self.min_bound) 150 if self.max_bound is not None: maxb = str(self.max_bound) 151 return "DS:%(ds-name)s:%(DST)s:%(heartbeat)d:%(min)s:%(max)s" % { 152 'ds-name': self.name, 'DST': self.type, 153 'heartbeat': self.heartbeat, 154 'min': minb, 'max': maxb 155 }
156 157 158 159
160 -class Archive:
161
162 - def __init__(self, rows, consolidation='AVERAGE', 163 steps=1, xfiles_factor=0):
164 assert consolidation in CONSOLIDATION_FUNCTIONS 165 assert xfiles_factor >= 0.0 and xfiles_factor < 1 166 self.rows = rows 167 self.consolidation = consolidation 168 self.steps = steps 169 self.xfiles_factor = xfiles_factor
170
171 - def __str__(self):
172 return "RRA:%(CF)s:%(xff)f:%(steps)d:%(rows)d" % { 173 'CF': self.consolidation, 'xff': self.xfiles_factor, 174 'steps': self.steps, 175 'rows': self.rows 176 }
177 178 179 180
181 -class Graph:
182
183 - def __init__(self, imgname, defs, *options):
184 self.imgname = imgname 185 self.defs = defs 186 self.options = list(options)
187 # self.options.append('-z') 188
189 - def graph(self, additional_args = None):
190 #log.msg("*** rrd.graph %s" % self.imgname) 191 args = [self.imgname] 192 args += map(str, self.defs) 193 args += self.options 194 if additional_args is not None: 195 args += additional_args 196 return rrdtool.graph(*args)
197 198 199 200 201 # def test_main(): 202 # test_support.run_unittest(UserStringTest) 203 204 # if __name__ == "__main__": 205 # test_main() 206