Реализация «движка правил» в Python - PullRequest
17 голосов
/ 22 января 2009

Я пишу приложение для сбора / анализа журналов на Python, и мне нужно написать «механизм правил» для сопоставления и обработки сообщений журнала.

Для этого нужно добавить:

  • Соответствие регулярного выражения для самого сообщения
  • Арифметические сравнения для серьезности / приоритета сообщения
  • Булевы операторы

Я предполагаю, что примером правила, вероятно, будет что-то вроде:

(message ~ "program\\[\d+\\]: message" and severity >= high) or (severity >= critical)

Я подумываю использовать PyParsing или аналогичный для фактического разбора правил и построения дерева разбора.

Текущий (еще не реализованный) дизайн, который я имею в виду, состоит в том, чтобы иметь классы для каждого типа правила, а также создавать и связывать их вместе в соответствии с деревом анализа. Тогда каждое правило будет иметь метод «совпадения», который может принимать объект сообщения, возвращающий, соответствует ли он правилу.

Очень быстро, что-то вроде:

class RegexRule(Rule):
    def __init__(self, regex):
         self.regex = regex

    def match(self, message):
         return self.regex.match(message.contents)

class SeverityRule(Rule):
    def __init__(self, operator, severity):
         self.operator = operator

    def match(self, message):
         if operator == ">=":
             return message.severity >= severity
         # more conditions here...

class BooleanAndRule(Rule):
    def __init__(self, rule1, rule2):
         self.rule1 = rule1
         self.rule2 = rule2

    def match(self, message):
          return self.rule1.match(message) and self.rule2.match(message)

Эти классы правил будут затем объединены в цепочку в соответствии с деревом разбора сообщения, и метод match () будет вызван в верхнем правиле, которое будет каскадно уменьшаться, пока все правила не будут оценены.

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

Может ли кто-нибудь, имеющий некоторый опыт в подобных вещах, пожалуйста, присоединиться и оценить идею?

EDIT: Пока есть несколько хороших ответов, вот немного пояснений.

Целью программы является сбор сообщений журнала с серверов в сети и сохранение их в базе данных. Помимо сбора сообщений журнала, сборщик определит набор правил, которые будут либо совпадать, либо игнорировать сообщения в зависимости от условий, и при необходимости пометить предупреждение.

Я не вижу, чтобы правила были более чем средней сложности, и они будут применяться в цепочке (списке) до тех пор, пока не будет достигнуто соответствующее предупреждение или правило игнорирования. Однако эта часть не так актуальна для вопроса.

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

Ответы [ 5 ]

59 голосов
/ 22 января 2009

Не изобретайте еще один язык правил.

Либо используйте Python, либо используйте другой существующий, уже отлаженный и рабочий язык, например BPEL.

Просто напишите свои правила на Python, импортируйте их и выполните. Жизнь проще, намного легче отлаживать, и вы фактически решили реальную проблему чтения журнала, не создавая другую проблему.

Представьте себе этот сценарий. Ваша программа ломается. Теперь это либо разбор правила, либо выполнение правила, либо само правило. Вы должны отладить все три. Если бы вы написали правило на Python, это было бы правилом, и это было бы так.

«Я думаю, что будет трудно отфильтровать Python до такой степени, что пользователь не сможет непреднамеренно сделать что-нибудь сумасшедшее с правилами, которые не предназначены».

Это в значительной степени аргумент "Я хочу написать компилятор".

1) Вы основной пользователь. Вы будете писать, отлаживать и поддерживать правила. Есть ли действительно армии сумасшедших программистов, которые будут делать сумасшедшие вещи? В самом деле? Если есть потенциальный сумасшедший пользователь, поговорите с ним . Научить их. Не боритесь с ними, изобретая новый язык (который вам потом придется поддерживать и отлаживать вечно).

2) Это просто обработка журнала. Там нет реальной стоимости для сумасшествия . Никто не собирается разрушать мировую экономическую систему из-за неправильного обращения с бревнами. Не выполняйте небольшую задачу с несколькими десятками строк Python на интерпретаторе из 1000 строк, чтобы интерпретировать несколько десятков строк некоторого языка правил. Просто напишите несколько десятков строк Python.

Просто напишите это на Python как можно быстрее и яснее и переходите к следующему проекту.

5 голосов
/ 18 декабря 2009

Вы также можете посмотреть на PyKE .

1 голос
/ 09 октября 2013

Рассматривали ли вы NebriOS? Мы только что выпустили этот инструмент после создания его для наших собственных целей. Это чистый движок правил Python / Django . На самом деле мы используем его для задач рабочего процесса, но он достаточно универсален, чтобы помочь вам в вашей ситуации. Вам нужно будет подключиться к удаленной БД и запустить правила против нее.

Python, который вы написали, в конечном итоге станет более чем одним правилом в системе. Вот, например, один:

class SeverityRule(NebriOS):
    # add listener or timer here

check(self):
    if operator == ">="
    return message.severity >= severity
    # any number of checks here


action(self):
    csv.append(message.severity, datetime.now)
    send_email(kamil@example.com, """Severity level alert: {{message.severity}}""")

Проверьте это на http://nebrios.com. Я не понимал, сколько нужно было создать приложение движка правил, такое как Nebri, до того, как моя команда начала. Это была ОГРОМНАЯ задача, которая намного глубже, чем кажется. ACL, очереди, формы, KVPS, эффективные проверки, полезные ошибки, анализ электронной почты, динамические формы и список можно продолжать.

0 голосов
/ 22 января 2009

Немного сложно ответить на вопрос, не зная, какова область применения.

  • О чем вы пытаетесь рассуждать?
  • О каком уровне анализа вы говорите?
  • Насколько сложными вы видите становление правил?
  • Насколько сложно взаимодействие между различными правилами?

На одном конце спектра есть простой одноразовый подход, как вы предложили. Это хорошо, если правил немного, относительно просто, и вы не делаете ничего более сложного, чем агрегирование сообщений журнала, соответствующих указанным правилам.

На другой стороне спектра находится система рассуждений с большим весом, что-то вроде CLIPS , которая имеет интерфейс Python . Это настоящий механизм правил с логическим выводом, который дает возможность делать сложные рассуждения. Если вы создаете что-то вроде диагностического движка, который работает вне журнала программы, это может быть более подходящим.

EDIT:

Я бы сказал, что текущая идея реализации подходит для того, что вы делаете. Что-нибудь намного больше, и я думаю, что вы, вероятно, рискуете чрезмерно спроектировать решение. Кажется, что вы получаете то, что хотите, сопоставляя сообщения журнала только на основе нескольких различных критериев.

0 голосов
/ 22 января 2009

Единственное место, которое отличается от самого синтаксиса Python - это часть message ~ "program\\[\d+\\]: message", поэтому мне интересно, действительно ли вам нужен новый синтаксис.

Обновление: Хорошо, у вас есть проблемы с юзабилити или безопасностью - это разумно. Пара предложений:

  • Получите подсказку от Awk и упростите синтаксис сопоставления с образцом, например, /program\[\d+\]: message/ вместо message ~ "program\\[\d+\\]: message".

  • Я бы реализовал это путем перевода в выражение Python при разборе входных данных вместо построения дерева объектов для оценки, если только вы не собираетесь выполнять больше операций с этими вещами, чем вычисление. Это должно потребовать меньше кода и работать быстрее. Верхний уровень может выглядеть примерно так:

    def compile(input):
        return eval('lambda message, severity: %s' % parse(input))
    

Еще одна идея, более дальняя: напишите свое приложение на Lua. Он предназначен для непрограммистов, чтобы расширять программы достаточно безопасно, без необходимости многому учиться. (Он успешно использовался таким образом, и вы можете тестировать в песочнице, чтобы пользовательский код не мог получить никаких возможностей, которые вы ему явно не передаете, мне сказали.)

Я сейчас заткнусь. :-) Удачи!

...