Реструктуризация разбора результатов анализа многопоточного файла журнала

1

У меня есть файл журнала многопоточного процесса, который выглядит так:

<timestamp_in> <first_function_call_input> <thread:1>
    input_parameter_1:     value
    input_parameter_2:     value

<timestamp_in> <another_function_call_input> <thread:2>
    input_parameters:      values
<timestamp_out> <another_function_call_output> <thread:2>
    output_parameters:     values

<timestamp_out> <first_function_call_output> <thread:1>
    output_parameters:     values

В моей переменной результатов анализа я хотел бы иметь информацию о входе и выходе одного вызова функции вместе, например, например:

>>> print(parse_results.dump())
  -[0]:
       -function: first_function
       -thread: 1
       -timestamp_in: ...
       -timestamp_out: ...
       -input_parameters:
             [0]:
                  -parameter_name: input_parameter_1
                  -parameter_value: value
             [1]:
                  -parameter_name: input_parameter_2
                  -parameter_value: value
       -output_parameters:
             [0]: ...
             ...
  -[1]:
       -function: another_function
       -thread: 2
       ...

Есть ли способ реструктурировать parse_results непосредственно во время разбора, поэтому мне не нужно реструктурировать результаты позже? Может быть, с некоторыми синтаксическими действиями? Или было бы проще просто разобрать части ввода и выходные части самостоятельно, а затем отсортировать их по потоку, временной отметке и функции и сшить части ввода и выходные части вместе в новом объекте?

Спасибо за вашу помощь!

Редактировать:
Я собираюсь выполнить сортировку входных частей и выходных частей после их разбора отдельно, что кажется проще. Тем не менее, мне все еще интересно, если и как можно реструктурировать экземпляр результатов синтаксического анализа. Скажем, у меня есть следующая грамматика и тестовая строка:

from pyparsing import *

ParserElement.inlineLiteralsUsing(Suppress)
key_val_lines = OneOrMore(Group(Word(alphas)('key') + ':' + Word(nums)('val')))('parameters')

special_key_val_lines = OneOrMore(Group(Word(printables)('key') + ':' + Word(alphas)('val')))('special_parameters')

log = OneOrMore(Group(key_val_lines | special_key_val_lines))('contents').setDebug()

test_string ='''
foo             : 1
bar             : 2
special_key1!   : wow
another_special : abc
normalAgain     : 3'''

parse_results = log.parseString(test_string).dump()
print(parse_results)

Это обеспечивает следующее:

- contents: [[['foo', '1'], ['bar', '2']], [['special_key1!', 'wow'], ['another_special', 'abc']], [['normalAgain', '3']]]
  [0]:
    [['foo', '1'], ['bar', '2']]
    - parameters: [['foo', '1'], ['bar', '2']]
      [0]:
        ['foo', '1']
        - key: 'foo'
        - val: '1'
      [1]:
        ['bar', '2']
        - key: 'bar'
        - val: '2'
  [1]:
    [['special_key1!', 'wow'], ['another_special', 'abc']]
    - special_parameters: [['special_key1!', 'wow'], ['another_special', 'abc']]
      [0]:
        ['special_key1!', 'wow']
        - key: 'special_key1!'
        - val: 'wow'
      [1]:
        ['another_special', 'abc']
        - key: 'another_special'
        - val: 'abc'
  [2]:
    [['normalAgain', '3']]
    - parameters: [['normalAgain', '3']]
      [0]:
        ['normalAgain', '3']
        - key: 'normalAgain'
        - val: '3'

Как изменить грамматику моего парсера таким образом, чтобы parse_results.contents[2].parameters[0] вместо этого были parse_results.contents[0].parameters[3]?

Теги:
multithreading
parsing
pyparsing
logfile

1 ответ

1
Лучший ответ

Чисто судить о том, где рисовать линию на этом, и я написал парсеров в обоих стилях.

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

С точки зрения тестирования это также позволит вам протестировать код реструктуризации отдельно от кода разбора, возможно, со списком dicts или namedtuples, который будет симулировать проанализированные результаты из отдельных записей журнала.

tl; dr - для этой ситуации я бы пошел с методом последующей обработки для окончательной сортировки/реорганизации анализируемых записей журнала.

EDIT: Чтобы изменить результаты синтаксического анализа на месте, определите действие синтаксического анализа, которое принимает один аргумент, который я обычно tokens, и изменяю их с помощью типичных мутаторов списка или dict:

def rearrange(tokens):
    # mutate tokens in place
    tokens.contents[0].parameters.append(tokens.contents[2].parameters[0])

log.addParseAction(rearrange)

Если вы вернете None (как в этом примере), то структура маркеров, которая была передана, сохраняется как возвращаемая структура маркера. Если вы вернете значение non- None, то новое возвращаемое значение заменяет заданные токены в выводе парсера. Это как целое парсеров преобразовать анализируемую строку фактических чисел или дат/время парсеров преобразование разобранных строк в Python datetime и datetime с.

  • 1
    Спасибо за вашу оценку. Я все еще задаюсь вопросом, можно ли и как изменить ParseResults при разборе, поэтому я отредактировал свой вопрос и добавил пример кода. Не могли бы вы взглянуть на это? Еще раз спасибо за создание pyparsing и поделиться своими знаниями об этом!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню