Thruk, NagVis and Checkmk are part of a whole ecosystem of consoles that
speaks MK Livestatus (LQL) to read a monitoring engine's state without
caring what that engine actually is. jaque implements that protocol, so those tools
point at it without a single config change on their side. What it costs:
Livestatus inherits the protocol's own gaps, the wait headers
(WaitTrigger, WaitCondition, WaitObject, WaitTimeout) and the
statehist table.
1. Turning it on
Two flags, both empty (protocol off) by default:
-livestatus-listen 127.0.0.1:6557 # TCP
-livestatus-socket /tmp/jaque-livestatus.sock # UNIX socket
Either or both can be set at once.
printf 'GET status\nOutputFormat: json\n\n' | nc -U /tmp/jaque-livestatus.sock
2. What it reads from
Its own projection of the event log, in parallel with the dashboard's: same mechanism, separate consumer, so a Livestatus client never blocks or is blocked by the dashboard.
3. The tables
Eleven tables: hosts, services, hostgroups, servicegroups,
contacts, downtimes, comments, status, timeperiods, log, plus
the meta-table columns describing all of them. Filtering, Stats:
aggregation (sum/min/max/avg), and both output formats (csv,
the Nagios default, and json) are supported.
hosts and services carry notifications_enabled; contacts
carries host_notifications_enabled and service_notifications_enabled;
status.enable_notifications reports the program-wide toggle.
hosts and services also carry active_checks_enabled (0 for a
passive object or one with active checks stopped),
accept_passive_checks (always 1), flap_detection_enabled (its own
check configured with flap detection on, and not stopped) and
event_handler_enabled (a handler configured, and not stopped), each
folding the object's own switch into its configuration. status reads
execute_host_checks, execute_service_checks, enable_flap_detection
and enable_event_handlers from the program-wide switches, and
check_host_freshness and check_service_freshness from the
configuration. accept_passive_host_checks,
accept_passive_service_checks, check_external_commands and
process_performance_data have no switch, so they always read 1.
obsess_over_hosts and obsess_over_services always read 0.
comments carries user comments (entry_type 1) beside the
acknowledgement (4) and downtime (2) rows. timeperiods carries one row
per configured
timeperiod (name, alias, in); hosts and services gain
check_period, notification_period, in_check_period and
in_notification_period, and contacts gains
host_notification_period and service_notification_period, the
contact's one notification_period reported under both.
downtimes gains fixed (1 for a fixed downtime, 0 for any other kind),
duration (seconds, set only on a flexible downtime), triggered_by
(the downtime ID a triggered downtime names, empty otherwise) and type
(0 while the downtime is currently in effect, 1 otherwise), on top of the
Nagios columns the table already carried. A recurring
downtime is not scheduled, so it has no row of
its own to read back; instead the table adds one row per object per
recurring downtime, for whichever occurrence is currently in effect or
the next one. scheduled_downtime_depth on hosts and services counts
downtimes actually in effect right now, scheduled and recurring alike,
rather than every downtime on file for the object.
GET services
Filter: state = 2
Stats: state = 2
OutputFormat: json
4. The log table
log holds twelve kinds of row, each in Nagios's own message format,
so a console that already parses Nagios's log understands jaque's rows
unchanged:
| Class | Type | Message |
|---|---|---|
| 0 | HOST EVENT HANDLER / SERVICE EVENT HANDLER |
host;svc;STATE;trigger;handler;status |
| 1 | HOST ALERT / SERVICE ALERT |
host;svc;STATE;HARD or SOFT;attempt;output |
| 1 | HOST FLAPPING ALERT / SERVICE FLAPPING ALERT |
host;svc;STARTED; or host;svc;STOPPED; |
| 1 | HOST ACKNOWLEDGE ALERT / SERVICE ACKNOWLEDGE ALERT |
host;svc;STARTED;author;comment |
| 1 | HOST ACKNOWLEDGE ALERT / SERVICE ACKNOWLEDGE ALERT |
host;svc;EXPIRED;author; |
| 1 | HOST DOWNTIME ALERT / SERVICE DOWNTIME ALERT |
host;svc;STARTED; |
| 1 | HOST DOWNTIME ALERT / SERVICE DOWNTIME ALERT |
host;svc;STOPPED; |
| 2 | CONFIG RELOAD |
generation;added;removed;changed |
| 2 | CONFIG RELOAD REJECTED |
the rejection reason |
| 3 | HOST NOTIFICATION / SERVICE NOTIFICATION |
contact;host;svc;STATE;;output |
| 4 | PASSIVE HOST CHECK / PASSIVE SERVICE CHECK |
host;svc;code;output |
| 5 | EXTERNAL COMMAND or EXTERNAL COMMAND REJECTED |
the verb, then the command's fields or the rejection reason |
A host row's service slot is empty and the separator stays, so a parser
built for Nagios's own log still finds the field it expects. STATE is
the Nagios word (UP, DOWN, OK, WARNING, CRITICAL, UNKNOWN).
log is a ring of -livestatus-log-cache entries, refilled from the
event log every time the process starts and kept current after that.
History older than the ring holds is not here: it lives in the events
sink, when one is configured.
Class 5, the EXTERNAL COMMAND rows, comes from the audit log rather
than the ring, so it goes back as far as the audit log itself retains.
5. Commands
A COMMAND line is the same one line the external command
FIFO accepts: [<unix_ts>] VERB;field;field, parsed the same way, with the same verbs and the
same field validation. A successful command gets an empty answer, as
Nagios's own Livestatus does. A line that fails to parse answers 400
with the parse error; a process with no command sink wired (-read-only
set) answers 403; an audit log that cannot take the record answers 503,
since a command with no audit record does not run.
Every COMMAND, accepted or not, is written to the audit log with the
connection's peer address and no principal: the protocol carries no
identity. Section 8 covers what accepting commands means for a
listener reachable beyond a trusted network.
6. Verified against a real client
The status table implements all 20 columns Thruk's connect probe
(get_processinfo) actually requests, taken from Thruk's own traffic
rather than inferred from reading the LQL spec. The exact request/response
sequence Thruk sends on connect is pinned in a replay test against real
Thruk traffic: it is checked against what a production Nagios console does
the moment it connects.
7. Who can read it
Any console that already knows how to talk Livestatus, such as Thruk, NagVis, Checkmk or WOCU, can point at a jaque instance and read its state without modifying its own configuration at all. Combined with the exec plugin protocol and the FIFO, this is the third leg that lets an existing Nagios-adjacent toolchain keep functioning unmodified while the engine underneath changes.
8. Security considerations
As in the original Livestatus protocol, the wire format carries no
authentication: anything that can reach the socket can read full state.
-livestatus-listen should bind a trusted interface rather than
0.0.0.0, and -livestatus-socket should rely on filesystem permissions
to keep the socket restricted: the protocol offers no door of its own to
lock.
Both listeners accept COMMAND too, so a reachable TCP listener is a
command surface. See Security considerations
for what that means and how -read-only removes it.