Eine der häufigsten Anforderungen unserer Kunden ist das Protokollieren, welche Regeln denn wirklich gefeuert haben. Die Ausführung eines Regelwerks in der Regelmaschine ist ja zunächst mal eine Black Box. Man weiß nicht wirklich, was passiert und warum eine bestimmte Entscheidung getroffen wird. Durch das Logging wird dieBlack Box durchsichtig.
Hintergrund
Aus den Projekten heraus gibt es meist 3 Gründe für das Protokollieren:
- Prozesstransparenz: Häufig müssen Entscheidungen protokolliert und die Gründe für diese Entscheidungen nachvollziehbar sein.
- Fehlersuche: In vielen Fällen findet man durch ein geschicktes Protokollieren heraus, warum Fehler auftreten. Beispielsweise erkennt man, welche Regeln unerwünscht feuern und auch warum dies passiert. Ein Debugging ist so meist nicht notwendig.
- Einfaches Testen von neuen Regelwerken: Greifen die Bedingungen einer Regel bei der gewünschten Konstellation.
Das Interface IlrTool
ILOG JRules bietet bereits seit den Anfangsversionen eine elegante Möglichkeit, die Ausführung von Regeln zu protokollieren. Mit dem Interface IlrTool kann man einfach und schnell alle wichtigen Ereignisse während der Ausführung eines Regelwerks protokollieren. Für uns ist dies meist das “Tool” der Wahl.
IlrTool beschreibt einen EventHandler für eine Vielzahl von Ereignissen, die während der Ausführung in der Regelmaschine auftreten können. Dies umfasst das Ausführen einer Regelinstanz, der Start eines neuen Tasks, das Manipulieren von Objekten im Working Memory (assert, retract oder update) und vieles mehr.
Für die meisten Projekte genügt dabei eine Methode von IlrTool: Die Regelmaschine ruft
public void notifyBeginInstance(IlrRuleInstance rule)
immer vor dem Ausführen einer Regelinstanz auf. Über den Parameter IlrRuleInstance kann man auf die Regelinstanz selbst zugreifen, z.B. um den Namen zu protokollieren oder die gebundenen Objekte der Instanz auszuwerten. Eine typische Implementierung der Methode ist daher:
logger.info("FIRED: " + rule.getRuleName() );
Vorgehensweise in J2SE
In einer J2SE-Umgebung oder bei früheren Version von JRules kann man vor dem Starten der Ausführung eine Klasse, die IlrTool implementiert, direkt im Java-Code mit der Regelmaschine verbinden. Die API stellt dazu 3 Methoden in der Klasse IlrContext (API für JRules 6.7.3) bereit:
int connectTool(IlrTool tool) void disconnectTool(int toolID) void disconnectTools()
Die erste Methode verbindet eine “Rule-Logger”-Klasse mit der Regelmaschine und liefert eine ID zurück. Durch Angabe dieser ID in der zweite Methode kann die Verbindung wieder aufgehoben werden. Die letzte Methode entfernt alle Logger (sprich IlrTools) aus dem IlrContext.
Das Entfernen eines verbundenen IlrTools ist wichtig: Wir hatten bei einem Kunden die Meldung, dass in einem Projekt die Log-Meldungen explodieren. Beim ersten Durchlauf war alles in Ordnung, aber nach einiger Zeit waren plötzlich viele Einträge für einzelne Regel im Protokoll. Ursache war das fehlende Entfernen der IlrTools. Mit jeder Ausführung wurde ein weiterer Logger an die Regelmaschine gebunden und nach der n-ten Ausführung gab es n Logger.
Man umgibt also am besten den Befehl zum Ausführen der Regeln mit dem connect / disconnect -Paar:
context.connect(new RuleLogger()); context.execute(); context.disconnectTools();
Vorgehensweise mit RES
In den meisten aktuellen Projekten kommt der Rule Execution Server zum Einsatz. Der Zugriff auf einen IlrContext ist im umgebenden Java-Programm nicht mehr so einfach möglich und der oben vorgestellte Code funktioniert nicht mehr. Innerhalb des Regelwerks hat man aber über ?context eine Referenz auf das aktuelle IlrContext-Objekt. Also verschiebt man einfach das Verbinden in die Initial Actions und das Trennen in die Final Actions des Mainflows. Bitte nicht das Trennen mit ?context.disconnectTools() in den Final Actions vergessen.
Ausblick
In einem späteren Post zeige ich noch andere Möglichkeiten, wie man die Ausführung der Regeln protokollieren kann.