Gentoo Archives: gentoo-commits

From: "André Erdmann" <dywi@×××××××.de>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/db/
Date: Tue, 30 Jul 2013 18:40:27
Message-Id: 1375200132.3b92458a280855f69a6aabc8a6c84e4868562444.dywi@gentoo
1 commit: 3b92458a280855f69a6aabc8a6c84e4868562444
2 Author: André Erdmann <dywi <AT> mailerd <DOT> de>
3 AuthorDate: Tue Jul 30 16:02:12 2013 +0000
4 Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
5 CommitDate: Tue Jul 30 16:02:12 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=3b92458a
7
8 roverlay/db: rrdtool.py
9
10 ---
11 roverlay/db/rrdtool.py | 176 +++++++++++++++++++++++++++++++++++++++++++++++++
12 1 file changed, 176 insertions(+)
13
14 diff --git a/roverlay/db/rrdtool.py b/roverlay/db/rrdtool.py
15 new file mode 100644
16 index 0000000..6d450fe
17 --- /dev/null
18 +++ b/roverlay/db/rrdtool.py
19 @@ -0,0 +1,176 @@
20 +# R overlay -- stats collection, wrapper for writing rrd databases
21 +# -*- coding: utf-8 -*-
22 +# Copyright (C) 2013 André Erdmann <dywi@×××××××.de>
23 +# Distributed under the terms of the GNU General Public License;
24 +# either version 2 of the License, or (at your option) any later version.
25 +
26 +from __future__ import division
27 +
28 +# NOT using rrdtool's python bindings as they're available for python 2 only
29 +
30 +import logging
31 +import os
32 +import time
33 +
34 +import roverlay.tools.runcmd
35 +from roverlay.tools.runcmd import run_command
36 +
37 +import roverlay.util
38 +
39 +import roverlay.util.objects
40 +
41 +class RRDVariable ( object ):
42 +
43 + DST = frozenset ({ 'GAUGE', 'COUNTER', 'DERIVE', 'ABSOLUTE', })
44 +
45 + def __init__ ( self,
46 + name, val_type, val_min=None, val_max=None, heartbeat=None, step=300
47 + ):
48 + if val_type not in self.DST:
49 + raise ValueError ( "invalid DS type: {!r}".format ( val_type ) )
50 +
51 + self.name = name
52 + self.val_type = val_type
53 + self.val_min = val_min
54 + self.val_max = val_max
55 + self.heartbeat = heartbeat or ( 2 * step )
56 + # --- end of __init__ (...) ---
57 +
58 + def get_key ( self ):
59 + mstr = lambda k: 'U' if k is None else str ( k )
60 +
61 + return "DS:{ds_name}:{DST}:{heartbeat}:{vmin}:{vmax}".format (
62 + ds_name=self.name, DST=self.val_type, heartbeat=self.heartbeat,
63 + vmin=mstr ( self.val_min ), vmax=mstr ( self.val_max )
64 + )
65 + # --- end of get_key (...) ---
66 +
67 + __str__ = get_key
68 +
69 +# --- end of RRDVariable ---
70 +
71 +class RRDArchive ( object ):
72 +
73 + CF_TYPES = frozenset ({ 'AVERAGE', 'MIN', 'MAX', 'LAST', })
74 +
75 + def __init__ ( self, cf, xff, steps, rows ):
76 + if cf not in self.CF_TYPES:
77 + raise ValueError ( "unknown CF: {!r}".format ( cf ) )
78 + elif not isinstance ( xff, float ):
79 + raise TypeError ( "xff must be a float." )
80 + elif xff < 0.0 or xff >= 1.0:
81 + raise ValueError (
82 + "xff not in range: 0.0 <= {:f} <= 1.0?".format ( xff )
83 + )
84 + elif not isinstance ( steps, int ) or steps <= 0:
85 + raise ValueError ( "steps must be an integer > 0." )
86 +
87 + elif not isinstance ( rows, int ) or rows <= 0:
88 + raise ValueError ( "rows must be an integer > 0." )
89 +
90 + self.cf = cf
91 + self.xff = float ( xff )
92 + self.steps = int ( steps )
93 + self.rows = int ( rows )
94 + # --- end of __init__ (...) ---
95 +
96 + def get_key ( self ):
97 + return "RRA:{cf}:{xff}:{steps}:{rows}".format (
98 + cf=self.cf, xff=self.xff, steps=self.steps, rows=self.rows
99 + )
100 + # --- end of get_key (...) ---
101 +
102 + __str__ = get_key
103 +
104 + @classmethod
105 + def new_day ( cls, cf, xff, step=300 ):
106 + # one CDP per hour (24 rows)
107 + return cls ( cf, xff, 3600 // step, 24 )
108 + # --- end of new_day (...) ---
109 +
110 + @classmethod
111 + def new_week ( cls, cf, xff, step=300 ):
112 + # one CDP per 6h (28 rows)
113 + return cls ( cf, xff, 21600 // step, 42 )
114 + # --- end of new_week (...) ---
115 +
116 + @classmethod
117 + def new_month ( cls, cf, xff, step=300 ):
118 + # one CDP per day (31 rows)
119 + return cls ( cf, xff, (24*3600) // step, 31 )
120 + # --- end of new_month (...) ---
121 +
122 +# --- end of RRDArchive ---
123 +
124 +class RRD ( object ):
125 + # should be subclassed 'cause _do_create() is not implemented here
126 +
127 + RRDTOOL_CMDV_HEAD = ( 'rrdtool', )
128 +
129 + LOGGER = logging.getLogger ( 'RRD' )
130 +
131 + def __init__ ( self, filepath ):
132 + self.filepath = filepath
133 + self._commit_buffer = []
134 + self._dbfile_exists = False
135 + self.logger = self.__class__.LOGGER
136 + self.INIT_TIME = self.time_now() - 10
137 + # --- end of __init__ (...) ---
138 +
139 + def time_now ( self ):
140 + return int ( time.time() )
141 + # --- end of time_now (...) ---
142 +
143 + def _call_rrdtool ( self, args, return_success=True ):
144 + return run_command (
145 + self.RRDTOOL_CMDV_HEAD + args, None, self.logger,
146 + return_success=return_success
147 + )
148 + # --- end of _call_rrdtool (...) ---
149 +
150 + @roverlay.util.objects.abstractmethod
151 + def _do_create ( self, filepath ):
152 + pass
153 + # --- end of _do_create (...) ---
154 +
155 + def create_if_missing ( self ):
156 + if self._dbfile_exists or not os.access ( self.filepath, os.F_OK ):
157 + return self.create()
158 + # --- end of create_if_missing (...) ---
159 +
160 + def create ( self ):
161 + roverlay.util.dodir_for_file ( self.filepath )
162 + self._do_create ( self.filepath )
163 + if os.access ( self.filepath, os.F_OK ):
164 + self._dbfile_exists = True
165 + else:
166 + raise Exception ( "database file does not exist." )
167 + # --- end of create (...) ---
168 +
169 + def add ( self, values, timestamp=None ):
170 + if timestamp is False:
171 + t = 'N'
172 + elif timestamp is None:
173 + t = str ( self.time_now() )
174 + else:
175 + t = str ( timestamp )
176 +
177 + self._commit_buffer.append (
178 + t + ':' + ':'.join ( str(v) for v in values )
179 + )
180 + # --- end of add (...) ---
181 +
182 + def clear ( self ):
183 + self._commit_buffer = []
184 + # --- end of clear (...) ---
185 +
186 + def commit ( self ):
187 + if self._commit_buffer:
188 + self.create_if_missing()
189 + self._call_rrdtool (
190 + ( 'update', self.filepath ) + tuple ( self._commit_buffer )
191 + )
192 + self.clear()
193 + # --- end of commit (...) ---
194 +
195 +# --- end of RRD ---