Commit 993d9fcd authored by Vincent Pelletier's avatar Vincent Pelletier

Replace matplotlib with js-based graphing.

parent 9fa71de0
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
############################################################################## ##############################################################################
# TODO: # TODO:
# - use some templating system instead of hardcoded html strings # - use some templating system instead of hardcoded html strings
# - implement an alternative to matplotlib (inline SVG ? flotcharts ?) to have
# nice output with pypy
# - provide some form of raw data output, not just html # - provide some form of raw data output, not just html
# - allow user to specify min & max dates # - allow user to specify min & max dates
from cgi import escape from cgi import escape
...@@ -40,20 +38,12 @@ from operator import itemgetter ...@@ -40,20 +38,12 @@ from operator import itemgetter
from urllib import splittype, splithost from urllib import splittype, splithost
import argparse import argparse
import gzip import gzip
import json
import os import os
import re import re
import sys import sys
import time import time
try:
import matplotlib
except ImportError:
matplotlib = None
else:
matplotlib.use('Agg')
import matplotlib.pyplot as pyplot
from matplotlib.dates import AutoDateLocator, AutoDateFormatter
MONTH_VALUE_DICT = dict((y, x) for (x, y) in enumerate(('Jan', 'Feb', 'Mar', MONTH_VALUE_DICT = dict((y, x) for (x, y) in enumerate(('Jan', 'Feb', 'Mar',
'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), 1)) 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), 1))
...@@ -384,6 +374,7 @@ period_parser = { ...@@ -384,6 +374,7 @@ period_parser = {
} }
def main(): def main():
file_dir = os.path.dirname(__file__)
parser = argparse.ArgumentParser(description='Compute Apdex out of log files') parser = argparse.ArgumentParser(description='Compute Apdex out of log files')
parser.add_argument('logfile', nargs='+', parser.add_argument('logfile', nargs='+',
help='Log files to process') help='Log files to process')
...@@ -418,6 +409,10 @@ def main(): ...@@ -418,6 +409,10 @@ def main():
help='Suppress warnings about malformed lines.') help='Suppress warnings about malformed lines.')
parser.add_argument('-s', '--stats', action='store_true', parser.add_argument('-s', '--stats', action='store_true',
help='Enable parsing stats (time taken to parse all files, ...)') help='Enable parsing stats (time taken to parse all files, ...)')
parser.add_argument('--js', default=file_dir,
help='Folder containing needed js files. Default: %(default)s')
parser.add_argument('--js-embed', action='store_true',
help='Embed js files instead of linking to them.')
args = parser.parse_args() args = parser.parse_args()
line_regex = '' line_regex = ''
try: try:
...@@ -524,56 +519,53 @@ def main(): ...@@ -524,56 +519,53 @@ def main():
'.stats th.text, .stats td.text { text-align: left; } ' '.stats th.text, .stats td.text { text-align: left; } '
'table.stats { border-collapse: collapse; } ' 'table.stats { border-collapse: collapse; } '
'.problem { background-color: #f00; color: white; } ' '.problem { background-color: #f00; color: white; } '
'.warning { background-color: #f80; color: white; }' '.warning { background-color: #f80; color: white; } '
'</style></head><body><h1>Overall</h1>' 'h1 { background-color: #ccc; }'
'h2 { background-color: #eee; }'
'</style>')
for script in ('jquery.js', 'jquery.flot.js', 'jquery.flot.time.js',
'main.js'):
if args.js_embed:
out.write('<script type="text/javascript">//<![CDATA[')
out.write(getResource(script))
out.write('//]]></script>')
else:
out.write('<script type="text/javascript" src="%s/%s"></script>' % (
args.js, script))
out.write('</head><body><h1>Overall</h1>'
'<h2>Hits per day</h2><table class="stats"><tr><th>date</th><th>hits</th></tr>') '<h2>Hits per day</h2><table class="stats"><tr><th>date</th><th>hits</th></tr>')
for date, hit in sorted(hit_per_day.iteritems(), key=ITEMGETTER0): for date, hit in sorted(hit_per_day.iteritems(), key=ITEMGETTER0):
out.write('<tr><td>%s</td><td>%s</td></tr>' % (date, hit)) out.write('<tr><td>%s</td><td>%s</td></tr>' % (date, hit))
out.write('</table>') out.write('</table>')
def graph(title, data, options={}):
out.write('<h2>%s</h2><div class="graph" style="width:600px;height:300px" '
'data-points="' % title)
out.write(escape(json.dumps(data), quote=True))
out.write('" data-options="')
out.write(escape(json.dumps(options), quote=True))
out.write('"></div>')
for site_id, data in per_site.iteritems(): for site_id, data in per_site.iteritems():
out.write('<h1>Site: %s</h1>' % site_id) out.write('<h1>Site: %s</h1>' % site_id)
if matplotlib is not None: daily_data = data.getApdexData()
daily_data = data.getApdexData() date_list = [int(time.mktime(time.strptime(x[0], '%Y/%m/%d' + {
date_list = [datetime.strptime(x[0], '%Y/%m/%d' + {'day': ' %H'}.get( 'day': ' %H'}.get(args.period, ''))) * 1000) for x in daily_data]
args.period, '')) for x in daily_data] graph('Apdex',
date_locator = AutoDateLocator(minticks=3, maxticks=5) [zip(date_list, (x[1] for x in daily_data))],
date_formatter = AutoDateFormatter(date_locator) {
date_formatter.scaled = { 'xaxis': {'mode': 'time'},
365.: '%Y', 'yaxis': {'max': 100},
30.: '%Y/%m', 'lines': {'show': True},
1.: '%Y/%m/%d', 'points': {'show': True},
1. / 24: '%Y/%m/%d\n%H:%M', },
} )
apdex_plot = pyplot.subplot(2, 1, 1) graph('Hits',
apdex_plot.xaxis.set_major_locator(date_locator) [zip(date_list, (x[4] for x in daily_data))],
apdex_plot.xaxis.set_major_formatter(date_formatter) {
pyplot.title('Apdex') 'xaxis': {'mode': 'time'},
pyplot.ylabel('%') 'lines': {'show': True},
pyplot.plot(date_list, [x[1] for x in daily_data], '-') 'points': {'show': True},
pyplot.plot(date_list, [x[1] for x in daily_data], '.') },
)
# response_time_plot = pyplot.subplot(3, 1, 2)
# response_time_plot.xaxis.set_major_locator(date_locator)
# response_time_plot.xaxis.set_major_formatter(date_formatter)
# pyplot.title('Response time')
# pyplot.ylabel('time (s)')
# pyplot.plot(date_list, [x[2] for x in daily_data], '-', label='Average')
# pyplot.plot(date_list, [x[3] for x in daily_data], '--', label='Max')
# pyplot.legend()
hit_plot = pyplot.subplot(2, 1, 2)
hit_plot.xaxis.set_major_locator(date_locator)
hit_plot.xaxis.set_major_formatter(date_formatter)
pyplot.title('Hits')
pyplot.plot(date_list, [x[4] for x in daily_data], '-')
pyplot.plot(date_list, [x[4] for x in daily_data], '.')
plot_filename = site_id.strip('/').replace('/', '__') + '.png'
pyplot.subplots_adjust(hspace=.4)
pyplot.savefig(plot_filename)
pyplot.clf()
out.write('<img src="' + plot_filename + '" />')
out.write(data.asHTML(decimator)) out.write(data.asHTML(decimator))
end_stat_time = time.time() end_stat_time = time.time()
if args.stats: if args.stats:
......
$(function() {
$(".graph").each(function (i){
$.plot(
this,
$.parseJSON($(this).attr('data-points')),
$.parseJSON($(this).attr('data-options')));
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment