Skip to content

Commit 3079850

Browse files
author
fivemru
committed
Init commit
0 parents  commit 3079850

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed

log.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
2+
import sys
3+
import re
4+
import os
5+
import os.path
6+
import time
7+
import subprocess
8+
9+
if sys.version.startswith("3"):
10+
import io
11+
io_method = io.BytesIO
12+
else:
13+
import cStringIO
14+
io_method = cStringIO.StringIO
15+
16+
from collections import Counter
17+
18+
19+
def parse_log_lines(content, fields):
20+
tree = {}
21+
count_lines = 0
22+
start = time.time()
23+
24+
for line in content:
25+
count_lines += 1
26+
data = parse_line(line)
27+
28+
tmp = tree
29+
30+
for i, field in enumerate(fields):
31+
isLast = True if i == len(fields) - 1 else False
32+
val = ""
33+
if type(field) is list:
34+
for fi in field:
35+
val += format_value(fi, data)
36+
else:
37+
val = format_value(field, data)
38+
39+
if tmp.get(val) == None:
40+
tmp[val] = 0 if isLast else {}
41+
if isLast:
42+
tmp[val] += 1
43+
tmp = tmp[val]
44+
45+
end = time.time()
46+
return {
47+
'lines': count_lines,
48+
'tree': tree,
49+
'time': (end - start),
50+
}
51+
52+
53+
def parse_line(line):
54+
chunk = line.split()
55+
return {
56+
'ip': chunk[0],
57+
'date': chunk[3][1:12],
58+
'code': (chunk[8] if len(chunk) >= 8 else ""),
59+
'method': (chunk[5][1:] if len(chunk) >= 5 else ""),
60+
'uri': (chunk[6] if len(chunk) >= 6 else ""),
61+
'protocol': (chunk[7][:-1] if len(chunk) >= 7 else ""),
62+
'request': (chunk[5][1:]+" "+chunk[6]+" "+chunk[7][:-1] if len(chunk) >= 7 else ""),
63+
'ua': (' '.join(chunk[11:])[1:-1] if len(chunk) >= 11 else ""),
64+
'ref': (chunk[10][1:-1] if len(chunk) >= 11 else ""),
65+
}
66+
67+
68+
def field_param(field):
69+
chunk = field.split(':')
70+
return {
71+
'name': chunk[0],
72+
'format': (chunk[1] if len(chunk) > 1 else ""),
73+
}
74+
75+
76+
def norm_date(date_str):
77+
return '-'.join(
78+
reduce(
79+
lambda str, re: str.replace(
80+
re[1],
81+
'{0}'.format(re[0]).zfill(2)
82+
),
83+
enumerate(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
84+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 1),
85+
date_str.replace('\t', '')
86+
).split('/')[::-1]
87+
)
88+
89+
90+
def format_value(field, data):
91+
f_param = field_param(field)
92+
value = ('{0:' + f_param['format'] + '}').format(
93+
data[f_param['name']]
94+
)
95+
return value + "\t"
96+
97+
98+
def find_and_replace(tree, fields, field, find_name, fn):
99+
new_tree = {}
100+
col_separator = '\t'
101+
field_names = []
102+
103+
if type(field) is list:
104+
for fi in field:
105+
field_names.append(field_param(fi)['name'])
106+
else:
107+
field_names.append(field_param(field)['name'])
108+
109+
try:
110+
field_names.index(find_name)
111+
112+
for k, v in tree.items():
113+
if type(field) is list:
114+
ch = k.split(col_separator)
115+
116+
for i, name in enumerate(field_names):
117+
if name == find_name:
118+
ch[i] = fn(ch[i])
119+
120+
new_tree[col_separator.join(ch)] = v
121+
else:
122+
new_tree[fn(k)] = v
123+
124+
except Exception as err:
125+
# print("Unexpected error:", err)
126+
new_tree = tree
127+
pass
128+
129+
return new_tree
130+
131+
132+
def print_tree(tree, fields, pad="", level=0):
133+
134+
tree = find_and_replace(tree, fields, fields[level], 'date',
135+
lambda value: norm_date(value))
136+
sum = 0
137+
for item in sorted(tree):
138+
val = tree[item]
139+
if type(val) is dict:
140+
print(pad + item)
141+
sum += print_tree(val, fields, pad + "\t", level + 1)
142+
else:
143+
print(pad + str(val) + "\t" + item)
144+
sum += val
145+
print("---sum=" + str(sum))
146+
return sum
147+
148+
149+
def print_report(files, fields, filters=[]):
150+
print('=== Report fields : ', fields, ' ===')
151+
152+
p = subprocess.Popen((["cat"] + files), stdout=subprocess.PIPE)
153+
content = io_method(p.communicate()[0])
154+
assert p.returncode == 0
155+
156+
res = parse_log_lines(content, fields)
157+
print("Number of lines: " + str(res['lines']))
158+
print("Time: " + str(res['time']) + "\n")
159+
print_tree(res['tree'], fields)
160+
print
161+
content.close()
162+
163+
164+
if __name__ == '__main__':
165+
print("Hello! This is simple Apache log analyzer\n")
166+
167+
files = []
168+
for filename in sys.argv[1:]:
169+
if os.path.isfile(filename):
170+
files.append(filename)
171+
172+
if len(files) == 0:
173+
print("Files not found: ", ("\n\t".join(sys.argv[1])))
174+
sys.exit(1)
175+
176+
print("Files (" + str(len(files)) + "): \n" + ("\t".join(files)) + "\n\n")
177+
178+
sys.stdout.flush()
179+
180+
# print_report(files, ['code'])
181+
# print_report(files, ['date'])
182+
# print_report(files, ['ip'])
183+
# print_report(files, ['method'])
184+
# print_report(files, ['request'])
185+
print_report(files, ['method', 'uri'])
186+
187+
# {
188+
# 'WP vulm':
189+
# }
190+
191+
# print_report(files, ['ip', 'ua', ['uri', 'ref']])
192+
# print_report(files, ['ip', 'date', 'ua', ['uri', 'ref']])
193+
# print_report(files, ['ip', 'code'])
194+
# print_report(files, ['date', ['ip:16', 'ua']])
195+
# print_report(files, ['ip:16', ['date', 'ua']])
196+
# print_report(files, ['ip:16', ['date', 'ua']])
197+
# print_report(files, ['date', 'request'])

0 commit comments

Comments
 (0)