]> git.decadent.org.uk Git - dak.git/blob - dak/graph.py
Merge remote branch 'ansgar/version-checks' into merge
[dak.git] / dak / graph.py
1 #!/usr/bin/env python
2
3 """ Produces a set of graphs of NEW/BYHAND/DEFERRED
4
5 @contact: Debian FTPMaster <ftpmaster@debian.org>
6 @copyright: 2011 Paul Wise <pabs@debian.org>
7 """
8
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
13
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
23 import os
24 import sys
25 import colorsys
26
27 import rrdtool
28 import apt_pkg
29
30 from daklib import utils
31 from daklib.dak_exceptions import *
32
33 Cnf = None
34 default_names = ["byhand", "new", "deferred"]
35
36 ################################################################################
37
38 def usage(exit_code=0):
39     print """Usage: dak graph
40 Graphs the number of packages in queue directories (usually new and byhand).
41
42   -h, --help                show this help and exit.
43   -r, --rrd=key             Directory where rrd files to be updated are stored
44   -x, --extra-rrd=key       File containing extra options to rrdtool graphing
45   -i, --images=key          Directory where image graphs to be updated are stored
46   -n, --names=key           A comma seperated list of rrd files to be scanned
47
48 """
49     sys.exit(exit_code)
50
51 ################################################################################
52
53 def graph(*args):
54     if args[2] == "deferred":
55         graph_deferred(*args)
56     else:
57         graph_normal(*args)
58
59 def deferred_colours():
60     colours = [0]*16
61     for i in range(0,16):
62         colours[i] = colorsys.hsv_to_rgb(i/16.0, 1.0, 0.5+i/32.0)
63         colours[i] = ''.join(['%02X' % (c*255) for c in colours[i]])
64     return colours
65
66 colours = deferred_colours()
67
68 def graph_deferred(rrd_dir, image_dir, name, extra_args, graph, title, start, year_lines=False):
69     image_file = os.path.join(image_dir, "%s-%s.png" % (name, graph))
70     rrd_file = os.path.join(rrd_dir, "%s.rrd" % name)
71     rrd_args = [image_file, "--start", start]
72     rrd_args += ("""
73 --end
74 now
75 --width
76 600
77 --height
78 150
79 --vertical-label
80 changes
81 --title
82 %s changes count for the last %s
83 --lower-limit
84 0
85 -E
86 """ % (name.upper(), title) ).strip().split("\n")
87
88     if year_lines:
89         rrd_args += ["--x-grid", "MONTH:1:YEAR:1:YEAR:1:31536000:%Y"]
90
91     for i in range(0,16):
92         rrd_args += ("""
93 DEF:d%i=%s:day%i:AVERAGE
94 AREA:d%i#%s:%i-day changes count:STACK
95 VDEF:ld%i=d%i,LAST
96 VDEF:mind%i=d%i,MINIMUM
97 VDEF:maxd%i=d%i,MAXIMUM
98 VDEF:avgd%i=d%i,AVERAGE
99 GPRINT:ld%i:cur\\: %%.0lf
100 GPRINT:mind%i:min\\: %%.0lf
101 GPRINT:maxd%i:max\\: %%.0lf
102 GPRINT:avgd%i:avg\\: %%.0lf\\j
103 """ % ((i, rrd_file, i, i, colours[i])+(i,)*13)).strip().split("\n")
104
105     rrd_args += extra_args
106     try:
107         ret = rrdtool.graph(*rrd_args)
108     except rrdtool.error, e:
109         print('warning: graph: rrdtool error, skipping %s-%s.png: %s' % (name, graph, e))
110
111 def graph_normal(rrd_dir, image_dir, name, extra_args, graph, title, start, year_lines=False):
112     image_file = os.path.join(image_dir, "%s-%s.png" % (name, graph))
113     rrd_file = os.path.join(rrd_dir, "%s.rrd" % name)
114     rrd_args = [image_file, "--start", start]
115     rrd_args += ("""
116 --end
117 now
118 --width
119 600
120 --height
121 150
122 --vertical-label
123 packages
124 --title
125 %s package count for the last %s
126 --lower-limit
127 0
128 -E
129 """ % (name.upper(), title) ).strip().split("\n")
130
131     if year_lines:
132         rrd_args += ["--x-grid", "MONTH:1:YEAR:1:YEAR:1:31536000:%Y"]
133
134     rrd_args += ("""
135 DEF:ds1=%s:ds1:AVERAGE
136 LINE2:ds1#D9382B:changes count
137 VDEF:lds1=ds1,LAST
138 VDEF:minds1=ds1,MINIMUM
139 VDEF:maxds1=ds1,MAXIMUM
140 VDEF:avgds1=ds1,AVERAGE
141 GPRINT:lds1:cur\\: %%.0lf
142 GPRINT:minds1:min\\: %%.0lf
143 GPRINT:maxds1:max\\: %%.0lf
144 GPRINT:avgds1:avg\\: %%.0lf\\j
145 DEF:ds0=%s:ds0:AVERAGE
146 VDEF:lds0=ds0,LAST
147 VDEF:minds0=ds0,MINIMUM
148 VDEF:maxds0=ds0,MAXIMUM
149 VDEF:avgds0=ds0,AVERAGE
150 LINE2:ds0#3069DA:src pkg count
151 GPRINT:lds0:cur\\: %%.0lf
152 GPRINT:minds0:min\\: %%.0lf
153 GPRINT:maxds0:max\\: %%.0lf
154 GPRINT:avgds0:avg\\: %%.0lf\\j
155 """ % (rrd_file, rrd_file)).strip().split("\n")
156
157     rrd_args += extra_args
158     try:
159         ret = rrdtool.graph(*rrd_args)
160     except rrdtool.error, e:
161         print('warning: graph: rrdtool error, skipping %s-%s.png: %s' % (name, graph, e))
162
163 ################################################################################
164
165 def main():
166     global Cnf
167
168     Cnf = utils.get_conf()
169     Arguments = [('h',"help","Graph::Options::Help"),
170                  ('x',"extra-rrd","Graph::Options::Extra-Rrd", "HasArg"),
171                  ('r',"rrd","Graph::Options::Rrd", "HasArg"),
172                  ('i',"images","Graph::Options::Images", "HasArg"),
173                  ('n',"names","Graph::Options::Names", "HasArg")]
174     for i in [ "help" ]:
175         if not Cnf.has_key("Graph::Options::%s" % (i)):
176             Cnf["Graph::Options::%s" % (i)] = ""
177
178     apt_pkg.ParseCommandLine(Cnf, Arguments, sys.argv)
179
180     Options = Cnf.SubTree("Graph::Options")
181     if Options["Help"]:
182         usage()
183
184     names = []
185
186     if Cnf.has_key("Graph::Options::Names"):
187         for i in Cnf["Graph::Options::Names"].split(","):
188             names.append(i)
189     elif Cnf.has_key("Graph::Names"):
190         names = Cnf.ValueList("Graph::Names")
191     else:
192         names = default_names
193
194     extra_rrdtool_args = []
195
196     if Cnf.has_key("Graph::Options::Extra-Rrd"):
197         for i in Cnf["Graph::Options::Extra-Rrd"].split(","):
198             f = open(i)
199             extra_rrdtool_args.extend(f.read().strip().split("\n"))
200             f.close()
201     elif Cnf.has_key("Graph::Extra-Rrd"):
202         for i in Cnf.ValueList("Graph::Extra-Rrd"):
203             f = open(i)
204             extra_rrdtool_args.extend(f.read().strip().split("\n"))
205             f.close()
206
207     if Cnf.has_key("Graph::Options::Rrd"):
208         rrd_dir = Cnf["Graph::Options::Rrd"]
209     elif Cnf.has_key("Dir::Rrd"):
210         rrd_dir = Cnf["Dir::Rrd"]
211     else:
212         print >> sys.stderr, "No directory to read RRD files from\n"
213         sys.exit(1)
214
215     if Cnf.has_key("Graph::Options::Images"):
216         image_dir = Cnf["Graph::Options::Images"]
217     else:
218         print >> sys.stderr, "No directory to write graph images to\n"
219         sys.exit(1)
220
221     for name in names:
222         stdargs = [rrd_dir, image_dir, name, extra_rrdtool_args]
223         graph(*(stdargs+['day', 'day', 'now-1d']))
224         graph(*(stdargs+['week', 'week', 'now-1w']))
225         graph(*(stdargs+['month', 'month', 'now-1m']))
226         graph(*(stdargs+['year', 'year', 'now-1y']))
227         graph(*(stdargs+['5years', '5 years', 'now-5y', True]))
228         graph(*(stdargs+['10years', '10 years', 'now-10y', True]))
229
230 ################################################################################
231
232 if __name__ == '__main__':
233     main()