]> git.donarmstrong.com Git - neurodebian.git/blob - tools/nd_apachelogs2subscriptionstats
More bandwidth.
[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         if len(bin_edges) < 2:
51             # protect against single data point entries by ignoring them
52             # wouldn't be able to draw a line anyway ;-)
53             continue
54         width = bin_edges[1] - bin_edges[0]
55         # think lines
56         ax.plot(bin_edges[:-1]+(width/2), hist / width,
57                 label=suite, color=colors[i%4], linestyle=linestyle[i//4], lw=2)
58         # transparent curve shading
59         ax.fill_between(bin_edges[:-1]+(width/2), 0, hist / width, alpha=0.2,
60                         label=suite, color=colors[i%4])
61         # figure out axis limits to avoid whitespace in plots
62         x_max = bin_edges[-2] + width/2
63         x_min = bin_edges[0] + width/2
64         if global_x_max is None or x_max > global_x_max:
65             global_x_max = x_max
66         if global_x_min is None or x_min < global_x_min:
67             global_x_min = x_min
68
69     ax.set_xlim(global_x_min, global_x_max)
70     ax.set_ylabel('New subscriptions [1/day]')
71     if title:
72         ax.set_title(title)
73     if ymax:
74         ax.set_ylim(0, ymax)
75
76     # set x-ticks in date
77     # see: http://matplotlib.sourceforge.net/examples/api/date_demo.html
78     ax.xaxis.set_major_locator(YearLocator())
79     ax.xaxis.set_major_formatter(DateFormatter('\n\n%Y'))
80     ax.xaxis.set_minor_locator(MonthLocator())
81     ax.xaxis.set_minor_formatter(DateFormatter('%b'))
82     # format the coords message box
83     ax.format_xdata = DateFormatter('%Y-%m-%d')
84     ax.grid(True)
85     # pukes with old matplotlib
86     #font = FontProperties()
87     #font.set_size = 8
88     pl.legend(loc='upper left', #prop=font,
89               labelspacing=.2, borderaxespad=.2,
90               handletextpad=.2, borderpad=.2)
91
92
93 if __name__ == '__main__':
94     if not len(sys.argv) > 1:
95         print 'Need output filename.'
96         sys.exit(1)
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=18).savefig(sys.argv[1], bbox_inches='tight', dpi=60)