скомпилировать регулярное выражение из файла журнала в dict, ошибка, когда файл журнала имеет новый атрибут - PullRequest
0 голосов
/ 01 мая 2018

Так что мне нужно проанализировать файл журнала nginx. На полпути к файлу журнала в конце каждой строки была добавлена ​​новая переменная.

Я использовал https://github.com/bbb1991/nginx-log-parser/blob/master/main.py как источник вдохновения (т.е. использовал большую часть кода).

import re





REQUEST_TIME_CONF = '$remote_addr - $remote_user [$time_local] "$request" ' \
                    '$status $body_bytes_sent $http_referer" ' \
                    '"$http_user_agent" "$gzip_ratio" "$request_time"'                    

def get_requests(file_name):
    """

    """

    file_to_open = open(file_name,"r+")
    log_lines = file_to_open.readlines()

    lines = []

    log_pattern = ''.join(
        '(?P<' + g + '>.*?)' if g else re.escape(c)
        for g, c in re.findall(r'\$(\w+)|(.)', REQUEST_TIME_CONF))

    for line in log_lines:
        lines.append(find(log_pattern,line))
    return lines

def find(log_pattern, text):
    match =  re.match(log_pattern, text)
    if match:
        return match
    else:
        return False

def process_log(log_file):

    requests = get_requests(log_file)
    #print(requests)

    for x in range(len(requests)):

        request = requests[x]

        request = request.groupdict()

        remote_addr = request.get('remote_addr')
        remote_user = request.get('remote_user')
        time_local = request.get('time_local')
        request_item = request.get('request')
        status = request.get('status')
        body_bytes_sent = request.get('body_bytes_sent')
        http_referer = request.get('http_referer')
        http_user_agent =  request.get('http_user_agent')
        gzip_ratio = request.get('gzip_ratio')
        try:
            request_time = request.get('request_time')
        except AttributeError:
            request_time = None        



       # print(remote_addr,remote_user,time_local,request_item,status,
            #  body_bytes_sent,http_referer,http_user_agent,gzip_ratio,
            #  request_time)
        print(request)

access_log_to_parse = '/Users/username/Documents/Development/sample_access.log'
process_log(access_log_to_parse)

Файл sample_access.log выглядит так:

10.1.0.59 - - [12/Jul/2017:17:57:56 +0600] "POST /court/ws/avf HTTP/1.1" 500 296 "-" "CodeGear SOAP 1.3" "0.01" "0.003"
10.1.0.59 - userTest [12/Jul/2017:17:57:56 +0600] "POST /court/ws/avf HTTP/1.1" 500 296 "-" "CodeGear SOAP 1.3" "0.01"

Nginx имеет специальный формат журнала, который объявлен в REQUEST_TIME_CONF

Я удалил request_time из последней строки, чтобы имитировать экземпляр, в котором строка журнала не имеет этого атрибута.

Поэтому, когда присутствует request_time, ему нужно будет записать значение request_time, в противном случае просто напишите None.

Следующая ошибка выдается при запуске кода:

AttributeError: 'bool' object has no attribute 'groupdict'

Я провел еще несколько исследований по этому вопросу, и похоже, что модуль re возвращает значение ИСТИНА или ЛОЖЬ, когда что-то совпадает (или нет), как вы можете видеть, я наивно пытался попробовать / поймать для request_time, думая, что если значения там нет, я могу просто передать ему значение Null, но это не сработало.

Итак, на мой взгляд, должна быть какая-то проверка в функции findall log_pattern regex или во время re.match, но мои навыки работы с Python отсутствуют (следовательно, код заимствует! Ха-ха)

1 Ответ

0 голосов
/ 01 мая 2018
Модуль

re возвращает совпадение или None никогда не логически, но ваша функция find может возвращать False, если совпадение равно None. В этом случае результат не должен добавляться в список.

for line in log_lines:
    request = find(log_pattern,line)
    if request:
        lines.append(request)
...