nb.man(7) NodeBrain Administrator Guide
Version 0.8.17 - August 2014



  nodebrain - NodeBrain State and Event Monitoring Agent


  Broad topics are covered by separate manual pages. If you are looking for something more specific than the overview provided here, select the page of interest.

    nodebrain - Overview

nb - Interpreter, Agent, Client, Utility

nb.cfg - Configuration Files

nb.syn - Rule Language Command Syntax

nb.mod - Node Modules (nb_.so plugins)

nb.lib - C API Function Library (libnb.so)

nbkit - Kit Utility

nbkit.caboodle - Kit and Caboodle Framework


  This manual page provides a high level overview of NodeBrain with references to other documentation. These pages are provided primarily as a convenience for Unix and Linux system administrators who may have to deal with NodeBrain in some way on their system, but do not necessarily want to build a new application or write NodeBrain rules. For this reason, the NodeBrain man pages are collectively called the NodeBrain Administrator Guide. Programmers may find it helpful as well. Never hurts to have a few man pages to get oriented.

Programmers and system administrators who what to build a new application or just learn more, should reference documents available online at http://www.nodebrain.org.


  The primary mission of NodeBrain is to be a light-weight event monitoring agent. In this respect, NodeBrain fancies itself to be a tool for creating an event monitoring service like Apache is to web applications and sendmail is to mail delivery. These tools perform a useful service in the background without the user awareness associated with a web browser or mail client. Although the demand for event monitoring is far less obvious than the demand for mail and web services, for those few unlucky folks who need to monitor a stream of events, it would be nice to have a relatively simple, flexible, and free tool. NodeBrain is at least free, and is trying to be simple and flexible---often competing goals.

Secondly, a NodeBrain agent would like to share information with peers. If one agent detects a condition of interest, we want it to be able to report the condition to other agents. This requires network communication via TCP/IP, preferably with options for encryption and peer authentication. This is supported by the peer and message modules distributed with NodeBrain.

Hopefully you are now visualizing a network of agents monitoring local streams of events and reporting interesting conditions (generated events) to peers. But we need a way to get events into these agents other than communication with peer agents. Our real sources of information are external. For this, NodeBrain provides modules supporting multiple methods: servant scripts, FIFO files, queues, log file audit, SNMP traps, syslog, etc. It can use STDIN for a batch job or an interactive client, and in both cases communicate with peers. So NodeBrain is also a client that enables the creation of an event stream into an agent. As a batch job, or utility command, it provides a loosely coupled application interface to the agents. As an interactive client, it provides a primitive line mode user interface to agents.


  Okay, so we have this tinker-toy component that can be used as an agent, an interactive client and a utility program. So now we need a way to describe the conditions we want it to respond to. We need a rule language. Guess what? NodeBrain is a rule language, and nb(1), is the interpreter of this language. Just when you were getting comfortable with the idea that NodeBrain is an event monitoring agent, we claim it is an interpreter. Well, actually any program that processes input is an interpreter to some extent, but NodeBrain is a language you can use to write scripts. Here is a script called HelloWorld.


    ^Hello World

Here we execute it.

    $ ./HelloWorld 2>/dev/null

    Hello World


Imagine a Perl interpreter (you can substitute your favorite interpreter) running as a daemon listening for code to interpret. That is a pretty flexible agent. Perhaps too flexible, but you could write code to impose constraints and structure on the incoming events and the types of actions the agent would be willing to perform for various users or applications. That would just be a Perl implementation of a server of some kind.

So why do we need a new language, this NodeBrain thing? Why do we not just build an agent using an existing interpreter? That seems like a good idea if you can easily do what you want. For example, some people use Prolog as a rule engine. That is nice because of the inferencing capabilities of Prolog. We are just trying to do something slightly different---we think. :) We may have to plead ignorance if proven wrong, but what we are trying to do with NodeBrain does not seem to be a good match for interpretive languages we are familiar with. We should also point out that NodeBrain is not a good substitute for what other interpreters do well. It is good, in the opinion of author, for a relatively specific problem space---the state and event monitoring space. All of our trusty favorite tools can be used in combination with NodeBrain in this problem space.


  Monitoring applications typically watch for, and react to, predefined conditions. Here is a simple reactive NodeBrain script.

    #!/usr/local/bin/nb -p

    define r1 on(a=1 and b=2) x=25;

For simplicity, we are illustrating the concept with an interactive script. In the execution below, user input is highlighted. Normally, assertions will come from external sources.

    $ ./reactor

N o d e B r a i n 0.8.17 (Dopey) 2014-02-15

Compiled Jun 25 2014 16:31:35 s390x-ibm-linux-gnu

Copyright (C) 2014 Ed Trettevik <eat@nodebrain.org>
MIT or Nodebrain License

/usr/local/bin/nb -p ./reactor

Date Time Message
---------- -------- --------------------------------------------
2014-06-27 09:38:03 NB000I NodeBrain nb[23246] me@myserver
2014-06-27 09:38:03 NB000I Argument [1] -p
2014-06-27 09:38:03 NB000I Argument [2] ./reactor
> #!/usr/local/bin/nb -p
> define r1 on(a=1 and b=2) x=25;
2014-06-27 09:38:03 NB000I Source file "./reactor" included. size=57
2014-06-27 09:38:03 NB000I Reading from standard input.
---------- --------

> assert a=1,b=7;

> assert b=2,c=15;
2008/06/27 09:38:34 NB000I Rule r1 fired (x=25)

> show x
x = 25

> quit
2008/06/27 09:38:48 NB000I NodeBrain nb[23246] terminating - exit code=0


  But wait. There is one more thing NodeBrain would like to add to its resume----diagnostic scripting. You should think "baby expert system tool". NodeBrain has a diagnostic mode that enables it to solve for unknown conditions. Here is a trivial and silly example.

    #!/usr/local/bin/nb -p

    define dog on(legs=4 and coat="fur" and tail);

    define cow on(legs=4 and coat="leather" and tail);

    define person on(legs=2 and (coat="skin" or coat="leather"));

    define bird on(legs=2 and coat="feathers" and tail);

    define fish on(!legs and coat="scales" and tail);

Let us call this diagnostic script "creature" and see what happens when we execute it. You should imagine that you are asking NodeBrain, with the help of the defined rules, to assist you in identifying a creature at the edge of a swimming pool. To solve this problem, NodeBrain, requests a little information from you. Your responses and NodeBrain conclusion are highlighted.

    $ ./creature

N o d e B r a i n 0.8.17 (Dopey) 2014-02-15

Compiled Jun 25 2014 16:31:35 s390x-ibm-linux-gnu

Copyright (C) 2014 Ed Trettevik <eat@nodebrain.org>
MIT or Nodebrain License

./nb -p ./creature

Date Time Message
---------- -------- --------------------------------------------
2014-06-27 07:01:37 NB000I NodeBrain nb[22427] me@myserver
2014-06-27 07:01:37 NB000I Argument [1] -p
2014-06-27 07:01:37 NB000I Argument [2] ./creature
> #!./nb -p
> define dog on(legs=4 and coat="fur" and tail);
> define cow on(legs=4 and coat="leather" and tail);
> define person on(legs=2 and (coat="skin" or coat="leather"));
> define bird on(legs=2 and coat="feathers" and tail);
> define fish on(!legs and coat="scales" and tail);
2014-06-27 07:01:37 NB000I Source file "./creature" included. size=274
2014-06-27 07:01:37 NB000I Reading from standard input.

---------- --------

> query




Enter cell legs==2






Enter cell coat=="skin"
2008/06/27 07:01:44 NB000I Rule person fired

> quit
2008/06/27 07:02:02 NB000I NodeBrain nb[22427] terminating - exit code=0

You will notice the user interface is not pretty. This is because we really expect this type of script to run as a batch job and get the answers to the questions automatically, not by asking a user. This is done only for interactive testing of the rules.

The most important thing to notice in the example above is that NodeBrain never asked us what kind of tail our creature has. It did not have to. It was able to select "person" and reject all other possibilities without knowing anything about the tail. This is how doctors and car mechanics diagnose problems without running every possible expensive test---well, if we are lucky. So the idea is for an agent to detect a condition based on rules and spawn a diagnostic script to determine the underlying problem. We want our diagnostic script to be intelligent enough to only run expensive tests when required. The diagnostic script can take action to resolve a problem, if in fact it determines there is a problem, or simply report its findings back to the agent rules for further decision making.


  We have been talking about state and event monitoring without providing a definition. We have been assuming the reader has an intuitive understanding that is close enough to what we mean. Now we will take the risk of making it less clear by attempting an explanation.

The first statement below describes a state, and the second statement describes an event.

    o The sun is out.
    o The sun came out from behind a cloud.

Both statements below describe states, but taken in sequence they describe an event---the same event as the second statement above.

    o The sun is behind a cloud.
    o The sun is out.

In NodeBrain, a state is represented by a unique combination of values in all the cells. Rules are used to monitor the state of specific sets of cells for "interesting" changes in state. A transition to an interesting state is recognized as an event of interest. In this scenario, we might argue that we are doing state monitoring and deriving events.

Now, let us think about it from the perspective of the source of this information. If the sun is behind a cloud, and you want to work in your internal office (no windows) until the sun comes out, you might ask a co-working with a window seat to let you know if the sun comes out from behind a cloud. When the co-worker comes to your office and says "The sun is out", the statement matches our description of a state. But you are both aware the co-working is really reporting an event, "The sun came out from behind a cloud." If you spent 15 minutes trying to finish up what you are working on and the co-worker returns to repeat the statement, "The sun is out", what does this mean? Does it mean the sun is still out, or that it went behind a cloud and came out again? After all, your request of the co-worker was to "let you know if the sun comes out from behind a cloud."

Suppose your request had been for the co-worker to come to your office every 15 minutes and tell you if the sun is out or if it is behind a cloud. Now the common understanding is that the co-worker (who is unreasonably patient with you) is reporting a state, and that you will detect the state change of interest. As an alternative, you might have an agreement that the co-working only report the state when it changes. In that case, the co-working is detecting the state change (an event) and reporting it as a new state, which you also recognize as an event.

As silly as this example is, NodeBrain supports these variations in the protocol between an agent and a peer (or other source of information). As NodeBrain commands, the statements above that report a state might look like this.

    assert sun="behind cloud";

    ... or ...

    assert !sunny; # this could be used if we only have two states

    assert sun="out";

    ... -or ...

    assert sunny;

A NodeBrain rule, for monitoring this state might look like the following, assuming we elect to use the highlighted option above.

    define sunCameOut on(sunny): ... action ...

This rule would respond only twice to the following set of assertions because we are monitoring for a state change to sunny.

    assert sunny; # action taken

    assert sunny;

    assert !sunny;

    assert !sunny;

    assert sunny; # action taken

    assert sunny;

    assert sunny;

The statement used earlier for an event report can also be expressed as a NodeBrain command. For this we use the verb ALERT instead of ASSERT.

    alert type="SunCameOut";

Here is a rule to monitor for this event. We are now using IF instead of ON.

    define sunCameOut if(type="SunCameOut"): ... action ...

This rule would respond three times to the following set of alerts because we are monitoring for events, and this represents three events.

    alert type="SunCameOut";

    alert type="SunCameOut";

    alert type="SunCameOut";

One final point here. Earlier we said an event is a change of state, and that we can monitor states to detect events. It is also true that we can monitor events to detect states.

    define sunCamOut if(type="SunCameOut") sunny;

    define sunHidden if(type="SunWentBehindCloud") !sunny;

The details are not important here, the point is simply that NodeBrain supports both the notion of a state and an event, and can translate between the two. It is very important to be able to recognize a reported event as just further evidence of a known state. If you have a leaky roof, every drip is an event. However, you do not want to call the roof repair company every time you detect a drip---you want to call them once each time the roof transitions into a state of disrepair, as evidenced by your first detection of a drip. Notice we converted from an event (drip) to a state (roof is in disrepair) and monitored for a state change to recognized a higher level event (roof has transitioned to a state of disrepair).


  It may be obvious, but let us comment on the name, "NodeBrain". First the "Brain" part. Like almost every program, nb(1) is a decision maker. In the animal world, as best we understand it, this function is assigned to brains when not overridden by hearts. So we use the term "brain" to identify our program as a generalized decision maker. To counter the notion that we think it is really smart, versions are given code names like "Numskull", "Knucklehead" and "Dunce", at least in prototype versions. The "Node" part has two explanations. First, nb(1) is designed to be an agent in a network of peers. In this model, NodeBrain is a brain that operates as a node within a network of brains. Secondly, an executing instance of nb(1) is a collection of nodes, each with a set of rules and extended functionality provided by a node module. So NodeBrain is a brain composed of nodes in addition to being a node within a network of brains.


  NodeBrain does not actually care how rule files are named, but people generally do. Here are some guidelines. We use *.nb as a generic reference to a file containing NodeBrain commands, but other suffixes may be used to identify the type of rules in a file.

name.nb    Rule file passed as an argument to nb or included from within another rule file. The *.nb suffix may also be used for executable scripts as an alternative to having no extention. It is a preferred alternative on Windows systems.
name    Rule file with shebang ("#!") header to run as a script that might be re-written in a different language. I am not personally keen on "executable" files having extensions that identify the language. Seems silly to have to rename a script and modify all references just because we change the language. But this is the perspective of a lazy programmer.
name.nbx    Text translation rules to convert a foreign text stream into a NodeBrain command steam.



NB_MODULE_PATH    See nb.mod(5).


  See nb(1).


  See nb(1).


  See nb(1).


  Ed Trettevik <eat@nodebrain.org>


  nb(1), nb.cfg(7), nb.syn(5), nb.mod(5), nb.lib(3), nbkit(1), nbkit-caboodle(7)

[1] NodeBrain Home Page

[2] NodeBrain Tutorial

[3] NodeBrain Language Reference

NodeBrain 0.8.17August 2014nb.man(7)