]> git.donarmstrong.com Git - neurodebian.git/blob - tools/nd_apachelogs2subscriptionstats
BF+ENH: nd_rebuildarchive had to have :s in the regexp for grep + notes for post...
[neurodebian.git] / tools / nd_apachelogs2subscriptionstats
1 #!/usr/bin/python
2 #
3 # Create a figure with the NeuroDebian repo subscription stats from the apache logs
4 # Requires out put of 
5 # zgrep "GET /lists/[a-z\.]\+ HTTP" neuro.debian.net-*access*gz | sed -e 's,.*gz:\([0-9\.]\+\).*\[\(.*\):.*:.*:.*/lists/\(.*\) HTTP.*,\2;\3;\1,' -e 's,/, ,g'
6 # either from a file or on stdin. Needs output filename as the only argument
7
8 import fileinput
9 import sys
10 from datetime import datetime
11 import numpy as np
12 import matplotlib
13 matplotlib.use('Agg')
14 import pylab as pl
15 from matplotlib.dates import date2num
16 from matplotlib.dates import YearLocator, MonthLocator, DateFormatter
17 from matplotlib.font_manager import FontProperties
18 from ConfigParser import SafeConfigParser
19
20
21 dt = [('ip', '|S16'),
22       ('loc', '|S3'),
23       ('suite', '|S20'),
24       ('date', float)]
25
26
27 def make_figure(data, ymax):
28     fig = pl.figure(figsize=(14,3))
29     ax = fig.add_subplot(121)
30     plot_datehist(ax, data, 10, [code for code in cfg.options('release codenames') if cfg.get('release codenames', code).count('Debian')], title="Debian", ymax=ymax)
31     ax = fig.add_subplot(122)
32     plot_datehist(ax, data, 10, [code for code in cfg.options('release codenames') if cfg.get('release codenames', code).count('Ubuntu')], title="Ubuntu", ymax=ymax)
33     fig.autofmt_xdate()
34     return fig
35
36
37 def plot_datehist(ax, data, bins, suites, title=None, ymax=None):
38     colors=['#ff0088', '#20435C', '#45902C', '#E08720']
39     linestyle=['-', '--']
40     global_x_max = None
41     global_x_min = None
42     global_y_max = None
43     for i, suite in enumerate(suites):
44         dates = data['date'][data['suite'] == suite]
45         # history in days
46         history_length = dates.max() - dates.min()
47         # make approx monthly bins, smaller bins yield spiky curves
48         # needs new=True to work with oldish numpy
49         (hist, bin_edges) = np.histogram(dates, np.ceil(history_length/30.), new=True)
50         width = bin_edges[1] - bin_edges[0]
51         # think lines
52         ax.plot(bin_edges[:-1]+(width/2), hist / width,
53                 label=suite, color=colors[i%4], linestyle=linestyle[i//4], lw=2)
54         # transparent curve shading
55         ax.fill_between(bin_edges[:-1]+(width/2), 0, hist / width, alpha=0.2,
56                         label=suite, color=colors[i%4])
57         # figure out axis limits to avoid whitespace in plots
58         x_max = bin_edges[-2] + width/2
59         x_min = bin_edges[0] + width/2
60         if global_x_max is None or x_max > global_x_max:
61             global_x_max = x_max
62         if global_x_min is None or x_min < global_x_min:
63             global_x_min = x_min
64
65     ax.set_xlim(global_x_min, global_x_max)
66     ax.set_ylabel('New subscriptions [1/day]')
67     if title:
68         ax.set_title(title)
69     if ymax:
70         ax.set_ylim(0, ymax)
71
72     # set x-ticks in date
73     # see: http://matplotlib.sourceforge.net/examples/api/date_demo.html
74     ax.xaxis.set_major_locator(YearLocator())
75     ax.xaxis.set_major_formatter(DateFormatter('\n\n%Y'))
76     ax.xaxis.set_minor_locator(MonthLocator())
77     ax.xaxis.set_minor_formatter(DateFormatter('%b'))
78     # format the coords message box
79     ax.format_xdata = DateFormatter('%Y-%m-%d')
80     ax.grid(True)
81     # pukes with old matplotlib
82     #font = FontProperties()
83     #font.set_size = 8
84     pl.legend(loc='upper left', #prop=font,
85               labelspacing=.2, borderaxespad=.2,
86               handletextpad=.2, borderpad=.2)
87
88
89 if __name__ == '__main__':
90     if not len(sys.argv) > 1:
91         print 'Need output filename.'
92         sys.exit(1)
93     cfg_path="/home/neurodebian/neurodebian.git/neurodebian.cfg"
94     cfg = SafeConfigParser()
95     cfg.read(cfg_path)
96     data = []
97     for line in fileinput.FileInput(sys.argv[2:], openhook=fileinput.hook_compressed):
98         date, list_, ip = line.split(';')
99         try:
100             suite, loc = list_.split('.')
101         except ValueError:
102             suite = list_
103             loc = ''
104         date = datetime.strptime(date, "%d %b %Y")
105         data.append((ip.strip(), loc, suite, date2num(date)))
106     data = np.array(data, dtype=dt)
107     make_figure(data, ymax=13).savefig(sys.argv[1], bbox_inches='tight', dpi=60)