#!/usr/bin/perl # # Based on loganalyzer (Sergey N. Yatskevich ) # # Обработка лога Squid'а и запись результатов в таблицу proxy_log # # При обработке лога извлекается следующая информация : # 1) время (с детализацией по дням) обращения # 2) машина, с которой произошло обращение # 3) хост, к которому произошло обращение (только доменное имя) # 4) метод обращения (GET или POST) # 5) Взят-ли объект из кэша или произошла его загрузка из сети # 6) объем загруженной информации # # Интересует "объем информации"/"количество обращений" в разрезе # 1, 2, 3, 4 # use URI; use DBI; $dsn = "dbi:InterBase:dbname=billing;host=firebird;ib_dialect=3"; $user = "sysdba"; $passwd = "system"; sub parseLogLine { ($time, $duration, $client_address, $result_codes, $bytes, $request_method, $url, $rfc931, $hierarhy_code, $type) = split (/\s+/); # Пропускаем сообщения об ошибках выдаваемых Squid пользователям # и запросы к самому Squid'у if ($result_codes =~ /^NONE/ || $url =~ /^cache_object:/) { return ("SKIP_LINE", "", "", "", "", 0, 0); } # Squid не проставляет при типе соединения CONNECT (по крайней # мере для ICQ) используемый протокол, что вызывает ошибку # в пакете URI. Поэтому добавляем протокол сами. if ($request_method eq "CONNECT" && $url !~ /^https:/i) { $url = "https://$url"; } $uri = URI->new ($url); $uri = $uri->canonical; $host = $uri->host; ($day, $month, $year) = (localtime ($time)) [3, 4, 5]; $month++; $year += 1900; $hit = ($result_codes =~ /_HIT/) ? 1 : 0; return ("INSERT", "$year/$month/$day", $client_address, lc $host, $request_method, $hit, $bytes); } while () { ($state, $date, $client_address, $host, $request_method, $hit, $bytes) = parseLogLine ($_); if ($state eq "INSERT") { $total_count{"$date $client_address $host $request_method"} ++; $total_bytes{"$date $client_address $host $request_method"} += $bytes; if ($hit == 1) { $hit_count{"$date $client_address $host $request_method"} ++; $hit_bytes{"$date $client_address $host $request_method"} += $bytes; } } } $dbh = DBI->connect ($dsn, $user, $passwd, {AutoCommit => 0}); $sth = $dbh->prepare ("INSERT INTO proxy_log VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); foreach $key (keys %total_count) { if ($total_bytes{$key} > 0) { ($date, $client_address, $host, $request_method) = split (/ /, $key); ($hcount, $hbytes) = (exists $hit_count{$key}) ? ($hit_count{$key}, $hit_bytes{$key}) : (0, 0); $sth->execute ($date, $client_address, $host, $request_method, $total_count{$key}, $total_bytes{$key}, $hcount, $hbytes); if ($sth->state) { $dbh->rollback; $dbh->disconnect; die "Ошибка вставки записи, откат в начальное состояние\n"; } } } $dbh->commit; $dbh->disconnect;