| Составление отчета на основе файлов журналов Apache |
|
В настоящее время доля веб-сервера Apache составляет примерно 50 процентов от всех веб-серверов в Интернете. Цель следующего примера состоит в том, чтобы показать вам способ составления отчетов на основе файлов журналов веб-сервера Apache. В этом примере рассматривается только часть информации, доступной в файлах журналов Apache, но вы можете использовать описываемый подход для извлечения любых данных, содержащихся в этих файлах журналов. Данный подход можно легко адаптировать для работы с огромными файлами данных и для работы с большим числом данных. Уже приводилось несколько примеров анализа файлов журналов веб-сервера Apache, из которых извлекалась некоторая информация. В этом примере мы повторно воспользуемся модулями, чтобы продемонстрировать, как создавать удобочитаемые отчеты из одного или более файлов журналов. Помимо обработки всех файлов журналов, список которых определяется отдельно, вы можете указать этому сценарию, что он должен объединить файлы журналов и создать единый отчет. Исходный текст сценарий приводится в примере 14.2. Пример 14.2. Объединенный отчет на основе файлов журналов веб-сервера Apache
В самом начале сценария определяются две функции: open_files() и combine_lines(). Позднее обе эти функции будут использоваться в генераторах для упрощения программного кода. Функция open_files() -это функция-rенератор, которая принимает список (в действительности - любой итерируемый объект) имен файлов. Для каждого имени файла она создает кортеж из имени файла и соответствующего ему объекта открытого файла. Функция combine_lines() принимает итерируемые объекты открытых файлов в виде единственного аргумента. Она выполняет обход объектов файлов в цикле for. Для каждого файла выполняется обход строк в этом файле. И на каждой итерации она -с помощью инструкции yield - возвращает очередную строку. Итерируемый объект, получаемый от функции combine_lines(), можно сравнить с файлом: мы можем вbinолнять обход строк в этом объекте. Затем с помощью модуля optparse выполняется разбор аргументов командной строки, полученных от пользователя. Мы будем принимать только два аргумента, оба - логического типа: признак объединения файлов журналов и признак необходимости использовать библиотеку регулярных выражений. Параметр consolidate сообщает сценарию, что все файлы должны быть объединены при составлении отчета. Если сценарию передается этот параметр, мы, в некотором смысле, вbinолняем конкатенацию содержимого файлов. Но к этому мы еще вернемся. Параметр regex сообщает сценарию, что вместо библиотеки «split» следует использовать библиотеку регулярных выражений. Обе они предлагают идентичные функциональные возможности, но библиотека «split» работает быстрее. Затем проверяется, был ли указан параметр regex. Если параметр был указан, то импортируется модуль apache_log_parser_regex. В противном случае используется модуль apache_log_parser_split. В действительности мы включили этот параметр, чтобы сравнить производительность двух библиотек. О производительности этого сценария мы поговорим немного позже. Затем вызывается функция open_files(), которой передается список имен файлов, полученный от пользователя. Как мы уже упоминали, функция open_files() - это функция-rенератор, которая возвращает объект файла для каждого имени во входном списке. Это означает, что каждый файл открывается фактически, только когда функция возвращает соответствующий объект. Теперь, когда у нас имеется итерируемый объект с открытыми файлами, мы можем вbinолнять с ним некоторые операции. Мы можем выполнить обход всех файлов и составить отчет по каждому из них или объединить их некоторым способом и составить объединенный отчет сразу по всем файлам. Это как раз то место, где на сцену выходит функция combine_lines(). Если пользователь передал ключ «consolidate», то «список файлов», по которому будут вbinолняться итерации, будет содержать единственный объект, подобный файлу: генератор всех строк во всех файлах. Далее, независимо от того, настоящие файлы содержатся в списке или комбинированный файл, каждый из них передается соответствующей функции generate_log_report(), которая возвращает словарь с IP-адресами и количеством байтов, отправленных по этим адресам. Для каждого файла выводятся строки-разделители и отформатированные строки с результатами работы функции generate_log_report(). Ниже приводится вывод, полученный в результате обработки одного файла журнала размером 28 Кбайт:
Вывод, полученный в результате обработки трех файлов журналов (фактически это три копии одного и того же файла, созданные путем многократного копирования данных из оригинального файла), выглядит, как показано ниже:
А ниже приводится объединенный отчет для всех трех файлов:
Ниже приводятся результаты тестирования:
Итак, какова же производительность этого сценария? И каково потребление памяти? Все тесты, которые приводятся в этом разделе, вbinолнялись на сервере Ubuntu Gutsy, с процессором Athlon 64 Х2 5400+ 2.8 ГГц, с объемом ОЗУ 2 Гбайта и с жестким диском Seagate ьarracuda 7200 RPM SATA. Размер файла журнала составлял примерно 1 Гбайт:
При использовании библиотеки, вbinолняющей извлечение данных с помощью регулярных выражений, на создание отчета ушло порядка 46 секунд. При использовании версии, использующей метод string. split(), на создание отчета ушло 34 секунды. Но показатели потребления памяти оказались плачевными. Объем занятой памяти достиг 130 Мбайт. Причина в том, что функция generate_log_report() сохраняет список переданных байтов для каждого IP-адреса в файле журнала. Поэтому, чем больше файл, тем больший объем памяти будет потреблять этот сценарий. Но мы можем с этим кое-что сделать. Ниже приводится менее «жадная до памяти» версия библиотеки, вbinолняющей анализ файла журнала:
Теперь подсчет общего числа переданных байтов ведется по мере извлечения значений, а не в вызывающей функции. Ниже приводится несколько измененная версия сценария summarize_logfiles с новым параметром, позволяющим импортировать библиотеку с пониженным потреблением памяти:
Эти изменения привели к тому, что сценарий стал выполняться немного быстрее, чем версия с большим потреблением памяти:
На протяжении работы этого сценария потребление памяти составило порядка 4 Мбайт. Этот сценарий способен обрабатывать 2 Гбайтные файлы журналов за одну минуту. Теоретически размеры файлов могут быть неопределенно большого размера, и это не будет приводить к существенному увеличению объемов потребляемой памяти, как в предыдущей версии. Однако, поскольку для хранения данных используется словарь, каждый ключ которого - это уникальный IP-адрес, потребление памяти будет расти с увеличением числа уникальных IP-адресов. Если объем потребляемой памяти станет слишком велик, вы могли бы заменить словарь каким-нибудь хранилищем данных, или даже реляционной базой данных, такой как berkeley DB.
Related Articles
Set as favorite
Bookmark
Email This
Hits: 288 Комментарии (0)RSS feed CommentsНаписать комментарий |