You are viewing xfox

...and the road becomes my bride - Выделяем поля из логов nginx на python

> Recent Entries
> Archive
> Friends
> Profile
> My Website

January 1st, 2010


Previous Entry Share Next Entry
06:30 pm - Выделяем поля из логов nginx на python

Для анализа логов nginx мне понадобилось регулярное выражение, которое бы корректно разделяло запись на отдельные поля. Немного по-колдовав над логом, я понял, что наилучший способ разобраться в формате лога - это выцепить его из конфигурации сервера.

Кроме очевидного плюса - выделение полей с учетом всех разделителей и кавычек, использование формата позволяет получить именованные поля.

Вот код, который у меня получился, возможно пригодится.

import re

# формат из конфигурации nginx
FORMAT = '$remote_addr - $remote_user [$time_local] "$request" $status' + \
    ' $bytes_sent "$http_referer"' + \
    ' "$http_user_agent" "$gzip_ratio" "$cookie" $hostname'

# выражение, описывающее переменную в конфигурации логов nginx
TOKEN = '\$([a-z\_]+)'

# возможные скобки и кавычки вокруг переменных в конфигурации логов nginx
POSSIBLE_QUOTES = ('[]', '"', '\'')

def get_matcher(format):
    quotes = re.escape(''.join(POSSIBLE_QUOTES))

    pat = format
    for token in re.findall(TOKEN, format):
        res = re.search('([%s]?)(\$%s)([%s]?)' % \
            (quotes, token, quotes), format).groups()
        if not res:
            continue
        elif res[0] <> res[2]:
            tq = res[0] + res[2]
            tq_escaped = '\%s|\%s' % (res[0], res[2])
        else:
            tq = res[0]
            tq_escaped = '\%s' % res[0]

        tq = re.escape(tq)
        tq_escaped = re.escape(tq_escaped)

        if not tq:
            ftoken = '\$%s' % (token)
            ptoken = '(?P<' + token + '>[^\ ]*)'
        else:
            ftoken = '[%s]\$%s[%s]' % (tq, token, tq)
            ptoken = '[%s](?P<%s>(?:%s|[^%s])*)[%s]' % (tq, token, tq_escaped, tq, tq)

        pat = re.sub(ftoken, ptoken, pat)

    patc = re.compile(pat)
    def matcher(line):
        return patc.match(line)
    return matcher

def main():
    f = file('access_log')
    matcher = get_matcher(FORMAT)
    for line in f:
        print matcher(line).groupdict()

Возможно кому-нибудь будет полезным

UPD: Немного поправил код, чтобы он корректно работал с записями, в которых встречаются поля вида: “some text with escaped \” qoute”

--
Этот, а также другие мои посты по it-тематике вы можете прочитать здесь

(Leave a comment)


> Go to Top
LiveJournal.com