如何加速此 Apache 日志解析?
How to speed up this Apache log parsing?
我正在解析大型 Apache 日志,例如:
example.com:80 1.2.3.4 - - [01/Jul/2021:06:12:12 +0000] "GET /test/example/index.php?a=b&c=d HTTP/1.1" 302 486 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.3945.117 Safari/537.36"
与:
import apache_log_parser, shlex
parser = apache_log_parser.make_parser("%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"")
with open("access.log") as f:
for l in enumerate(f):
x = parser(l)
每条线需要 ~0.1 毫秒(i5 笔记本电脑)/~0.9 毫秒(低端 Atom CPU N2800 1.86GHz)
这相当慢:每行将近一毫秒!
所以我决定用 shlex
进行自己的解析(这很好地处理了诸如 first "second block" "third block" fourth
之类的引号)。
更糟!我得到,每行,~0.3 ms(i5 笔记本电脑)/~1.6ms 低端服务器
with open("access.log") as f:
for l in enumerate(f):
x = shlex.split(l)
问题:哪种更快的方法(可能使用直接正则表达式?)可以允许解析此类日志?我只需要 server port ip datetime url status bytes referer useragent
。
我终于找到了一个可以将速度提高 10 倍的解决方案:纯正则表达式。
import re
r = re.compile(r'(?P<server>.*?):(?P<port>.*?) (?P<ip>.*?) (?P<remote_log_name>.*?) (?P<userid>.*?) \[(?P<date>.*?)\] \"(?P<request>.*?)\" (?P<status>.*?) (?P<length>.*?) \"(?P<referer>.*?)\" \"(?P<useragent>.*?)\"')
with open("access.log") as f:
for l in enumerate(f):
d = next(r.finditer(l)).groupdict()
d['url'] = d['request'].split()[1] if ' ' in d['request'] else '-'
# d['date'] = datetime.datetime.strptime(d['date'], '%d/%b/%Y:%H:%M:%S %z').isoformat() # optional
~ 在我的 i5 笔记本电脑上每行 0.01 毫秒。
我正在解析大型 Apache 日志,例如:
example.com:80 1.2.3.4 - - [01/Jul/2021:06:12:12 +0000] "GET /test/example/index.php?a=b&c=d HTTP/1.1" 302 486 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.3945.117 Safari/537.36"
与:
import apache_log_parser, shlex
parser = apache_log_parser.make_parser("%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"")
with open("access.log") as f:
for l in enumerate(f):
x = parser(l)
每条线需要 ~0.1 毫秒(i5 笔记本电脑)/~0.9 毫秒(低端 Atom CPU N2800 1.86GHz)
这相当慢:每行将近一毫秒!所以我决定用
shlex
进行自己的解析(这很好地处理了诸如first "second block" "third block" fourth
之类的引号)。
更糟!我得到,每行,~0.3 ms(i5 笔记本电脑)/~1.6ms 低端服务器with open("access.log") as f: for l in enumerate(f): x = shlex.split(l)
问题:哪种更快的方法(可能使用直接正则表达式?)可以允许解析此类日志?我只需要
server port ip datetime url status bytes referer useragent
。
我终于找到了一个可以将速度提高 10 倍的解决方案:纯正则表达式。
import re
r = re.compile(r'(?P<server>.*?):(?P<port>.*?) (?P<ip>.*?) (?P<remote_log_name>.*?) (?P<userid>.*?) \[(?P<date>.*?)\] \"(?P<request>.*?)\" (?P<status>.*?) (?P<length>.*?) \"(?P<referer>.*?)\" \"(?P<useragent>.*?)\"')
with open("access.log") as f:
for l in enumerate(f):
d = next(r.finditer(l)).groupdict()
d['url'] = d['request'].split()[1] if ' ' in d['request'] else '-'
# d['date'] = datetime.datetime.strptime(d['date'], '%d/%b/%Y:%H:%M:%S %z').isoformat() # optional
~ 在我的 i5 笔记本电脑上每行 0.01 毫秒。