]> git.donarmstrong.com Git - neurodebian.git/blob - tools/nd_apachelogs2subscriptionstats
Need to cope with popularity.
[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     if len(sys.argv) > 2:
94         ymax = float(sys.argv[2])
95     else:
96         ymax = 13
97     cfg_path="/home/neurodebian/neurodebian.git/neurodebian.cfg"
98     cfg = SafeConfigParser()
99     cfg.read(cfg_path)
100     data = []
101     for line in fileinput.FileInput(sys.argv[2:], openhook=fileinput.hook_compressed):
102         date, list_, ip = line.split(';')
103         try:
104             suite, loc = list_.split('.')
105         except ValueError:
106             suite = list_
107             loc = ''
108         date = datetime.strptime(date, "%d %b %Y")
109         data.append((ip.strip(), loc, suite, date2num(date)))
110     data = np.array(data, dtype=dt)
111     make_figure(data, ymax).savefig(sys.argv[1], bbox_inches='tight', dpi=60)