[Zope-Checkins] CVS: Zope/utilities - requestprofiler.py:1.8
Andreas Jung
andreas@zope.com
Mon, 17 Sep 2001 12:58:40 -0400
Update of /cvs-repository/Zope/utilities
In directory cvs.zope.org:/tmp/cvs-serv23786
Modified Files:
requestprofiler.py
Log Message:
added new "timed" report statistics to measure number of requests
and number of requests per time unit for a given date range.
=== Zope/utilities/requestprofiler.py 1.7 => 1.8 ===
+#!/usr/bin/env python2.1
+
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
@@ -290,14 +291,18 @@
else:
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 = {}
cumulative = {}
finished = []
unfinished = {}
-
+
+ if verbose:
+ print "reading logfile"
+
while 1:
line = f.readline()
+
if not line:
break
line = string.strip(line)
@@ -320,6 +325,9 @@
del unfinished[id]
finished.append(request)
request.active = len(unfinished)
+
+ if verbose:
+ print "reading logfile finished"
finished.extend(unfinished.values())
requests = finished
@@ -339,11 +347,19 @@
dict = cumulative
elif mode == 'detailed':
dict = requests
+ elif mode == 'timed':
+ dict = requests
else:
raise "Invalid mode."
- dict.sort(sortf)
- write(dict, top)
+ if mode=='timed':
+ timeDict = {}
+ timesort(timeDict,requests)
+ timewrite(timeDict,start,end,resolution)
+
+ else:
+ dict.sort(sortf)
+ write(dict, top)
def write(requests, top=0):
if len(requests) == 0:
@@ -370,6 +386,55 @@
return t
except:
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):
v1 = v1.endstage()
@@ -411,7 +476,7 @@
details = usage(0)
pname = sys.argv[0]
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).
For cumulative reports, each line in the profile indicates information
@@ -420,6 +485,9 @@
For detailed reports, each line in the profile indicates information about
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.
If a 'sort' value is specified, sort the profile info by the spec. The sort
@@ -453,6 +521,8 @@
NOTE: 'active' count may be fooled by Zope restarts, which aren't
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
the profile (as per the sort). The default is to show all data in the profile.
@@ -460,10 +530,14 @@
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.
-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.
Examples:
@@ -485,6 +559,12 @@
%(pname)s debug.log --detailed --start='2001/05/10 06: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
begin after 6am UTC on May 10, 2001 and which end before
11pm UTC on May 11, 2001.
@@ -498,11 +578,13 @@
def usage(basic=1):
usage = (
"""
-Usage: %s filename [--cumulative|--detailed]
+Usage: %s filename [--cumulative|--detailed|--timed]
+
[--sort=spec]
[--top==n]
[--verbose]
- [ --today | [--start=date] [--end=date] ]
+ [--today | [--start=date] [--end=date] ]
+ [--resolution=seconds]
[--help]
Provides a profile of the detailed (-M) Zope request log.
@@ -526,11 +608,12 @@
verbose = 0
start = None
end = None
+ resolution=10
try:
opts, extra = getopt.getopt(
sys.argv[2:], '', ['sort=', 'top=', 'help', 'verbose', 'today',
- 'cumulative', 'detailed', 'start=',
- 'end=']
+ 'cumulative', 'detailed', 'timed','start=',
+ 'end=','resolution=']
)
for opt, val in opts:
if opt=='--sort': sortby = val
@@ -538,6 +621,9 @@
if opt=='--help': print detailedusage(); sys.exit(0)
if opt=='--verbose':
verbose = 1
+
+ if opt=='--resolution':
+ resolution=int(val)
if opt=='--today':
now = time.gmtime(time.time())
# for testing - now = (2001, 04, 19, 0, 0, 0, 0, 0, -1)
@@ -556,6 +642,9 @@
d_sortby = sortby
if opt=='--cumulative':
mode='cumulative'
+ if opt=='--timed':
+ mode='timed'
+
validcumsorts = ['url', 'hits', 'hangs', 'max', 'min', 'median',
'mean', 'total']
@@ -579,10 +668,13 @@
sortf = codesort
else:
sortf = Sort(sortby)
+
+ elif mode=='timed':
+ sortf = timesort
else:
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:
a = "%s is not a valid %s sort spec, use one of %s"