20 — Advanced

Rule Tracing & Debugging

The Tracer provides event-driven debugging for rule execution. It lets you observe every stage of a rule or ruleset lifecycle through listener callbacks, making it easy to debug, audit, and monitor your rule engine in action.

Listener Types

Tracer supports three listener types, each targeting a different scope of events:

RuliiListener

Receives all events (rules and rulesets)

RuleListener

Receives rule-level events only

RuleSetListener

Receives ruleset-level events only

Creating a Tracer

Tracer tracer = Tracer.builder().build();

Rule-Level Events

A RuleListener can respond to the following events during rule execution:

Event Description
onRuleStartFired when a rule begins execution
onPreConditionCheckFired before the pre-condition is evaluated
onConditionCheckFired after the main condition is evaluated
onThenFired when the then-action executes
onOtherwiseFired when the otherwise-action executes
onRuleErrorFired when a rule throws an error
onRuleEndFired when a rule finishes execution

RuleSet-Level Events

A RuleSetListener can respond to the following events during ruleset execution:

Event Description
onRuleSetStartFired when a ruleset begins execution
onPreConditionCheckFired before the ruleset pre-condition
onInitializerFired when the initializer runs
onRuleRunFired each time a rule within the set runs
onStopFired when execution stops early
onFinalizerFired when the finalizer runs
onResultFired when the result is produced
onRuleSetEndFired when the ruleset finishes
onErrorFired when the ruleset encounters an error

Example: Adding a Rule Listener

Tracer tracer = Tracer.builder().build();

// Add a rule listener
tracer.addListener(new RuleListener() {
    @Override
    public void onRuleStart(Rule rule) {
        System.out.println("Starting: " + rule.getName());
    }

    @Override
    public void onConditionCheck(Rule rule, Condition condition, boolean result) {
        System.out.println(rule.getName() + " condition: " + result);
    }

    @Override
    public void onRuleEnd(Rule rule, RuleResult result) {
        System.out.println("Finished: " + rule.getName() + " → " + result.status());
    }
});

// Use tracer in RuleContext
RuleContext ctx = RuleContext.builder()
    .tracer(tracer)
    .build(name -> "Alice", age -> 30);

rule.run(ctx);
// Output:
// Starting: AgeCheck
// AgeCheck condition: true
// Finished: AgeCheck → PASS

Listener Management

The Tracer provides methods to manage listeners at runtime:

// Add a listener
tracer.addListener(myListener);

// Remove a specific listener
tracer.removeListener(myListener);

// Clear all listeners
tracer.clear();

Use Cases

Debugging

Step through rule execution to identify logic issues

Audit Logging

Record which rules fired and their outcomes

Monitoring

Track rule execution performance and patterns