Commit 7611b0c2 authored by Andreas Jung's avatar Andreas Jung

added new "timed" report statistics to measure number of requests

and number of requests per time unit for a given date range.
parent 7d4a0e24
#!/usr/bin/env python #!/usr/bin/env python2.1
############################################################################## ##############################################################################
# #
# Zope Public License (ZPL) Version 1.0 # Zope Public License (ZPL) Version 1.0
...@@ -86,7 +87,7 @@ ...@@ -86,7 +87,7 @@
""" Request log profiler script """ """ Request log profiler script """
__version__='$Revision: 1.7 $'[11:-2] __version__='$Revision: 1.8 $'[11:-2]
import string, sys, time, getopt, tempfile import string, sys, time, getopt, tempfile
...@@ -290,14 +291,18 @@ def parsebigmlogline(line): ...@@ -290,14 +291,18 @@ def parsebigmlogline(line):
else: else:
return None return None
def analyze(f, top, sortf, start=None, end=None, mode='cumulative'): def analyze(f, top, sortf, start=None, end=None, mode='cumulative', resolution='10'):
beginrequests = {} beginrequests = {}
cumulative = {} cumulative = {}
finished = [] finished = []
unfinished = {} unfinished = {}
if verbose:
print "reading logfile"
while 1: while 1:
line = f.readline() line = f.readline()
if not line: if not line:
break break
line = string.strip(line) line = string.strip(line)
...@@ -320,6 +325,9 @@ def analyze(f, top, sortf, start=None, end=None, mode='cumulative'): ...@@ -320,6 +325,9 @@ def analyze(f, top, sortf, start=None, end=None, mode='cumulative'):
del unfinished[id] del unfinished[id]
finished.append(request) finished.append(request)
request.active = len(unfinished) request.active = len(unfinished)
if verbose:
print "reading logfile finished"
finished.extend(unfinished.values()) finished.extend(unfinished.values())
requests = finished requests = finished
...@@ -339,11 +347,19 @@ def analyze(f, top, sortf, start=None, end=None, mode='cumulative'): ...@@ -339,11 +347,19 @@ def analyze(f, top, sortf, start=None, end=None, mode='cumulative'):
dict = cumulative dict = cumulative
elif mode == 'detailed': elif mode == 'detailed':
dict = requests dict = requests
elif mode == 'timed':
dict = requests
else: else:
raise "Invalid mode." raise "Invalid mode."
dict.sort(sortf) if mode=='timed':
write(dict, top) timeDict = {}
timesort(timeDict,requests)
timewrite(timeDict,start,end,resolution)
else:
dict.sort(sortf)
write(dict, top)
def write(requests, top=0): def write(requests, top=0):
if len(requests) == 0: if len(requests) == 0:
...@@ -370,6 +386,55 @@ def getdate(val): ...@@ -370,6 +386,55 @@ def getdate(val):
return t return t
except: except:
raise ProfileException, "bad date %s" % val raise ProfileException, "bad date %s" % val
def timesort(dict,requests):
for r in requests:
if not r.t_end: r.t_end=r.start
for t in range(r.start,r.t_end+1):
if not dict.has_key(t):
dict[t] = 0
dict[t]+=1
def timewrite(dict,start,end,resolution):
max_requests = 0
print "Start: %s End: %s Resolution: %d secs" % \
(tick2str(start),tick2str(end),resolution)
print "-" * 78
print
print "Date/Time #requests requests/second"
for t in range(start,end,resolution):
s = tick2str(t)
num = 0
for tick in range(t,t+resolution):
if dict.has_key(tick):
num = num + dict[tick]
if num>max_requests: max_requests = num
s = s + " %6d %4.2lf" % (num,num*1.0/resolution)
print s
print '='*78
print "Peak: %6d %4.2lf" % \
(max_requests,max_requests*1.0/resolution)
def tick2str(t):
return time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(t))
def codesort(v1, v2): def codesort(v1, v2):
v1 = v1.endstage() v1 = v1.endstage()
...@@ -411,7 +476,7 @@ def detailedusage(): ...@@ -411,7 +476,7 @@ def detailedusage():
details = usage(0) details = usage(0)
pname = sys.argv[0] pname = sys.argv[0]
details = details + """ details = details + """
Reports are of two types: cumulative or detailed. The default is cumulative. Reports are of three types: cumulative,detailed or timed. The default is cumulative.
Data is taken from the Zope detailed request log (the -M log). Data is taken from the Zope detailed request log (the -M log).
For cumulative reports, each line in the profile indicates information For cumulative reports, each line in the profile indicates information
...@@ -420,6 +485,9 @@ about a Zope method (URL) collected via the detailed request log (the -M log). ...@@ -420,6 +485,9 @@ about a Zope method (URL) collected via the detailed request log (the -M log).
For detailed reports, each line in the profile indicates information about For detailed reports, each line in the profile indicates information about
a single request. a single request.
For timed reports, each line in the profile indicates informations about
the number of requests and the number of requests/second for a period of time.
'filename' is the path to the '-M' log that contains detailed request data. 'filename' is the path to the '-M' log that contains detailed request data.
If a 'sort' value is specified, sort the profile info by the spec. The sort If a 'sort' value is specified, sort the profile info by the spec. The sort
...@@ -453,6 +521,8 @@ For detailed (non-cumulative) reports, the following sort specs are accepted: ...@@ -453,6 +521,8 @@ For detailed (non-cumulative) reports, the following sort specs are accepted:
NOTE: 'active' count may be fooled by Zope restarts, which aren't NOTE: 'active' count may be fooled by Zope restarts, which aren't
reflected in the -M log. reflected in the -M log.
For timed reports there are no sort specs allowed.
If the 'top' argument is specified, only report on the top 'n' entries in If the 'top' argument is specified, only report on the top 'n' entries in
the profile (as per the sort). The default is to show all data in the profile. the profile (as per the sort). The default is to show all data in the profile.
...@@ -460,10 +530,14 @@ If the 'verbose' argument is specified, do not trim url to fit into 80 cols. ...@@ -460,10 +530,14 @@ If the 'verbose' argument is specified, do not trim url to fit into 80 cols.
If the 'today' argument is specified, limit results to hits received today. If the 'today' argument is specified, limit results to hits received today.
If the 'start' argument is specified in the form 'YYYY/MM/DD HH:MM:SS' (UTC), The 'resolution' argument is used only for timed reports and specifies the
number of seconds between consecutive lines in the report
(default is 60 seconds).
If the 'start' argument is specified in the form 'DD/MM/YYYY HH:MM:SS' (UTC),
limit results to hits received after this date/time. limit results to hits received after this date/time.
If the 'end' argument is specified in the form 'YYYY/MM/DD HH:MM:SS' (UTC), If the 'end' argument is specified in the form 'DD/MM/YYYY HH:MM:SS' (UTC),
limit results to hits received before this date/time. limit results to hits received before this date/time.
Examples: Examples:
...@@ -485,6 +559,12 @@ Examples: ...@@ -485,6 +559,12 @@ Examples:
%(pname)s debug.log --detailed --start='2001/05/10 06:00:00' %(pname)s debug.log --detailed --start='2001/05/10 06:00:00'
--end='2001/05/11 23:00:00' --end='2001/05/11 23:00:00'
Show timed report statistics for entries in the log for one day
with a resolution of 5 minutes
%(pname)s debug.log --times --resolution=300 --start='2001/05/10 06:00:00'
--end='2001/05/11 23:00:00'
Show detailed report statistics for entries in 'debug.log' which Show detailed report statistics for entries in 'debug.log' which
begin after 6am UTC on May 10, 2001 and which end before begin after 6am UTC on May 10, 2001 and which end before
11pm UTC on May 11, 2001. 11pm UTC on May 11, 2001.
...@@ -498,11 +578,13 @@ Examples: ...@@ -498,11 +578,13 @@ Examples:
def usage(basic=1): def usage(basic=1):
usage = ( usage = (
""" """
Usage: %s filename [--cumulative|--detailed] Usage: %s filename [--cumulative|--detailed|--timed]
[--sort=spec] [--sort=spec]
[--top==n] [--top==n]
[--verbose] [--verbose]
[ --today | [--start=date] [--end=date] ] [--today | [--start=date] [--end=date] ]
[--resolution=seconds]
[--help] [--help]
Provides a profile of the detailed (-M) Zope request log. Provides a profile of the detailed (-M) Zope request log.
...@@ -526,11 +608,12 @@ if __name__ == '__main__': ...@@ -526,11 +608,12 @@ if __name__ == '__main__':
verbose = 0 verbose = 0
start = None start = None
end = None end = None
resolution=10
try: try:
opts, extra = getopt.getopt( opts, extra = getopt.getopt(
sys.argv[2:], '', ['sort=', 'top=', 'help', 'verbose', 'today', sys.argv[2:], '', ['sort=', 'top=', 'help', 'verbose', 'today',
'cumulative', 'detailed', 'start=', 'cumulative', 'detailed', 'timed','start=',
'end='] 'end=','resolution=']
) )
for opt, val in opts: for opt, val in opts:
if opt=='--sort': sortby = val if opt=='--sort': sortby = val
...@@ -538,6 +621,9 @@ if __name__ == '__main__': ...@@ -538,6 +621,9 @@ if __name__ == '__main__':
if opt=='--help': print detailedusage(); sys.exit(0) if opt=='--help': print detailedusage(); sys.exit(0)
if opt=='--verbose': if opt=='--verbose':
verbose = 1 verbose = 1
if opt=='--resolution':
resolution=int(val)
if opt=='--today': if opt=='--today':
now = time.gmtime(time.time()) now = time.gmtime(time.time())
# for testing - now = (2001, 04, 19, 0, 0, 0, 0, 0, -1) # for testing - now = (2001, 04, 19, 0, 0, 0, 0, 0, -1)
...@@ -556,6 +642,9 @@ if __name__ == '__main__': ...@@ -556,6 +642,9 @@ if __name__ == '__main__':
d_sortby = sortby d_sortby = sortby
if opt=='--cumulative': if opt=='--cumulative':
mode='cumulative' mode='cumulative'
if opt=='--timed':
mode='timed'
validcumsorts = ['url', 'hits', 'hangs', 'max', 'min', 'median', validcumsorts = ['url', 'hits', 'hangs', 'max', 'min', 'median',
'mean', 'total'] 'mean', 'total']
...@@ -579,10 +668,13 @@ if __name__ == '__main__': ...@@ -579,10 +668,13 @@ if __name__ == '__main__':
sortf = codesort sortf = codesort
else: else:
sortf = Sort(sortby) sortf = Sort(sortby)
elif mode=='timed':
sortf = timesort
else: else:
raise 'Invalid mode' raise 'Invalid mode'
analyze(open(sys.argv[1]), top, sortf, start, end, mode) analyze(open(sys.argv[1]), top, sortf, start, end, mode, resolution)
except AssertionError, val: except AssertionError, val:
a = "%s is not a valid %s sort spec, use one of %s" a = "%s is not a valid %s sort spec, use one of %s"
......
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