4.3 KB


Brawler is a ECA (Event Condition Action) engine which can process multiple event concurrently. A user can define rules which execute certain actions under certain conditions. The engine is defined in brawler.engine.


The event-based system of Brawler relies heavily on priorities for control flow. Both events and rules (which are triggered by events) have priorities. By default events and rules have the priority 0 which is the highest priority. Events are processed according to their priority and all triggering rules of a single event are executed according to their priority.


The processor is the central piece of the event engine. It controls the thread pool, contains the rule index and handles the event processing.

The engines behaviour is solely defined by rules. These rules are added before the engine is started. Each added rule has a priority which determines their execution order if multiple rules are triggered by the same event. The main processing cycle, once the engine has been started, can be described as:

Event injection -> Triggering check -> Rule Matching -> Fire Rules

When injecting a new event it is possible to also pass a monitor with a certain scope and a priority. The scope is used by the processor to narrow down the triggering rules. A possible scenario for scopes are different types of analysis (e.g. quick analysis or deep analysis - only a subset of rules is required for the quick analysis). The priority determines when an event is processed - higher priority events are processed first.

After an event is injected the Processor first checks if anything triggers on the event. The result of this is cached. The trigger check is just a first quick check to determine if the event can be discarded right away - even if the event passes the check, is it possible, that no rule will actually fire.

After the first triggering check passed, the event is handed over to a task which runs in the thread pool. The task uses the rule index to determine all triggering rules. After filtering rules which are out of scope or which are suppressed by other rules, the remaining rules are sorted by their priority and then their action is executed.

A rule action will normally inject new events into the processor which starts the processing cycle again.


For every event there is a monitor following the event. Monitors form trees as the events cascade. Monitor objects hold additional information such as priority (how quickly should the associated event be processed), processing errors, rule scope, as well as context objects.


Rules define the conditions under which a particular action should be executed. Every rule must have the following properties:

  • [Name] A name which identifies the rule.
  • [KindMatch] Match on event kinds: A list of strings in dot notation which describes event kinds. May contain '' characters as wildcards (e.g. core.tests.).
  • [ScopeMatch] Match on event cascade scope: A list of strings in dot notation which describe the required scopes which are required for this rule to trigger. The included / excluded scopes for an event are stored in its monitor.
  • [StateMatch] Match on event state: A simple list of required key / value states in the event state. Nil values can be used as wildcards (i.e. match is only on key).
  • [Priority] Rules are sorted by their priority before their actions are executed.
  • [SuppressionList] A list of rules (identified by their name) which should be suppressed if this rule fires.
  • [Action] A function which will be executed if this rule fires.


Events are injected into the processor and cause rules to fire. An event is a simple object which contains:

  • [Name] A name which identifies the event.
  • [Kind] An event kind - this is checked against the kind match of rules during the triggering check.
  • [State] An event state which contains additional data.

Events are always processed together with a monitor which is either implicitly created or explicitly given together with the event. If the monitor is explicitly given it is possible to specify an event scope which limits the triggering rules and a priority which determines the event processing order. An event with a lower priority is guaranteed to be processed after all events of a higher priority if these have been added before the lower priority event.