1#! /usr/bin/env python3
3"""Produces a set of graphs of NEW/BYHAND/DEFERRED
5@contact: Debian FTPMaster <ftpmaster@debian.org>
6@copyright: 2011 Paul Wise <pabs@debian.org>
7"""
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.
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.
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
23import colorsys
24import os
25import sys
27import apt_pkg
28import rrdtool
30from daklib import utils
32Cnf = None
33default_names = ["byhand", "new", "deferred"]
35################################################################################
38def usage(exit_code=0):
39 print(
40 """Usage: dak graph
41Graphs the number of packages in queue directories (usually new and byhand).
43 -h, --help show this help and exit.
44 -r, --rrd=key Directory where rrd files to be updated are stored
45 -x, --extra-rrd=key File containing extra options to rrdtool graphing
46 -i, --images=key Directory where image graphs to be updated are stored
47 -n, --names=key A comma separated list of rrd files to be scanned
49"""
50 )
51 sys.exit(exit_code)
54################################################################################
57def graph(*args):
58 if args[2] == "deferred":
59 graph_deferred(*args)
60 else:
61 graph_normal(*args)
64def deferred_colours():
65 colours = [0] * 16
66 for i in range(0, 16):
67 colours[i] = colorsys.hsv_to_rgb(i / 16.0, 1.0, 0.5 + i / 32.0)
68 colours[i] = "".join("%02X" % int(c * 255) for c in colours[i])
69 return colours
72colours = deferred_colours()
75def graph_deferred(
76 rrd_dir, image_dir, name, extra_args, graph, title, start, year_lines=False
77):
78 image_file = os.path.join(image_dir, "%s-%s.png" % (name, graph))
79 rrd_file = os.path.join(rrd_dir, "%s.rrd" % name)
80 rrd_args = [image_file, "--start", start]
81 rrd_args += (
82 (
83 """
84--end
85now
86--width
87600
88--height
89150
90--vertical-label
91changes
92--title
93%s changes count for the last %s
94--lower-limit
950
96-E
97"""
98 % (name.upper(), title)
99 )
100 .strip()
101 .split("\n")
102 )
104 if year_lines:
105 rrd_args += ["--x-grid", "MONTH:1:YEAR:1:YEAR:1:31536000:%Y"]
107 for i in range(0, 16):
108 rrd_args += (
109 (
110 """
111DEF:d%i=%s:day%i:AVERAGE
112AREA:d%i#%s:%i-day changes count:STACK
113VDEF:ld%i=d%i,LAST
114VDEF:mind%i=d%i,MINIMUM
115VDEF:maxd%i=d%i,MAXIMUM
116VDEF:avgd%i=d%i,AVERAGE
117GPRINT:ld%i:cur\\: %%.0lf
118GPRINT:mind%i:min\\: %%.0lf
119GPRINT:maxd%i:max\\: %%.0lf
120GPRINT:avgd%i:avg\\: %%.0lf\\j
121"""
122 % ((i, rrd_file, i, i, colours[i]) + (i,) * 13)
123 )
124 .strip()
125 .split("\n")
126 )
128 rrd_args += extra_args
129 try:
130 rrdtool.graph(*rrd_args)
131 except rrdtool.error as e:
132 print(
133 ("warning: graph: rrdtool error, skipping %s-%s.png: %s" % (name, graph, e))
134 )
137def graph_normal(
138 rrd_dir, image_dir, name, extra_args, graph, title, start, year_lines=False
139):
140 image_file = os.path.join(image_dir, "%s-%s.png" % (name, graph))
141 rrd_file = os.path.join(rrd_dir, "%s.rrd" % name)
142 rrd_args = [image_file, "--start", start]
143 rrd_args += (
144 (
145 """
146--end
147now
148--width
149600
150--height
151150
152--vertical-label
153packages
154--title
155%s package count for the last %s
156--lower-limit
1570
158-E
159"""
160 % (name.upper(), title)
161 )
162 .strip()
163 .split("\n")
164 )
166 if year_lines:
167 rrd_args += ["--x-grid", "MONTH:1:YEAR:1:YEAR:1:31536000:%Y"]
169 rrd_args += (
170 (
171 """
172DEF:ds1=%s:ds1:AVERAGE
173LINE2:ds1#D9382B:changes count
174VDEF:lds1=ds1,LAST
175VDEF:minds1=ds1,MINIMUM
176VDEF:maxds1=ds1,MAXIMUM
177VDEF:avgds1=ds1,AVERAGE
178GPRINT:lds1:cur\\: %%.0lf
179GPRINT:minds1:min\\: %%.0lf
180GPRINT:maxds1:max\\: %%.0lf
181GPRINT:avgds1:avg\\: %%.0lf\\j
182DEF:ds0=%s:ds0:AVERAGE
183VDEF:lds0=ds0,LAST
184VDEF:minds0=ds0,MINIMUM
185VDEF:maxds0=ds0,MAXIMUM
186VDEF:avgds0=ds0,AVERAGE
187LINE2:ds0#3069DA:src pkg count
188GPRINT:lds0:cur\\: %%.0lf
189GPRINT:minds0:min\\: %%.0lf
190GPRINT:maxds0:max\\: %%.0lf
191GPRINT:avgds0:avg\\: %%.0lf\\j
192"""
193 % (rrd_file, rrd_file)
194 )
195 .strip()
196 .split("\n")
197 )
199 rrd_args += extra_args
200 try:
201 rrdtool.graph(*rrd_args)
202 except rrdtool.error as e:
203 print(
204 ("warning: graph: rrdtool error, skipping %s-%s.png: %s" % (name, graph, e))
205 )
208################################################################################
211def main():
212 global Cnf
214 Cnf = utils.get_conf()
215 Arguments = [
216 ("h", "help", "Graph::Options::Help"),
217 ("x", "extra-rrd", "Graph::Options::Extra-Rrd", "HasArg"),
218 ("r", "rrd", "Graph::Options::Rrd", "HasArg"),
219 ("i", "images", "Graph::Options::Images", "HasArg"),
220 ("n", "names", "Graph::Options::Names", "HasArg"),
221 ]
222 for i in ["help"]:
223 key = "Graph::Options::%s" % i
224 if key not in Cnf: 224 ↛ 222line 224 didn't jump to line 222, because the condition on line 224 was never false
225 Cnf[key] = ""
227 apt_pkg.parse_commandline(Cnf, Arguments, sys.argv)
229 Options = Cnf.subtree("Graph::Options")
230 if Options["Help"]: 230 ↛ 233line 230 didn't jump to line 233, because the condition on line 230 was never false
231 usage()
233 names = []
235 if "Graph::Options::Names" in Cnf:
236 for i in Cnf["Graph::Options::Names"].split(","):
237 names.append(i)
238 elif "Graph::Names" in Cnf:
239 names = Cnf.value_list("Graph::Names")
240 else:
241 names = default_names
243 extra_rrdtool_args = []
245 if "Graph::Options::Extra-Rrd" in Cnf:
246 for i in Cnf["Graph::Options::Extra-Rrd"].split(","):
247 with open(i) as f:
248 extra_rrdtool_args.extend(f.read().strip().split("\n"))
249 elif "Graph::Extra-Rrd" in Cnf:
250 for i in Cnf.value_list("Graph::Extra-Rrd"):
251 with open(i) as f:
252 extra_rrdtool_args.extend(f.read().strip().split("\n"))
254 if "Graph::Options::Rrd" in Cnf:
255 rrd_dir = Cnf["Graph::Options::Rrd"]
256 elif "Dir::Rrd" in Cnf:
257 rrd_dir = Cnf["Dir::Rrd"]
258 else:
259 print("No directory to read RRD files from\n", file=sys.stderr)
260 sys.exit(1)
262 if "Graph::Options::Images" in Cnf:
263 image_dir = Cnf["Graph::Options::Images"]
264 else:
265 print("No directory to write graph images to\n", file=sys.stderr)
266 sys.exit(1)
268 for name in names:
269 stdargs = [rrd_dir, image_dir, name, extra_rrdtool_args]
270 graph(*(stdargs + ["day", "day", "now-1d"]))
271 graph(*(stdargs + ["week", "week", "now-1w"]))
272 graph(*(stdargs + ["month", "month", "now-1m"]))
273 graph(*(stdargs + ["year", "year", "now-1y"]))
274 graph(*(stdargs + ["5years", "5 years", "now-5y", True]))
275 graph(*(stdargs + ["10years", "10 years", "now-10y", True]))
278################################################################################
281if __name__ == "__main__":
282 main()