]> git.decadent.org.uk Git - dak.git/blob - tools/logs.py
Merge branch 'master' of ftp-master.debian.org:/srv/ftp.debian.org/git/dak
[dak.git] / tools / logs.py
1 #!/usr/bin/python
2 # (c) 2008 Thomas Viehmann
3 # Free software licensed under the GPL version 2 or later
4
5
6 import os,re,datetime, sys
7 import tempfile, time
8
9 ITEMS_TO_KEEP = 20
10 CACHE_FILE = '/srv/ftp-master.debian.org/misc/dinstall_time_cache'
11 GRAPH_DIR = '/srv/ftp.debian.org/web/stat'
12
13 LINE = re.compile(r'(?:|.*/)dinstall_(\d{4})\.(\d{2})\.(\d{2})-(\d{2}):(\d{2}):(\d{2})\.log(?:\.bz2)?:'+
14                   r'Archive maintenance timestamp \(([^\)]*)\): (\d{2}):(\d{2}):(\d{2})$')
15 UNSAFE = re.compile(r'[^a-zA-Z/\._:0-9\- ]')
16
17 graphs = {"dinstall1": {"keystolist":["pg_dump1", "i18n 1", "accepted", "dominate", "generate-filelist", "apt-ftparchive",
18                                     "pdiff", "release files", "w-b", "i18n 2", "apt-ftparchive cleanup"],
19                         "showothers":True},
20           "dinstall2": {"keystolist":['External Updates', 'p-u-new', 'o-p-u-new', 'cruft', 'import-keyring', 'overrides', 'cleanup', 'scripts', 'mirror hardlinks', 'stats', 'compress', "pkg-file-mapping" ],
21                         "showothers":False},
22           "totals":{"keystolist":["apt-ftparchive", "apt-ftparchive cleanup"],"showothers":True}}
23
24 #'mirror hardlinks', 'apt-ftparchive', 'logremove', 'startup', 'import-keyring', 'release files', 'accepted', 'stats', 'o-p-u-new', 'i18n 2', 'locked part finished', 'i18n 1', 'cruft', 'pdiff', 'init', 'cleanup', , 'p-u-new', 'run-parts', 'compress', 'scripts', 'expire_dumps', 'removed', 'make-suite-file-list', 'pg_dump1', 'pg_dump2', 'overrides', 'reports', 'merkel projectb push', 'buildd', 'apt-ftparchive cleanup', 'w-b'
25
26 wantkeys = set()
27 for tmp in graphs.values():
28     wantkeys |= set(tmp["keystolist"])
29
30 d = {}
31 kl = []
32 ks = set()
33 if os.path.exists(CACHE_FILE):
34     for l in open(CACHE_FILE):
35         dt, l = l.split('\t',1)
36         l = map(lambda x: (lambda y: (y[0],float(y[1])))(x.split(':',1)), l.split('\t'))
37         newk = [x[0] for x in l if x[0] not in ks]
38         kl += newk
39         ks |= set(newk)
40         d[dt] = dict(l)
41
42 olddt = None
43 args = sys.argv[1:]
44 m = UNSAFE.search(' '.join(args))
45 if m:
46     raise Exception("I don't like command line arguments including char '%s'"%m.group(0))
47
48 if args:
49   for l in os.popen('bzgrep -H "^Archive maintenance timestamp" "'+'" "'.join(args)+'"'):
50     m = LINE.match(l)
51     if not m:
52         raise Exception("woops '%s'"%l)
53     g = map(lambda x: (not x.isdigit() and x) or int(x), m.groups())
54     dt = datetime.datetime(*g[:6])
55     if olddt != dt:
56         oldsecs = 0
57         olddt = dt
58     dt2 = datetime.datetime(*(g[:3]+g[-3:]))
59     secs = (dt2-dt).seconds
60     assert secs >= 0 # should add 24*60*60
61     k = g[6]
62     d.setdefault(str(dt),{})[k] = (secs-oldsecs)/60.0
63     oldsecs = secs
64     if k not in ks:
65         ks.add(k)
66         kl.append(k)
67
68 if (wantkeys-ks):
69     print >> sys.stderr, "warning, requested keys not found in any log: "+' '.join(wantkeys-ks)
70
71 datakeys = d.keys()
72 datakeys.sort()
73
74 f = open(CACHE_FILE+".tmp","w")
75 for dk in datakeys:
76     print >> f, dk+'\t'+'\t'.join(
77       ["%s:%s"%(k,str(d[dk][k])) for k in kl if k in d[dk]])
78 f.close()
79 os.rename(CACHE_FILE+".tmp", CACHE_FILE)
80 datakeys = datakeys[-ITEMS_TO_KEEP:]
81
82 def dump_file(outfn,keystolist, showothers):
83     showothers = (showothers and 1) or 0
84     # careful, outfn is NOT ESCAPED
85     f = tempfile.NamedTemporaryFile()
86     otherkeys = ks-set(keystolist)
87     print >>f, '\t'.join(keystolist+showothers*['other'])
88     for k in datakeys:
89         v = d[k]
90         others = sum(map(lambda x: v.get(x,0),otherkeys))
91         print >>f, k+'\t'+'\t'.join(map(lambda x: str(v.get(x,0)), keystolist)+showothers*[str(others)])
92     f.flush()
93     n = f.name
94
95     p = os.popen("R --vanilla --slave > /dev/null","w")
96     p.write("""
97   d = read.table("%(datafile)s",  sep = "\t")
98   #d[["ts"]] <- as.POSIXct(d[["timestamp"]])
99   k = setdiff(names(d),c("ts","timestamp"))
100   #palette(rainbow(max(length(k),2)))
101   palette(c("midnightblue", "gold", "turquoise", "plum4", "palegreen1", "OrangeRed", "green4", "blue",
102         "magenta", "darkgoldenrod3", "tomato4", "violetred2","thistle4", "steelblue2", "springgreen4", "salmon","gray"))
103   #plot(d[["runtime"]],d[["compress"]],type="l",col="blue")
104   #lines(d[["runtime"]],d[["logremove"]],type="l",col="red")
105   #legend(as.POSIXct("2008-12-05"),9500,"logremove",col="red",lty=1)
106   bitmap(file = "%(outfile)s", type="png16m",width=16.9,height=11.8)
107   #plot(d[["ts"]],d[["compress"]],type="l",col="blue")
108   #lines(d[["ts"]],d[["logremove"]],type="l",col="red")
109   barplot(t(d[,k]), col=palette(), xlab="date",ylab="time/minutes"
110           )
111   par(xpd = TRUE)
112   legend(xinch(-1.2),par("usr")[4]+yinch(1),legend=k,
113                   ncol=3,fill=1:15) #,xjust=1,yjust=1)
114   text(xinch(10),par("usr")[4]+yinch(.5),"%(title)s", cex=2)
115
116   dev.off()
117   q()
118   """%{'datafile':n,'outfile':outfn,
119        'title':((not showothers)*"partial ")+"dinstall times"})
120     p.flush()
121     assert not p.close()
122
123 for afn,params in graphs.items():
124     dump_file(os.path.join(GRAPH_DIR,afn+'.png'), **params)