понедельник, 18 июня 2012 г.

Как использовать hive в web-аналитике. Анализ логов апача

В этом посте я расскажу, как при помощи hive можно вытащить что-нибудь ценное из логов апача. Если слова hive или веб-аналитика вам ничего не говорят, то рекомендую прочитать мой предыдущий пост:


В качестве справочного материала рекомендую использовать книгу Tom White "Hadoop The DefinitiveGuide", или читать про hive в wiki на сайте apache

Лог апача

Итак, исходными данными, по которым мы можем посчитать полезные нам метрики являются логи веб-серверов, которые обрабатывают наши запросы.
На большинстве серверов в качестве веб-сервера используется Apache, поэтому будем анализировать именно его логи.
Обычно лог апача выглядит как нибудь так:
155.54.41.193 - - [01/May/2012:00:42:31 +0400] "GET http://news.rambler.ru/73221.html HTTP 1.0" 200 3591 - "Mozilla/5.0 (Windows; I; Windows NT 5.1; ru; rv:1.9.2.13) Gecko/20100101 Firefox/4.0" 

через пробел в него пишутся поля
  • IP
  • чтото неизвестное (всегда стоит прочерк)
  • имя пользователя, (если пользователь авторизуется на сервере, что крайне редко)
  • дата клика
  • запрос, который был сделан к серверу
  • код ответа
  • длина ответа
  • реферрер (предыдущая станица, на который был человек)
  • юзер агент (описание устройства, с которого пользователь заходил на сайт)
Такие логи содержат в себе крайне важную информацию о том, как пользователи посещают ресурс. Кроме этих полей Apache может писать в лог и другую полезную информацию, например содержимое выданных пользователю кук.

Для дальнейших экспериметов логи apache можно сгенерировать специальным python скриптом, который я выложил на github.

В качестве параметров скрипта можно задать число пользователей ресурса, частоту их заходов, время начала и конца генерации логов.
Ключ «-h» выдает подробный хелп по утилите, а вызов скрипта без агрументов геренирует логи за май 2012 года.

Итак, поехали считать статистику!

Для начала надо создать таблицу, через которую у hive будет доступ к полям лога. Разбирать лог на поля нам прийдется при помощи регулярных выражений. Логи разложены по папкам и сейчас мы создадим таблицу по логам за один день.
CREATE EXTERNAL TABLE apache_logs ( 
    -- это команда создать таблицу. EXTERNAL означает 
    -- что данные в ней нужны где-то еще и их не надо 
    -- удалять удалять при удалении таблицы
    ip STRING,
    human_time STRING,
    url STRING,
    response STRING,
    referrer STRING,
    user_agent STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
    -- serde это сокращение от "serialization-deserialization" - 
    -- алгоритм, как разбирать данные по столбцам
WITH SERDEPROPERTIES (
"input.regex" =
"([\\d\\.]+) - - \\[(.*?)\\] \"GET (.+?) HTTP.*?\" (\\d+?) \\d+? (\\S+?) \"(.+?)\"")
    -- это то регулярное выражение, которым надо разбирать 
    -- апачовый лог. Каждая скобка в нем - содержимое очередной колонки
LOCATION '/home/mezentsev/src/hive_web_analytics/logs/2012-05-01'
    -- путь на диске до папки в которой хранятся логи
;
Чтобы проверить, что все создалось хорошо, можно вызвать простейшую команду
SELECT * FROM apache_logs LIMIT 10;

Если вы увидите на экране что-то типа
220.232.156.191 01/May/2012:09:00:13 +0400      http://news.rambler.ru...
189.244.47.170  01/May/2012:09:00:40 +0400      http://news.rambler.ru...
207.173.21.42   01/May/2012:09:01:39 +0400      http://news.rambler.ru...
207.173.21.42   01/May/2012:09:01:42 +0400      http://news.rambler.ru...
............... 
то все работает нормально.
 
Теперь посмотрим, что же интересного мы можем узнать про наш сайт. Такой же простой командой как и предыдущая мы можем посчитать число кликов на сайте

SELECT COUNT (1) FROM apache_logs; 
(у меня получилось 4551 кликов, если у вас другое число — это нормально, так как скрипт генерит логи пользователей случайным образом).

Про COUNT и другие функции можно почитать в разделе функции и операторы на wiki hive

Узнать число разных пользователей на сайте не так просто. Дело в том, что чаще всего IP у пользователей интернета выдаются динамически и вполне легко два случайных визитеров могли бы зайти на сайт с одним IP. Номальное решение этой проблемы - выдавать посетителям сайта уникальные куки, записывать их содержимое отдельным полем в лог и дальше считать пользователей по ним. Другой способ - можно считать уникальной характеристикой пару IP + useragent, однако в реальности пользователя можно отслеживать по ней только в течении одной сессии, может быть одного дня:

SELECT COUNT (DISTINCT CONCAT(ip,user_agent)) 
FROM apache_logs; 
(у меня получилось 96 посетителей)

Здесь команда CONCAT(A,B) склеивает 2 строчки в одну, а COUNT (DISTINCT C)— считает число таких разнообразных значений в таблице.
Теперь можно, для примера, узнать число пользователей которые побывали на сайте с айпада. Информация об устройстве содержится в строке user_agent и может быть извлечена командой  
SELECT COUNT (DISTINCT CONCAT(ip,user_agent))
FROM apache_logs
WHERE user_agent LIKE "%iPad%";
(32 человека)
"A LIKE B", как вы уже догадались, это сравнение строки A с маской B.

Пользовательские функции

Разбор агента пользователя может быть более сложным и требовать выполнения нестандартных функций, написанных специально для задачи.
HiveQL поддерживает написание таких функций
 тобы не превращать hiveQL запрос в нечитабельного и медлительного монстра, его можно вынести в специальную UDF функцию (user defined function). UDF функции пишутся на java, потом инициализируются в hive как новые пользовательские функции, после чего их можно использовать наравне со встроенными.
Элементарный код функции разбора юзер агента можно скачать с github:
[TODO: вставить ссылку]
Собирается она при помощи ant'а, но в начале вам может потребоваться поправить build.xml, указав правильные пути до библиотек hadoop и hivе.
Когда код собран в jar, его сначала надо будет добавить в текущую сессию hive
 
ADD JAR /home/mezentsev/..../get_os_from_user_agent.jar
    -- здесь должен быть полный путь до jar файла с UDF функцией
;
CREATE TEMPORARY FUNCTION get_os AS 'GetOsFromUserAgent';

Функция разбора юзерагента будет называтся get_os.
Теперь можно увидеть, из под каких операционных систем к нам заходили люди

SELECT get_os (user_agent) FROM apache_logs LIMIT 10;

И даже посчитать, сколько человек под какой операционкой сидело:
SELECT get_os (user_agent) AS os,
COUNT (DISTINCT CONCAT (ip,user_agent))
FROM apache_logs
GROUP BY GET_OS (user_agent);

Комментариев нет:

Отправить комментарий