SYSLOG Interfaces

Standard SYSLOG Interfaces

The NuttX SYSLOG is an architecture for getting debug and status information from the system. The syslogging interfaces are defined in the header file include/syslog.h. The primary interface to SYSLOG sub-system is the function syslog() and, to a lesser extent, its companion vsyslog():

    /****************************************************************************
    
    int syslog(int priority, FAR const IPTR char *format, ...);
    int vsyslog(int priority, FAR const IPTR char *src, va_list ap);

The additional setlogmask() interface can use use to filter SYSLOG output:

    /****************************************************************************
    
    int setlogmask(int mask);

These are all standard interfaces as defined at OpenGroup.org.

Debug Interfaces

In NuttX, syslog output is really synonymous to debug output and, therefore, the debugging interface macros defined in the header file include/debug.h are also syslogging interfaces. Those macros are simply wrappers around syslog(). The debugging interfaces differ from the syslog interfaces in that:

Each debug macro has a base name that represents the priority and a prefix that represents the sub-system. Each macro is individually initialized by both priority and sub-system. For example, uerr() is the macro used for error level messages from the USB subsystem and is enabled with CONFIG_DEBUG_USB_ERROR.

The base debug macro names, their priority, and configuration variable are summarized below:

SYSLOG Channels

SYSLOG Channel Interfaces

In the NuttX SYSLOG implementation, the underlying device logic the supports the SYSLOG output is referred to as a SYSLOG channel. Each SYSLOG channel is represented by an interface defined in include/nuttx/syslog/syslog.h:

    /* This structure provides the interface to a SYSLOG device */
    
    typedef CODE int (*syslog_putc_t)(int ch);
    typedef CODE int (*syslog_flush_t)(void);
    
    struct syslog_channel_s
    {
      /* I/O redirection methods */
    
      syslog_putc_t sc_putc;    /* Normal buffered output */
      syslog_putc_t sc_force;   /* Low-level output for interrupt handlers */
      syslog_flush_t sc_flush;  /* Flush buffered output (on crash) */
    
      /* Implementation specific logic may follow */
    };

The channel interface is instantiated by calling syslog_channel():

    /****************************************************************************
    
    int syslog_channel(FAR const struct syslog_channel_s *channel);

syslog_channel() is a non-standard, internal OS interface and is not available to applications. It may be called numerous times as necessary to change channel interfaces. By default, all system log output goes to console (/dev/console).

SYSLOG Channel Initialization

The initial, default SYSLOG channel is established with statically initialized global variables so that some level of SYSLOG output may be available immediately upon reset. This initialized data is in the file drivers/syslog/syslog_channel.c. The initial SYSLOG capability is determined by the selected SYSLOG channel:

The syslog channel device is initialized when the bring-up logic calls syslog_intialize():

    /****************************************************************************
    
    #ifndef CONFIG_ARCH_SYSLOG
    int syslog_initialize(enum syslog_init_e phase);
    #else
    #  define syslog_initialize(phase)
    #endif

Different types of SYSLOG devices have different OS initialization requirements. Some are available immediately at reset, some are available after some basic OS initialization, and some only after OS is fully initialized. In order to satisfy these different initialization requirements, syslog_initialize() is called twice from the boot-up logic:

There are other types of SYSLOG channel devices that may require even further initialization. For example, the file SYSLOG channel (described below) cannot be initialized until the necessary file systems have been mounted.

Interrupt Level SYSLOG Output

As a general statement, SYSLOG output only supports normal output from NuttX tasks. However, for debugging purposes, it is also useful to get SYSLOG output from interrupt level logic. In an embedded system, that is often where the most critical operations are performed.

There are three conditions under which SYSLOG output generated from interrupt level processing can a included the SYSLOG output stream:

Low-Level Serial Output. If you are using a SYSLOG console channel (CONFIG_SYSLOG_CONSOLE) with a serial console (CONFIG_SYSLOG_SERIAL_CONSOLE) and if the underlying architecture supports the low-level up_putc() interface(CONFIG_ARCH_LOWPUTC), then the SYLOG logic will direct the output to up_putc() which is capable of generating the serial output within the context of an interrupt handler.

There are a few issues in doing this however:

In-Memory Buffering. If the RAMLOG SYSLOG channel is supported, then all SYSLOG output is buffered in memory. Interrupt level SYSLOG output is no different than normal SYSLOG output in this case.

Serialization Buffer. A final option is the use the an interrupt buffer to buffer the interrupt level SYSLOG output. In this case:

The SYSLOG interrupt buffer is enabled with CONFIG_SYSLOG_INTBUFFER. When the interrupt buffer is enabled, you must also provide the size of the interrupt buffer with CONFIG_SYSLOG_INTBUFSIZE.

SYSLOG Channel Options

SYSLOG Console Device

The typical SYSLOG device is the system console. If you are using a serial console, for example, then the SYSLOG output will appear on that serial port.

This SYSLOG channel is automatically selected by syslog_initialize() in the LATE initialization phase based on configuration options. The configuration options that affect this channel selection include:

Interrupt level SYSLOG output will be lost unless: (1) the interrupt buffer is enabled to support serialization, or (2) a serial console is used and up_putc() is supported.

NOTE: The console channel uses the fixed character device at /dev/console. The console channel is not synonymous with stdout (or file descriptor 1). stdout is the current output from a task when, say, printf() if used. Initially, stdout does, indeed, use the /dev/console device. However, stdout may subsequently be redirected to some other device or file. This is always the case, for example, when a transient device is used for a console – such as a USB console or a Telnet console. The SYSLOG channel is not redirected as stdout is; the SYSLOG channel will stayed fixed (unless it is explicitly changed via syslog_channel()).

References: drivers/syslog/syslog_consolechannel.c and drivers/syslog/syslog_device.c

SYSLOG Character Device

The system console device, /dev/console, is a character driver with some special properties. However, any character driver may be used as the SYSLOG output channel. For example, suppose you have a serial console on /dev/ttyS0 and you want SYSLOG output on /dev/ttyS1. Or suppose you support only a Telnet console but want to capture debug output /dev/ttyS0.

This SYSLOG device channel is selected with CONFIG_SYSLOG_CHAR and has no other dependencies. Differences fromthe SYSLOG console channel include:

References: drivers/syslog/syslog_devchannel.c and drivers/syslog/syslog_device.c

SYSLOG File Device

Files can also be used as the sink for SYSLOG output. There is, however, a very fundamental difference in using a file as opposed the system console, a RAM buffer, or character device: You must first mount the file system that supports the SYSLOG file. That difference means that the file SYSLOG channel cannot be supported during the boot-up phase but can be instantiated later when board level logic configures the application environment, including mounting of the file systems.

The interface syslog_file_channel() is used to configure the SYSLOG file channel:

    /****************************************************************************
    
    #ifdef CONFIG_SYSLOG_FILE
    int syslog_file_channel(FAR const char *devpath);
    #endif
    

References: drivers/syslog/syslog_filechannel.c, drivers/syslog/syslog_device.c, and include/nuttx/syslog/syslog.h.

SYSLOG RAMLOG Device

The RAMLOG is a standalone feature that can be used to buffer any character data in memory. There are, however, special configurations that can be used to configure the RAMLOG as a SYSLOG channel. The RAMLOG functionality is described in a more general way in the following paragraphs.

RAM Logging Device

The RAM logging driver is a driver that was intended to support debugging output (SYSLOG) when the normal serial output is not available. For example, if you are using a Telnet or USB serial console, the debug output will get lost – or worse. For example, what if you want to debug the network over Telnet?

The RAM logging driver can also accept debug output data from interrupt handler with no special serialization buffering. As an added benefit, the RAM logging driver is much less invasive. Since no actual I/O is performed with the debug output is generated, the RAM logger tends to be much faster and will interfere much less when used with time critical drivers.

The RAM logging driver is similar to a pipe in that it saves the debugging output in a circular buffer in RAM. It differs from a pipe in numerous details as needed to support logging.

This driver is built when CONFIG_RAMLOG is defined in the Nuttx configuration.

dmesg

When the RAMLOG (with SYSLOG) is enabled, a new NuttShell (NSH) command will appear: dmesg. The dmsg command will dump the contents of the circular buffer to the console (and also clear the circular buffer).

RAMLOG Configuration options

If CONFIG_RAMLOG_CONSOLE or CONFIG_RAMLOG_SYSLOG is selected, then the following must also be provided:

Other miscellaneous settings

SYSLOG (Input) Character Device

If the option CONFIG_SYSLOG_CHARDEV is selected then support for a special character device at /dev/syslog is supported. The function {{ syslog_register()}} can be used to register that character device:

    /****************************************************************************
    
    void syslog_register(void);

Careful... there is overloaded naming here! A character device can serve as the SYSLOG output channel as described above. There we were referring to a data path like: syslog() -> SYSLOG channel layer -> Character driver output channel.

Here we are talking about a different SYSLOG character devices that provides input data to the SYSLOG channel. That is a data path like: SYSLOG Character driver -> SYSLOG channel layer -> Output channel. Very confusing and begs for some re-naming.