slogger

System logger

Syntax:

slogger [-cm] [-f severity] [-l logfile[,size]]
        [-s size] [-u event_id] [-v[v]...]

Runs on:

Neutrino

Options:

-c
Open the log file with O_SYNC to forcibly commit the logged events to the disk.
-f severity
Log only events to the logfile with this severity or higher. This option is useful only with the -l option; slogger always saves all events in its internal buffers. The lowest severity is 7 and the highest is 0. The default is 7.
-l logfile[,size]
Write a copy to logfile of each event that has a severity that's numerically less than or equal to that specified by the -f option. If you specify the optional size after the filename, slogger alternates between two files, logfile0 and logfile1, as the files reach the given size (in kilobytes).
-m
Use CLOCK_MONOTONIC instead of the default CLOCK_REALTIME as the clock source.
-s size
Maintain a circular in-memory log buffer of this size (in kilobytes) to hold system log messages. When the buffer becomes full, the oldest messages are replaced by new ones as they arrive. The default size is 16 KB.
-u event_id
Generate a user-string trace event for all messages received. The given event ID must be in the range from _NTO_TRACE_USERFIRST through _NTO_TRACE_USERLAST, as defined in <sys/trace.h>. For more information, see the System Analysis Toolkit User's Guide, and TraceEvent() in the QNX Neutrino C Library Reference.

The default is not to generate trace events.

-v[v]...
Be verbose; more v characters cause more verbosity.

Description:

The system logger, slogger, is the central manager for logging applications' system messages. It maintains these messages in a circular buffer, allowing them to be read later or in real time. When the buffer fills, new messages replace the oldest ones in the buffer. If you use the -l and -f options, slogger also writes the messages to a log file, as described below.

Each system message is assigned a unique major code, minor code and a severity. The severity levels are as follows:

Manifest Name Value Description
_SLOG_SHUTDOWN 0 Shut down the system NOW (e.g. for OEM use)
_SLOG_CRITICAL 1 Unexpected unrecoverable error (e.g. hard disk error)
_SLOG_ERROR 2 Unexpected recoverable error (e.g. need to reset a hardware controller)
_SLOG_WARNING 3 Expected error (e.g. parity error on a serial port)
_SLOG_NOTICE 4 Warning (e.g. out of paper)
_SLOG_INFO 5 Information (e.g. printing page 3)
_SLOG_DEBUG1 6 Debug messages (e.g. normal detail)
_SLOG_DEBUG2 7 Debug messages (e.g. fine detail)

If you specify the -l logfile option, slogger creates a separate thread that saves to the specified file each system message that's of the severity given in the -f option.

If you use the optional size argument to the -l option, slogger alternates between two files, logfile0 and logfile1. When one file reaches the size given, slogger closes it and opens the other file. This file is truncated to zero length and new messages are written to it until it fills up. The process of alternating then repeats. This way you always have one file containing the latest messages and another file containing the most recent history.

Applications that can't assume that they have a standard console output that's viewable should use slogger for logging notices, warnings and errors. This includes all drivers and resource managers.

The slogger manager creates these devices in the pathname space:

/dev/slog
Used to read and write system log messages.
/dev/console
Implements a simple console tty that saves what you write to it in the system log. Reads always return end-of-file.

Applications wishing to post a new system log message should use the library routines slogb(), slogf(), slogi(), and vslogf(), which properly format the data and issue a write to /dev/slog.

To view the log, use sloginfo. Applications wishing to read system log messages may open /dev/slog for reading and issue read() calls. Each read may return one or more messages, but messages are never split across a read.

More than one application may open /dev/slog for reading at a time. Each sees its own copy of the data and doesn't affect the others. This allows multiple filters, each looking for certain log messages, to be run in parallel. Here's a simple filter that prints codes and severities:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/slog.h>

int main(int argc, char *argv[]) {
    int events[4096];
    int *evp;
    int n;
    int wait = 0;  // Set to 1 to block and print
                   // new events as they arrive.
    int fd;

    fd = open("/dev/slog",
              wait ? O_RDONLY : O_RDONLY|O_NONBLOCK);

    for(;;) {
        int cnt;

        // Read some events.
        n = read(fd, events, sizeof(events));
        if(n == -1) {
            // Normal case for a non-blocking read
            // with no events.
            if(errno == EAGAIN) {
                exit(EXIT_SUCCESS);
            }

            exit(EXIT_FAILURE);
        }

        // Converts bytes to ints (all events are
        // composed of ints).
        n /= sizeof(int);
        if(n == 0)
            break;

        for(evp = events ; evp < &events[n] ;
            evp += cnt) {
            int    major, minor, severity, txt;
            time_t sec;
            char   timebuf[60];

            major    = _SLOG_GETMAJOR(evp[1]);
            minor    = _SLOG_GETMINOR(evp[1]);
            cnt      = _SLOG_GETCOUNT(evp[0]) +
                       _SLOG_HDRINTS;
            severity = _SLOG_GETSEVERITY(evp[0]);
            txt      = _SLOG_GETTEXT(evp[0]);

            sec = evp[2];
            strftime(timebuf, sizeof(timebuf),
                     "%h %d %T", localtime(&sec));
            printf("%s    %d %5d    %2d ", timebuf,
                   severity, major, minor);

            if(txt)
                printf("%s",
                       (char *) &evp[_SLOG_HDRINTS]);
        }

    }

    exit(EXIT_SUCCESS);
}

You can clear the system log buffer by calling unlink("/dev/slog") from a program, or rm /dev/slog from the shell.

If you want to redirect syslogd output to slogger, send the log messages to /dev/console (which slogger monitors) by doing one of the following:

You should start slogger as soon as possible after the system boots (see the Controlling How Neutrino Starts chapter of the Neutrino User's Guide). Otherwise, messages from managers or drivers that were started before it may be lost. If slogger is killed (or never started), all messages that programs send to slogger are lost. If slogger is started or restarted, new messages go to the new slogger.

Examples:

Log system messages:

slogger

Maintain an awesome in-memory buffer for system messages:

slogger -s 100k

In addition to keeping an in-memory buffer, save in a file those system log messages of severity 0, 1, or 2:

slogger -l /var/logs/slogs -f 2

In addition to keeping an in-memory buffer, save all system log messages in a file. Since a size option is specified, the log file alternates between slogs0 and slogs1, switching as each file reaches a size of 100 KB:

slogger -l /var/logs/slogs,100k

See also:

sloginfo

slogb(), slogf(), slogi(), vslogf() in the Neutrino C Library Reference

Controlling How Neutrino Starts in the Neutrino User's Guide