ply - python parse text




Implémentation d'un "moteur de règles" en Python (4)

J'écris une application de collecte / analyse de journaux en Python et j'ai besoin d'écrire un "moteur de règles" pour correspondre et agir sur les messages du journal.

Il doit comporter:

  • Expression régulière correspondant au message lui-même
  • Comparaisons arithmétiques pour la gravité / la priorité des messages
  • opérateurs booléens

J'envisage un exemple de règle serait probablement quelque chose comme:

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

Je pense à utiliser PyParsing ou similaire pour réellement analyser les règles et construire l'arbre d'analyse.

La conception actuelle (pas encore implémentée) que j'ai en tête est d'avoir des classes pour chaque type de règle, et de les construire et de les enchaîner en fonction de l'arbre d'analyse. Ensuite, chaque règle aurait une méthode "matches" qui pourrait prendre un objet de message de retour, qu'il corresponde ou non à la règle.

Très rapidement, quelque chose comme:

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)

Ces classes de règles seraient ensuite enchaînées en fonction de l'arborescence d'analyse du message, et la méthode match () serait appelée sur la règle supérieure, ce qui se répercuterait en cascade jusqu'à ce que toutes les règles aient été évaluées.

Je me demande simplement si c'est une approche raisonnable, ou si mon design et mes idées sont complètement hors de propos? Malheureusement, je n'ai jamais eu l'occasion de suivre un cours de conception de compilateur ou quoi que ce soit de ce genre dans Unviersity, alors je suis à peu près de mon propre chef.

Quelqu'un avec de l'expérience dans ce genre de choses pourrait-il entrer et évaluer l'idée?

EDIT: Quelques bonnes réponses jusqu'à présent, voici un éclaircissement.

Le but du programme est de collecter des messages de journal à partir des serveurs du réseau et de les stocker dans la base de données. Outre la collecte de messages de journal, le collecteur définit un ensemble de règles qui correspondent ou ignorent les messages en fonction des conditions et signalent une alerte si nécessaire.

Je ne vois pas les règles de plus d'une complexité modérée, et elles seront appliquées dans une chaîne (liste) jusqu'à ce qu'une alerte d'appariement ou une règle d'ignorance soit atteinte. Cependant, cette partie n'est pas tout à fait pertinente à la question.

Pour autant que la syntaxe soit proche de la syntaxe Python, oui c'est vrai, mais je pense qu'il serait difficile de filtrer le Python au point où l'utilisateur ne pourrait pas faire par inadvertance des choses folles avec les règles qui n'étaient pas prévues.


Il est un peu difficile de répondre à la question sans savoir quelle est la portée de la demande.

  • Qu'est-ce que vous essayez de raisonner?
  • De quel niveau d'analyse parlez-vous?
  • À quel point voyez-vous les règles devenir compliquées?
  • Quelle est la complexité de l'interaction entre différentes règles?

À une extrémité du spectre se trouve une approche ponctuelle simple comme celle que vous avez proposée. C'est très bien si les règles sont peu nombreuses, relativement simples, et que vous ne faites rien de plus compliqué que d'agréger les messages du journal qui correspondent aux règles spécifiées.

De l'autre côté du spectre est un système de raisonnement lourd, quelque chose comme CLIPS qui a une interface Python . C'est un véritable moteur de règles avec inférence et offre la possibilité de faire un raisonnement sophistiqué. Si vous construisez quelque chose comme un moteur de diagnostic qui fonctionne à partir d'un journal de programme, cela pourrait être plus approprié.

MODIFIER:

Je dirais que l'idée de mise en œuvre actuelle est bonne pour ce que vous faites. Rien de plus et je pense que vous courez probablement le risque de sur-ingénierie de la solution. Il semble capturer ce que vous voulez, correspondant sur les messages du journal en fonction de quelques critères différents.


Le seul endroit différent de la syntaxe Python est le message ~ "program\\[\d+\\]: message" , donc je me demande si vous avez vraiment besoin d'une nouvelle syntaxe.

Mise à jour: OK, vous avez des problèmes de convivialité ou de sécurité - c'est raisonnable. Quelques suggestions:

  • Prenez un indice de Awk et rationalisez la syntaxe d'appariement, par exemple /program\[\d+\]: message/ au lieu de message ~ "program\\[\d+\\]: message" .

  • Je l'implémenterais en traduisant en une expression Python lorsque l'entrée est analysée, au lieu de construire un arbre d'objets à évaluer, sauf si vous vous attendez à faire plus d'opérations sur ces choses que l'évaluation. Cela devrait nécessiter moins de code et courir plus vite. Le niveau supérieur pourrait ressembler à quelque chose comme:

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

Une autre idée, plus loin: écrivez votre application dans Lua. Il est conçu pour les non-programmeurs afin d'étendre les programmes raisonnablement sans avoir besoin d'apprendre beaucoup. (Il a été utilisé de cette façon avec succès, et vous pouvez bac à sable d'évaluation afin que le code de l'utilisateur ne peut pas obtenir à toutes les capacités que vous ne lui passez pas explicitement, on me dit.)

Je vais me taire maintenant. :-) Bonne chance!


Vous pourriez aussi vouloir regarder PyKE .


Avez-vous considéré NebriOS? Nous venons de publier cet outil après l'avoir construit pour nos propres besoins. C'est un pur moteur de règles Python / Django . Nous l'utilisons pour les tâches de workflow, mais c'est assez générique pour vous aider dans votre situation. Vous devez vous connecter à la base de données distante et exécuter les règles à son encontre.

Le Python que vous avez écrit finirait par être plus d'une règle dans le système. En voici un par exemple:

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([email protected].com, """Severity level alert: {{message.severity}}""")

Découvrez-le sur http://nebrios.com . Je n'ai pas réalisé combien il y avait à construire une application de moteur de règles comme Nebri jusqu'à ce que mon équipe ait commencé. C'était une tâche énorme qui va beaucoup plus loin que cela semble. ACL, files d'attente, formulaires, KVPS, vérifications efficaces, erreurs utiles, analyse de courrier électronique, formulaires dynamiques, et la liste continue.





rules