blob: 28b1d8bdfd9bc8c8bd59d20cbaf24ee0b16b9811 [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossum4e8aef81994-01-07 10:53:41 +00002
3# Extract statistics from ftp daemon log.
4
5# Usage:
6# ftpstats [-m maxitems] [-s search] [file]
7# -m maxitems: restrict number of items in "top-N" lists, default 25.
8# -s string: restrict statistics to lines containing this string.
9# Default file is /usr/adm/ftpd; a "-" means read stdandard input.
10
11# The script must be run on the host where the ftp daemon runs.
12# (At CWI this is currently buizerd.)
13
14import os
15import sys
16import regex
17import string
18import getopt
19
20pat = '^\([a-zA-Z0-9 :]*\)!\(.*\)!\(.*\)!\([<>].*\)!\([0-9]+\)!\([0-9]+\)$'
21prog = regex.compile(pat)
22
23def main():
24 maxitems = 25
25 search = None
26 try:
27 opts, args = getopt.getopt(sys.argv[1:], 'm:s:')
28 except getopt.error, msg:
29 print msg
30 print 'usage: ftpstats [-m maxitems] [file]'
31 sys.exit(2)
32 for o, a in opts:
33 if o == '-m':
34 maxitems = string.atoi(a)
35 if o == '-s':
36 search = a
37 file = '/usr/adm/ftpd'
38 if args: file = args[0]
39 if file == '-':
40 f = sys.stdin
41 else:
42 try:
43 f = open(file, 'r')
44 except IOError, msg:
45 print file, ':', msg
46 sys.exit(1)
47 bydate = {}
48 bytime = {}
49 byfile = {}
50 bydir = {}
51 byhost = {}
52 byuser = {}
53 bytype = {}
54 lineno = 0
55 try:
Guido van Rossum4e8aef81994-01-07 10:53:41 +000056 while 1:
Guido van Rossum4117e541998-09-14 16:44:15 +000057 line = f.readline()
58 if not line: break
59 lineno = lineno + 1
60 if search and string.find(line, search) < 0:
61 continue
62 if prog.match(line) < 0:
63 print 'Bad line', lineno, ':', `line`
64 continue
65 items = prog.group(1, 2, 3, 4, 5, 6)
66 (logtime, loguser, loghost, logfile, logbytes,
67 logxxx2) = items
68## print logtime
69## print '-->', loguser
70## print '--> -->', loghost
71## print '--> --> -->', logfile
72## print '--> --> --> -->', logbytes
73## print '--> --> --> --> -->', logxxx2
74## for i in logtime, loghost, logbytes, logxxx2:
75## if '!' in i: print '???', i
76 add(bydate, logtime[-4:] + ' ' + logtime[:6], items)
77 add(bytime, logtime[7:9] + ':00-59', items)
78 direction, logfile = logfile[0], logfile[1:]
79 # The real path probably starts at the last //...
80 while 1:
81 i = string.find(logfile, '//')
82 if i < 0: break
83 logfile = logfile[i+1:]
84 add(byfile, logfile + ' ' + direction, items)
85 logdir = os.path.dirname(logfile)
Guido van Rossum4e8aef81994-01-07 10:53:41 +000086## logdir = os.path.normpath(logdir) + '/.'
Guido van Rossum4117e541998-09-14 16:44:15 +000087 while 1:
88 add(bydir, logdir + ' ' + direction, items)
89 dirhead = os.path.dirname(logdir)
90 if dirhead == logdir: break
91 logdir = dirhead
92 add(byhost, loghost, items)
93 add(byuser, loguser, items)
94 add(bytype, direction, items)
Guido van Rossum4e8aef81994-01-07 10:53:41 +000095 except KeyboardInterrupt:
96 print 'Interrupted at line', lineno
97 show(bytype, 'by transfer direction', maxitems)
98 show(bydir, 'by directory', maxitems)
99 show(byfile, 'by file', maxitems)
100 show(byhost, 'by host', maxitems)
101 show(byuser, 'by user', maxitems)
102 showbar(bydate, 'by date')
103 showbar(bytime, 'by time of day')
104
105def showbar(dict, title):
106 n = len(title)
107 print '='*((70-n)/2), title, '='*((71-n)/2)
108 list = []
109 keys = dict.keys()
110 keys.sort()
111 for key in keys:
112 n = len(str(key))
113 list.append((len(dict[key]), key))
114 maxkeylength = 0
115 maxcount = 0
116 for count, key in list:
117 maxkeylength = max(maxkeylength, len(key))
118 maxcount = max(maxcount, count)
119 maxbarlength = 72 - maxkeylength - 7
120 for count, key in list:
121 barlength = int(round(maxbarlength*float(count)/maxcount))
122 bar = '*'*barlength
123 print '%5d %-*s %s' % (count, maxkeylength, key, bar)
124
125def show(dict, title, maxitems):
126 if len(dict) > maxitems:
127 title = title + ' (first %d)'%maxitems
128 n = len(title)
129 print '='*((70-n)/2), title, '='*((71-n)/2)
130 list = []
131 keys = dict.keys()
132 for key in keys:
133 list.append((-len(dict[key]), key))
134 list.sort()
135 for count, key in list[:maxitems]:
136 print '%5d %s' % (-count, key)
137
138def add(dict, key, item):
139 if dict.has_key(key):
140 dict[key].append(item)
141 else:
142 dict[key] = [item]
143
144main()