2012-03-11 06:35:29 +01:00
#!/usr/bin/env python
2008-07-01 20:59:13 +02:00
# Copyright Arvid Norberg 2008. Use, modification and distribution is
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2011-03-20 09:58:16 +01:00
import os , sys , time , os
2012-03-11 06:35:29 +01:00
from multiprocessing . pool import ThreadPool
thread_pool = ThreadPool ( 4 )
2007-09-29 18:14:03 +02:00
2008-12-27 03:22:20 +01:00
stat = open ( sys . argv [ 1 ] )
line = stat . readline ( )
while not ' second: ' in line :
line = stat . readline ( )
keys = line . strip ( ) . split ( ' : ' ) [ 1 : ]
2011-03-20 09:58:16 +01:00
output_dir = ' session_stats_report '
2012-03-11 06:35:29 +01:00
line_graph = 0
histogram = 1
stacked = 2
graph_colors = [ ]
pattern = [ [ 0 , 0 , 1 ] , [ 0 , 1 , 0 ] , [ 1 , 0 , 0 ] , [ 1 , 0 , 1 ] , [ 0 , 1 , 1 ] , [ 1 , 1 , 0 ] ]
def process_color ( c , op ) :
for i in range ( 3 ) :
if op == 0 :
c [ i ] = min ( 255 , c [ i ] + 0xb0 )
if op == 2 :
c [ i ] = max ( 0 , c [ i ] - 0x50 )
return c
for i in range ( 0 , len ( pattern ) * 3 ) :
op = i / len ( pattern )
c = list ( pattern [ i % len ( pattern ) ] )
for i in range ( 3 ) : c [ i ] * = 0xff
c = process_color ( c , op )
c = ' # %02x %02x %02x ' % ( c [ 0 ] , c [ 1 ] , c [ 2 ] )
graph_colors . append ( c )
line_colors = list ( graph_colors )
line_colors . reverse ( )
def plot_fun ( script ) :
os . system ( ' gnuplot " %s " 2>/dev/null ' % script ) ;
sys . stdout . write ( ' . ' )
sys . stdout . flush ( )
def gen_report ( name , unit , lines , short_unit , generation , log_file , type = line_graph ) :
2011-03-20 09:58:16 +01:00
try :
os . mkdir ( output_dir )
except : pass
2012-03-11 06:35:29 +01:00
filename = os . path . join ( output_dir , ' %s _ %04d .png ' % ( name , generation ) )
thumb = os . path . join ( output_dir , ' %s _ %04d _thumb.png ' % ( name , generation ) )
2011-03-21 09:16:04 +01:00
# don't re-render a graph unless the logfile has changed
try :
dst1 = os . stat ( filename )
dst2 = os . stat ( thumb )
src = os . stat ( log_file )
if dst1 . st_mtime > src . st_mtime and dst2 . st_mtime > src . st_mtime :
sys . stdout . write ( ' . ' )
2012-03-11 06:35:29 +01:00
return None
2011-03-21 09:16:04 +01:00
except : pass
2012-03-11 06:35:29 +01:00
script = os . path . join ( output_dir , ' %s _ %04d .gnuplot ' % ( name , generation ) )
out = open ( script , ' wb ' )
2008-12-27 03:22:20 +01:00
print >> out , " set term png size 1200,700 "
2011-03-21 09:16:04 +01:00
print >> out , ' set output " %s " ' % filename
2011-03-20 19:59:16 +01:00
print >> out , ' set yrange [0:*] '
2010-01-31 22:13:52 +01:00
print >> out , " set tics nomirror "
2008-12-27 03:22:20 +01:00
print >> out , " set key box "
2012-03-11 06:35:29 +01:00
if type == histogram :
2011-09-19 00:14:51 +02:00
binwidth = 0.005 ;
print >> out , ' binwidth= %f ' % binwidth
print >> out , ' set boxwidth binwidth '
print >> out , ' bin(x,width)=width*floor(x/width) + binwidth/2 '
print >> out , ' set xrange [0: %f ] ' % ( binwidth * 100 )
print >> out , ' set xlabel " %s " ' % unit
print >> out , ' set ylabel " number " '
k = lines [ 0 ]
2011-03-17 06:31:06 +01:00
try :
column = keys . index ( k ) + 2
except :
print ' " %s " not found ' % k
2011-09-19 00:14:51 +02:00
return
print >> out , ' plot " %s " using (bin($ %d ,binwidth)):(1.0) smooth freq with boxes ' % ( log_file , column )
print >> out , ' '
print >> out , ' '
print >> out , ' '
2012-03-11 06:35:29 +01:00
elif type == stacked :
print >> out , ' set xrange [0:*] '
print >> out , ' set ylabel " %s " ' % unit
print >> out , ' set xlabel " time (s) " '
print >> out , ' set format y " %% .1s %% c %s " ; ' % short_unit
print >> out , ' set style fill solid 1.0 noborder '
print >> out , ' plot ' ,
column = 2
first = True
prev = ' '
graph = ' '
plot_expression = ' '
color = 0
for k in lines :
try :
column = keys . index ( k ) + 2
except :
print ' " %s " not found ' % k
continue ;
if not first :
plot_expression = ' , ' + plot_expression
graph + = ' + '
axis = ' x1y1 '
graph + = ' $ %d ' % column
plot_expression = ' " %s " using 1:( %s ) title " %s " axes %s with filledcurves y1=0 lc rgb " %s " ' % ( log_file , graph , k , axis , graph_colors [ color % len ( graph_colors ) ] ) + plot_expression
first = False
color + = 1
print >> out , plot_expression
2011-09-19 00:14:51 +02:00
else :
print >> out , ' set xrange [0:*] '
print >> out , ' set ylabel " %s " ' % unit
print >> out , ' set xlabel " time (s) " '
print >> out , ' set format y " %% .1s %% c %s " ; ' % short_unit
print >> out , ' plot ' ,
column = 2
first = True
2012-03-11 06:35:29 +01:00
color = 0
2011-09-19 00:14:51 +02:00
for k in lines :
try :
column = keys . index ( k ) + 2
except :
print ' " %s " not found ' % k
continue ;
if not first : print >> out , ' , ' ,
axis = ' x1y1 '
2012-03-11 06:35:29 +01:00
print >> out , ' " %s " using 1: %d title " %s " axes %s with steps lc rgb " %s " ' % ( log_file , column , k , axis , line_colors [ color % len ( line_colors ) ] ) ,
2011-09-19 00:14:51 +02:00
first = False
2012-03-11 06:35:29 +01:00
color + = 1
2011-09-19 00:14:51 +02:00
print >> out , ' '
print >> out , ' set term png size 150,100 '
2011-03-21 09:16:04 +01:00
print >> out , ' set output " %s " ' % thumb
2011-03-20 09:58:16 +01:00
print >> out , ' set key off '
print >> out , ' unset tics '
print >> out , ' set format x " " '
print >> out , ' set format y " " '
print >> out , ' set xlabel " " '
print >> out , ' set ylabel " " '
print >> out , ' set y2label " " '
2011-03-20 22:05:49 +01:00
print >> out , ' set rmargin 0 '
print >> out , ' set lmargin 0 '
print >> out , ' set tmargin 0 '
print >> out , ' set bmargin 0 '
2011-03-20 09:58:16 +01:00
print >> out , " replot "
2008-12-27 03:22:20 +01:00
out . close ( )
2012-03-11 06:35:29 +01:00
return script
2011-03-20 09:58:16 +01:00
2011-03-20 17:14:56 +01:00
def gen_html ( reports , generations ) :
2011-03-20 09:58:16 +01:00
file = open ( os . path . join ( output_dir , ' index.html ' ) , ' w+ ' )
2011-03-20 21:22:23 +01:00
css = ''' img { margin: 0}
#head { display: block }
2011-03-20 22:05:49 +01:00
#graphs { white-space:nowrap; }
2011-03-20 21:22:23 +01:00
h1 { line - height : 1 ; display : inline }
h2 { line - height : 1 ; display : inline ; font - size : 1 em ; font - weight : normal } ; '''
print >> file , ' <html><head><style type= " text/css " > %s </style></head><body> ' % css
2011-03-20 09:58:16 +01:00
for i in reports :
2011-04-26 08:27:48 +02:00
print >> file , ' <div id= " head " ><h1> %s </h1><h2> %s </h2><div><div id= " graphs " > ' % ( i [ 0 ] , i [ 3 ] )
2011-03-20 17:14:56 +01:00
for g in generations :
2012-03-11 06:35:29 +01:00
print >> file , ' <a href= " %s _ %04d .png " ><img src= " %s _ %04d _thumb.png " ></a> ' % ( i [ 0 ] , g , i [ 0 ] , g )
2011-03-20 22:05:49 +01:00
print >> file , ' </div> '
2011-03-20 09:58:16 +01:00
2011-03-20 21:22:23 +01:00
print >> file , ' </body></html> '
2011-03-20 09:58:16 +01:00
file . close ( )
reports = [
2012-03-11 06:35:29 +01:00
( ' torrents ' , ' num ' , ' ' , ' number of torrents in different torrent states ' , [ ' downloading torrents ' , ' seeding torrents ' , \
' checking torrents ' , ' stopped torrents ' , ' upload-only torrents ' , ' error torrents ' , ' queued seed torrents ' , \
' queued download torrents ' ] , stacked ) ,
2012-03-06 11:34:18 +01:00
( ' torrents_want_peers ' , ' num ' , ' ' , ' number of torrents that want more peers ' , [ ' torrents want more peers ' ] ) ,
2012-03-04 12:18:27 +01:00
( ' peers ' , ' num ' , ' ' , ' num connected peers ' , [ ' peers ' , ' connecting peers ' , ' connection attempts ' , ' banned peers ' , ' total peers ' ] ) ,
( ' peers_max ' , ' num ' , ' ' , ' num connected peers ' , [ ' peers ' , ' connecting peers ' , ' connection attempts ' , ' banned peers ' , ' max connections ' , ' total peers ' ] ) ,
( ' peer_churn ' , ' num ' , ' ' , ' connecting and disconnecting peers ' , [ ' connecting peers ' , ' connection attempts ' ] ) ,
2012-03-06 11:34:18 +01:00
( ' peer_limits ' , ' num ' , ' ' , ' number of connections per limit ' , [ ' average peers per limit ' ] ) ,
2011-04-26 08:27:48 +02:00
( ' connect_candidates ' , ' num ' , ' ' , ' number of peers we know of that we can connect to ' , [ ' connect candidates ' ] ) ,
( ' peers_list_size ' , ' num ' , ' ' , ' number of known peers (not necessarily connected) ' , [ ' num list peers ' ] ) ,
2011-06-21 09:44:13 +02:00
( ' overall_rates ' , ' rate ' , ' B/s ' , ' download and upload rates ' , [ ' uploaded bytes ' , ' downloaded bytes ' , ' upload rate ' , ' download rate ' , ' smooth upload rate ' , ' smooth download rate ' ] ) ,
2011-04-26 08:27:48 +02:00
( ' disk_write_queue ' , ' Bytes ' , ' B ' , ' bytes queued up by peers, to be written to disk ' , [ ' disk write queued bytes ' , ' disk queue limit ' , ' disk queue low watermark ' ] ) ,
2012-03-09 07:24:01 +01:00
( ' peers_requests ' , ' num ' , ' ' , ' incoming piece request rate ' , [ ' piece requests ' , ' piece rejects ' , ' max piece requests ' , ' invalid piece requests ' , ' choked piece requests ' , ' cancelled piece requests ' ] ) ,
2012-03-09 18:03:10 +01:00
( ' peers_upload ' , ' num ' , ' ' , ' number of peers by state wrt. uploading ' , [ ' peers up interested ' , ' peers up unchoked ' , ' peers up requests ' , ' peers disk-up ' , ' peers up send buffer ' , ' peers bw-up ' , ' max unchoked ' ] ) ,
2011-06-13 18:20:21 +02:00
( ' peers_download ' , ' num ' , ' ' , ' number of peers by state wrt. downloading ' , [ ' peers down interesting ' , ' peers down unchoked ' , ' peers down requests ' , ' peers disk-down ' , ' peers bw-down ' , ' num end-game peers ' ] ) ,
2012-03-02 09:52:54 +01:00
( ' peer_errors ' , ' num ' , ' ' , ' number of peers by error that disconnected them ' , [ ' error peers ' , ' peer disconnects ' , ' peers eof ' , ' peers connection reset ' , ' connect timeouts ' , ' uninteresting peers disconnect ' , ' banned for hash failure ' , ' no memory peer errors ' , ' too many peers ' , ' transport timeout peers ' , ' connection refused peers ' , ' connection aborted peers ' , ' permission denied peers ' , ' no buffer peers ' , ' host unreachable peers ' , ' broken pipe peers ' , ' address in use peers ' , ' access denied peers ' , ' invalid argument peers ' , ' operation aborted peers ' ] ) ,
( ' peer_errors_incoming ' , ' num ' , ' ' , ' number of peers by incoming or outgoing connection ' , [ ' error incoming peers ' , ' error outgoing peers ' ] ) ,
( ' peer_errors_transport ' , ' num ' , ' ' , ' number of peers by transport protocol ' , [ ' error tcp peers ' , ' error utp peers ' ] ) ,
2012-03-06 11:34:18 +01:00
( ' peer_errors_encryption ' , ' num ' , ' ' , ' number of peers by encryption level ' , [ ' error encrypted peers ' , ' error rc4 peers ' , ' peer disconnects ' ] ) ,
2012-03-05 11:05:20 +01:00
( ' incoming requests ' , ' num ' , ' ' , ' incoming 16kiB block requests ' , [ ' pending incoming block requests ' , ' average pending incoming block requests ' ] ) ,
2012-03-11 06:35:29 +01:00
( ' waste ' , ' % o f all downloaded bytes ' , ' %% ' , ' proportion of all downloaded bytes that were wasted ' , [ ' % f ailed payload bytes ' , ' % wasted payload bytes ' , ' % protocol bytes ' ] , stacked ) ,
( ' waste by source ' , ' % o f all wasted bytes ' , ' %% ' , ' what \' causing the waste ' , [ ' redundant timed-out ' , ' redundant cancelled ' , ' redundant unknown ' , ' redundant seed ' , ' redundant end-game ' , ' redundant closing ' ] , stacked ) ,
2011-06-24 05:11:39 +02:00
( ' average_disk_time_absolute ' , ' job time ' , ' s ' , ' running averages of timings of disk operations ' , [ ' disk read time ' , ' disk write time ' , ' disk hash time ' , ' disk job time ' , ' disk sort time ' ] ) ,
( ' average_disk_queue_time ' , ' job queued time ' , ' s ' , ' running averages of disk queue time ' , [ ' disk queue time ' , ' disk job time ' ] ) ,
2012-03-11 06:35:29 +01:00
( ' disk_time ' , ' % o f total disk job time ' , ' %% ' , ' proportion of time spent by the disk thread ' , [ ' % r ead time ' , ' % write time ' , ' % ha sh time ' , ' % s ort time ' ] , stacked ) ,
2011-04-26 08:27:48 +02:00
( ' disk_cache_hits ' , ' blocks (16kiB) ' , ' ' , ' ' , [ ' disk block read ' , ' read cache hits ' , ' disk block written ' , ' disk read back ' ] ) ,
2011-07-24 18:06:08 +02:00
( ' disk_cache ' , ' blocks (16kiB) ' , ' ' , ' disk cache size and usage ' , [ ' disk buffer allocations ' , ' read disk cache size ' , ' disk cache size ' , ' cache size ' ] ) ,
2011-04-27 19:36:06 +02:00
( ' disk_readback ' , ' % o f written blocks ' , ' %% ' , ' portion of written blocks that had to be read back for hash verification ' , [ ' % r ead back ' ] ) ,
2011-04-26 08:27:48 +02:00
( ' disk_queue ' , ' number of queued disk jobs ' , ' ' , ' queued disk jobs ' , [ ' disk queue size ' , ' disk read queue size ' , ' read job queue size limit ' ] ) ,
2011-07-03 19:21:45 +02:00
( ' disk_iops ' , ' operations/s ' , ' ' , ' number of disk operations per second ' , [ ' read ops/s ' , ' write ops/s ' , ' smooth read ops/s ' , ' smooth write ops/s ' ] ) ,
2011-09-23 22:57:42 +02:00
( ' disk pending reads ' , ' Bytes ' , ' ' , ' number of bytes peers are waiting for to be read from the disk ' , [ ' pending reading bytes ' ] ) ,
2011-06-21 09:44:13 +02:00
( ' mixed mode ' , ' rate ' , ' B/s ' , ' rates by transport protocol ' , [ ' TCP up rate ' , ' TCP down rate ' , ' uTP up rate ' , ' uTP down rate ' , ' TCP up limit ' , ' TCP down limit ' ] ) ,
2012-03-04 21:08:50 +01:00
( ' connection_type ' , ' num ' , ' ' , ' peers by transport protocol ' , [ ' utp peers ' , ' tcp peers ' ] ) ,
2011-09-28 02:03:12 +02:00
( ' uTP delay ' , ' buffering delay ' , ' s ' , ' network delays measured by uTP ' , [ ' uTP peak send delay ' , ' uTP peak recv delay ' , ' uTP avg send delay ' , ' uTP avg recv delay ' ] ) ,
2012-03-11 06:35:29 +01:00
( ' uTP send delay histogram ' , ' buffering delay ' , ' s ' , ' send delays measured by uTP ' , [ ' uTP avg send delay ' ] , histogram ) ,
( ' uTP recv delay histogram ' , ' buffering delay ' , ' s ' , ' receive delays measured by uTP ' , [ ' uTP avg recv delay ' ] , histogram ) ,
( ' uTP stats ' , ' num ' , ' ' , ' number of uTP sockets by state ' , [ ' uTP idle ' , ' uTP syn-sent ' , ' uTP connected ' , ' uTP fin-sent ' , ' uTP close-wait ' ] , stacked ) ,
( ' system memory ' , ' ' , ' ' , ' virtual memory page count ' , [ ' active resident pages ' , ' inactive resident pages ' , ' pinned resident pages ' , ' free pages ' ] , stacked ) ,
2011-06-29 00:20:34 +02:00
( ' memory paging ' , ' ' , ' ' , ' vm disk activity ' , [ ' pageins ' , ' pageouts ' ] ) ,
( ' page faults ' , ' ' , ' ' , ' ' , [ ' page faults ' ] ) ,
2011-10-17 19:12:08 +02:00
( ' CPU usage ' , ' % ' , ' ' , ' ' , [ ' network thread system time ' , ' network thread user+system time ' ] ) ,
2011-10-17 07:17:21 +02:00
( ' boost.asio messages ' , ' events/s ' , ' ' , ' number of messages posted per second ' , [ \
' read_counter ' , ' write_counter ' , ' tick_counter ' , ' lsd_counter ' , \
' lsd_peer_counter ' , ' udp_counter ' , ' accept_counter ' , ' disk_queue_counter ' , \
2012-03-11 06:35:29 +01:00
' disk_read_counter ' , ' disk_write_counter ' ] , stacked ) ,
( ' send_buffer_sizes ' , ' num ' , ' ' , ' ' , [ ' up 8 ' , ' up 16 ' , ' up 32 ' , ' up 64 ' , ' up 128 ' , ' up 256 ' , \
' up 512 ' , ' up 1024 ' , ' up 2048 ' , ' up 4096 ' , ' up 8192 ' , ' up 16384 ' , ' up 32768 ' , ' up 65536 ' , \
2014-01-30 10:55:11 +01:00
' up 131072 ' , ' up 262144 ' , ' up 524288 ' , ' up 1048576 ' ] , stacked ) ,
2012-03-11 06:35:29 +01:00
( ' recv_buffer_sizes ' , ' num ' , ' ' , ' ' , [ ' down 8 ' , ' down 16 ' , ' down 32 ' , ' down 64 ' , ' down 128 ' , \
' down 256 ' , ' down 512 ' , ' down 1024 ' , ' down 2048 ' , ' down 4096 ' , ' down 8192 ' , ' down 16384 ' , \
2014-01-30 10:55:11 +01:00
' down 32768 ' , ' down 65536 ' , ' down 131072 ' , ' down 262144 ' , ' down 524288 ' , ' down 1048576 ' ] , stacked ) ,
2011-03-20 09:58:16 +01:00
# ('absolute_waste', 'num', '', ['failed bytes', 'redundant bytes', 'download rate']),
2008-12-27 03:22:20 +01:00
2011-03-20 09:58:16 +01:00
#somewhat uninteresting stats
2011-06-21 09:44:13 +02:00
( ' tick_rate ' , ' time between ticks ' , ' s ' , ' ' , [ ' tick interval ' , ' tick residual ' ] ) ,
2012-03-11 06:35:29 +01:00
( ' peer_dl_rates ' , ' num ' , ' ' , ' peers split into download rate buckets ' , [ ' peers down 0 ' , ' peers down 0-2 ' , ' peers down 2-5 ' , ' peers down 5-10 ' , ' peers down 50-100 ' , ' peers down 100- ' ] , stacked ) ,
( ' peer_dl_rates2 ' , ' num ' , ' ' , ' peers split into download rate buckets (only downloading peers) ' , [ ' peers down 0-2 ' , ' peers down 2-5 ' , ' peers down 5-10 ' , ' peers down 50-100 ' , ' peers down 100- ' ] , stacked ) ,
( ' peer_ul_rates ' , ' num ' , ' ' , ' peers split into upload rate buckets ' , [ ' peers up 0 ' , ' peers up 0-2 ' , ' peers up 2-5 ' , ' peers up 5-10 ' , ' peers up 50-100 ' , ' peers up 100- ' ] , stacked ) ,
( ' peer_ul_rates2 ' , ' num ' , ' ' , ' peers split into upload rate buckets (only uploading peers) ' , [ ' peers up 0-2 ' , ' peers up 2-5 ' , ' peers up 5-10 ' , ' peers up 50-100 ' , ' peers up 100- ' ] , stacked ) ,
( ' piece_picker_end_game ' , ' blocks ' , ' ' , ' ' , [ ' end game piece picker blocks ' , ' piece picker blocks ' , \
' piece picks ' , ' reject piece picks ' , ' unchoke piece picks ' , ' incoming redundant piece picks ' , \
' incoming piece picks ' , ' end game piece picks ' , ' snubbed piece picks ' ] , stacked ) ,
( ' piece_picker ' , ' blocks ' , ' ' , ' ' , [ ' piece picks ' , ' reject piece picks ' , ' unchoke piece picks ' , ' incoming redundant piece picks ' , ' incoming piece picks ' , ' end game piece picks ' , ' snubbed piece picks ' ] , stacked ) ,
2011-03-20 09:58:16 +01:00
]
2007-09-29 18:14:03 +02:00
2011-03-20 17:14:56 +01:00
print ' generating graphs '
log_file_path , log_file = os . path . split ( sys . argv [ 1 ] )
# count the number of log files (generations)
log_file_list = log_file . split ( ' . ' )
g = int ( log_file_list [ 1 ] )
generations = [ ]
2012-03-11 06:35:29 +01:00
scripts = [ ]
2011-03-23 05:44:38 +01:00
while os . path . exists ( os . path . join ( log_file_path , log_file ) ) :
2011-03-20 17:14:56 +01:00
print ' [ %s ] %04d \r [ ' % ( ' ' * len ( reports ) , g ) ,
2011-09-19 00:14:51 +02:00
for i in reports :
2012-03-11 06:35:29 +01:00
type = line_graph
try : type = i [ 5 ]
2011-09-19 00:14:51 +02:00
except : pass
2012-03-11 06:35:29 +01:00
script = gen_report ( i [ 0 ] , i [ 1 ] , i [ 4 ] , i [ 2 ] , g , os . path . join ( log_file_path , log_file ) , type )
if script != None : scripts . append ( script )
2011-03-20 17:14:56 +01:00
generations . append ( g )
g + = 1
log_file_list [ 1 ] = ' %04d ' % g
log_file = ' . ' . join ( log_file_list )
2012-03-11 06:35:29 +01:00
# run gnuplot on all scripts, in parallel
thread_pool . map ( plot_fun , scripts )
print ' \n generating html '
2011-03-20 17:14:56 +01:00
gen_html ( reports , generations )
2012-03-11 06:35:29 +01:00