Добро пожаловать! Войти Зарегистрироваться

Расширенный

Разбор синтаксического дерева, при анализе логов

Написал w-495 
Разбор синтаксического дерева, при анализе логов
11 October 2015 00:12
Задача

Есть набор фалов логов обращений к системе мониторинга Graphite.

Quote
Справка
Graphite часто используется для вывод на графики различных характеристик работы какой-то системы, зависящих от времени.
Например можно построить график изменения количества переходов на какую-то страницу сайта, или график потребления памяти, диска, график загрузки процессоров.
При отображении на графике строится набор точек, которые описывают указанную характеристику. Такой набор точек называют временнЫм рядом или временнОй серией.

Исходные логи Graphite имеют вид:
192.168.14.20  [23/Jul/2015:15:44:11 +0100] "GET    /render?from=-4hours&noCache=True&hideLegend=False&height=400&width=500&until=-&title=My%20Graphic&target=xStyle%28aliasByNode%28foo.bar.baz%29%29&yMax=400&_uniq=bb9b7ee2db0c13e3 HTTP/1.1" 200 1074 "[graphite.server.com]; "MyUserAgent" 0.048    0.048   "
Каждая строка лога содержит к себе запрос к веб-серверу, который отображает графики.
Среди параметров запроса есть ключ target, который содержит или название временного ряда,
или набор функций, которые применяются к временному ряду.
Ключ target может встречаться в запросе несколько раз.
Это означает, что пользователь хочет вывести на график несколько временных серий.
Требуется привести эти логи в вид, где можно анализировать какие функции вызываются, без учета названий временных рядов,

Решение

Реализация: graphite-log-parser.py

Общее описание:
1) Из каждой строки лога выделяем запрос к веб-серверу.
2) Декодируем каждый запрос из формата URL-encoding.
3) Средствами Python из каждого запроса выделяем ключи target.
4) С помощью регулярных выражений приводим значение ключа target в синтаксическую конструкцию, допустимую в языке Python.
5) Рекурсивно разбираем полученную строку как конструкцию на языке Python c помощью абстрактного синтаксического дерева. В этом может помочь модуль ast.
5.1) На каждом шаге рекурсии пытаемся понять, какая синтаксическая единица перед нами.
5.2) Если это переменная (название временного ряда), то заменяем ее на специальный символ.
5.3) Если это число или строка, то возвращаем как есть.
5.4) Если это вызов функции, то выполняем п.5.1 для каждого аргумента, а имя функции вместе с ее аргументами, описываем строкой, и кладем строку в стек.

Для примера строки лога, которую я привел выше получаем описание

CASE = ["cactiStyle(aliasByNode('***', 1))"]; PARAMS = «{'from': ['-4hours'], 'until': ['-']}»;
   <0> ~ CALL (0) = «aliasByNode('***', 1)»;
   <0> ~ CALL (1) = «xStyle(aliasByNode('***', 1))»;
К сожалению, только зарегистрированные пользователи могут писать в этом форуме.

Авторизоваться на форуме