j-easy / easy-rules

The simple, stupid rules engine for Java
https://github.com/j-easy/easy-rules/wiki
MIT License
4.86k stars 1.05k forks source link

Auditing which rules were fired when RuleEngine.fire() is called #360

Open vshanbha opened 3 years ago

vshanbha commented 3 years ago

I am considering using this library to build an embedded RuleEngine in our product. One of our requirement is to 'audit' rules which were fired during a particular run and then persist that audit information (with rule names) in side the database. The Rules are expected to be run in a multi-threaded environment. I am not sure if there is an out of the box feature that can simply get the list of Rules that were actually fired in a particular run.

Based on the reading of wiki and faqs - I can think of one way - Implementing RulesEngineListener interface. and adding the list of Rules fired as a separate "Fact" in the facts.

Do you recommend this option ? Are there any challenges you foresee in using this option ? Are there any other alternatives ?

vshanbha commented 3 years ago

Further to my question I was able to set up Audit as a separate Fact in the "facts" by implementing a RuleListener which appends Rule name to a Fact called RuleAudit whenever the onSuccess method is called.

There is one scenario though in terms of Actions that involve setting facts. Sometimes there are actions in the different rule which set value to the same "Fact". In this case I want that the value that is set on the said Fact is the one from the first rule that set that fact. Any later actions (and rules) trying to set that Fact should be skipped. I can do this by putting checks in the Action, however how do I audit this using RuleListener. One way I found was to throw an exception when an action tries to set a non-empty fact and then set up a OnFailure method in RuleListener to append rule name to a Fact called "RuleSkipped". This works however due to the exception being thrown it generates Error Logs and when we have 1000s of rules those Error Logs would be undesirable.

Any alternative ideas ?