Все задачи

HTTP 200 OK

18 Jul 2013

Администратор захотел подсчитать статистику по access-логу своего веб-сервера (Apache). Статистика: сколько запросов обработаны с тем или иным http-статусом, и сколько байт суммарно было отдано с каждым статусом.

Пример лога:

> head access.log
192.168.0.113 - - [08/Feb/2009:13:10:41 +0300] "GET /Books?v=td3 HTTP/1.1" 200 15600
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "POST /Login HTTP/1.1" 302 182
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /HomePage?cache=517 HTTP/1.1" 200 12987
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/role.gif HTTP/1.1" 200 84
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/key.gif HTTP/1.1" 200 94
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/bookmark.gif HTTP/1.1" 200 144
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/tabr1del.gif HTTP/1.1" 200 572
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/del.gif HTTP/1.1" 200 600
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/tabl1del.gif HTTP/1.1" 200 357
192.168.0.113 - - [08/Feb/2009:13:14:32 +0300] "GET /themes/my_tabs/icons/tabbgdel.gif HTTP/1.1" 200 152

Программа:

#!/usr/bin/perl

my %stat;
while(<>){ 
    /^.*(\d+) (\d+)$/;
    $stat{$1}->{count}++;
    $stat{$1}->{bytes} += $2;
}
print "$_: $stat{$_}->{count}, $stat{$_}->{bytes} bytes\n" for sort keys %stat;

Все хорошо? Конечно, нет!

Подсказка

Показать

Вывод программы оказался примерно таким:

0: 9, 30590 bytes
2: 1, 182 bytes

Подсказка-2

Показать

А хотелось-то примерно такого:

200: 9, 30590 bytes
302: 1, 182 bytes

Разоблачение

Показать

Квантификатор * – жадный, поэтому в регулярном выражении ^.*(\d+) (\d+)$ в .* попадает как можно более длинная строка, в том числе и первые цифры из http-статуса.

Кстати, регулярное выражение ^.*(\d+) (\d+)$ даст осечку еще и на 304-ых статусах:
192.168.0.114 - - [08/Feb/2009:13:06:08 +0300] "GET /something HTTP/1.1" 304 -