512 lines
20 KiB
ReStructuredText
512 lines
20 KiB
ReStructuredText
======
|
|
SYSLOG
|
|
======
|
|
|
|
|
|
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()``:
|
|
|
|
.. c::function:: int syslog(int priority, FAR const IPTR char *format, ...);
|
|
|
|
Generates a log message. The
|
|
priority argument is formed by ORing the facility and the level
|
|
values (see ``include/syslog.h``). The remaining arguments are a
|
|
format, as in ``printf()`` and any arguments to the format.
|
|
|
|
The NuttX implementation does not support any special formatting
|
|
characters beyond those supported by ``printf()``.
|
|
|
|
.. c::function:: void vsyslog(int priority, FAR const IPTR char *src, va_list ap);
|
|
|
|
Performs the same task as :c:func:`syslog`
|
|
with the difference that it takes a set of arguments which have
|
|
been obtained using the ``stdarg`` variable argument list macros.
|
|
|
|
.. c::function:: int setlogmask(int mask);
|
|
|
|
The additional setlogmask() interface can use use to filter SYSLOG output.
|
|
This function sets the logmask and returns the previous mask.
|
|
If the mask argument is zero, the current logmask is not modified.
|
|
|
|
The SYSLOG priorities are: ``LOG_EMERG``, ``LOG_ALERT``, ``LOG_CRIT``,
|
|
``LOG_ERR``, ``LOG_WARNING``, ``LOG_NOTICE``, ``LOG_INFO``, and ``LOG_DEBUG``.
|
|
The bit corresponding to a priority ``p`` is ``LOG_MASK(p)``; ``LOG_UPTO(p)``
|
|
provides the mask of all priorities in the above list up to and including ``p``.
|
|
|
|
Per *OpenGroup.org* "If the ``maskpri`` argument is 0,
|
|
the current log mask is not modified." In this implementation,
|
|
the value zero is permitted in order to disable all SYSLOG levels.
|
|
|
|
.. note::
|
|
REVISIT: Per POSIX the SYSLOG mask should be a per-process value but
|
|
in NuttX, the scope of the mask is dependent on the nature of the build:
|
|
|
|
- *Flat Build*: There is one, global SYSLOG mask that controls
|
|
all output.
|
|
|
|
- *Protected Build*: There are two SYSLOG masks. One within the
|
|
kernel that controls only kernel output. And one in user-space
|
|
that controls only user SYSLOG output.
|
|
|
|
- *Kernel Build*: The kernel build is compliant with the POSIX
|
|
requirement: There will be one mask for for each user process,
|
|
controlling the SYSLOG output only form that process. There
|
|
will be a separate mask accessible only in the kernel code to
|
|
control kernel SYSLOG output.
|
|
|
|
The above are all standard interfaces as defined at
|
|
`OpenGroup.org <http://pubs.opengroup.org/onlinepubs/009695399/functions/closelog.html>`__.
|
|
Those interfaces are available for use by application software.
|
|
The remaining interfaces discussed in this section are non-standard, OS-internal interfaces.
|
|
|
|
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:
|
|
|
|
- They do not take a priority parameter; the priority is inherent
|
|
in the debug macro name.
|
|
|
|
- They decorate the output stream with information such as the
|
|
file name
|
|
|
|
- They can each be disabled via configuration options.
|
|
|
|
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:
|
|
|
|
- ``info()``. The ``info()`` macro is the lowest priority
|
|
(``LOG_INFO``) and is intended to provide general information
|
|
about the flow of program execution so that you can get an
|
|
overview of the behavior of the program. ``info()`` is often
|
|
very chatty and voluminous and usually more information than
|
|
you may want to see. The ``info()`` macro is controlled via
|
|
CONFIG_DEBUG_subsystem_INFO
|
|
|
|
- ``warn()``. The ``warn()`` macro has medium priority
|
|
(``LOG_WARN``) and is controlled by
|
|
``CONFIG_DEBUG_subsystem_WARN``. The ``warn()`` is intended to
|
|
note exceptional or unexpected conditions that might be
|
|
potential errors or, perhaps, minor errors that easily
|
|
recovered.
|
|
|
|
- ``err()``. This is a high priority debug macro (``LOG_ERROR``)
|
|
and controlled by ``CONFIG_DEBUG_subsystem_ERROR``. The
|
|
``err()`` is reserved to indicate important error conditions.
|
|
|
|
- ``alert()``. The highest priority debug macro (``LOG_EMERG``)
|
|
and is controlled by ``CONFIG_DEBUG_ALERT``. The ``alert()``
|
|
macro is reserved for use solely by assertion and crash
|
|
handling logic. It also differs from the other macros in that
|
|
it cannot be enabled or disabled per subsystem.
|
|
|
|
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``:
|
|
|
|
.. code-block:: c
|
|
|
|
/* 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
|
|
:c:func:`syslog_channel()`.
|
|
|
|
.. c:function:: int syslog_channel(FAR const struct syslog_channel_s *channel);
|
|
|
|
Configure the SYSLOG function to use the provided
|
|
channel to generate SYSLOG output.
|
|
|
|
``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``).
|
|
|
|
:param channel: Describes the interface to the channel to be used.
|
|
|
|
:return:
|
|
Zero (OK)is returned on success. A negated errno value is
|
|
returned on any failure.
|
|
|
|
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:
|
|
|
|
- *In-Memory Buffer (RAMLOG)*. Full SYSLOG capability as
|
|
available at reset.
|
|
|
|
- *Serial Console*. If the serial implementation provides the
|
|
low-level character output function ``up_putc()``, then that
|
|
low level serial output is available as soon as the serial
|
|
device has been configured.
|
|
|
|
- For all other SYSLOG channels, all SYSLOG output goes to the
|
|
bit- bucket until the SYSLOG channel device has been
|
|
initialized.
|
|
|
|
The syslog channel device is initialized when the bring-up logic
|
|
calls :c:func:`syslog_initialize()`.
|
|
|
|
.. c:function:: int syslog_initialize(void)
|
|
|
|
.. code-block:: c
|
|
|
|
#include <nuttx/syslog/syslog.h>
|
|
#ifndef CONFIG_ARCH_SYSLOG
|
|
int syslog_initialize(void);
|
|
#else
|
|
# define syslog_initialize()
|
|
#endif
|
|
|
|
One power up, the SYSLOG facility is non-existent
|
|
or limited to very low-level output. This function is called later
|
|
in the initialization sequence after full driver support has been
|
|
initialized. It installs the configured SYSLOG drivers and enables
|
|
full SYSLOG capability.
|
|
|
|
This function performs these basic operations:
|
|
|
|
- Initialize the SYSLOG device
|
|
|
|
- Call :c:func:`syslog_channel` to begin using that device.
|
|
|
|
- If ``CONFIG_ARCH_SYSLOG`` is selected, then the
|
|
architecture-specific logic will provide its own SYSLOG device
|
|
initialize which must include as a minimum a call to
|
|
:c:func:`syslog_channel` to use the device.
|
|
|
|
:return:
|
|
Zero (``OK``) is returned on success; a
|
|
negated ``errno`` value is returned on any failure.
|
|
|
|
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.
|
|
|
|
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``) and if the underlying
|
|
architecture supports the low-level ``up_putc()``
|
|
interface(\ ``CONFIG_ARCH_LOWPUTC``), then the SYSLOG 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:
|
|
|
|
- ``up_putc()`` is able to generate debug output in any
|
|
context because it disables serial interrupts and polls the
|
|
hardware directly. These polls may take many milliseconds
|
|
and during that time, all interrupts are disable within the
|
|
interrupt handler. This, of course, interferes with the
|
|
real-time behavior of the RTOS.
|
|
|
|
- The output generated by ``up_putc()`` is immediate and in
|
|
real-time. The normal SYSLOG output, on the other hand, is
|
|
buffered in the serial driver and may be delayed with
|
|
respect to the immediate output by many lines. Therefore,
|
|
the interrupt level SYSLOG output provided through
|
|
``up_putc()`` is grossly out of synchronization with other
|
|
debug output
|
|
|
|
#. **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 of an
|
|
*interrupt buffer* to buffer the interrupt level SYSLOG output.
|
|
In this case:
|
|
|
|
- SYSLOG output generated from interrupt level process in not
|
|
sent to the SYSLOG channel immediately. Rather, it is
|
|
buffered in the interrupt serialization buffer.
|
|
|
|
- Later, when the next normal syslog output is generated, it
|
|
will first empty the content of the interrupt buffer to the
|
|
SYSLOG device in the proper context. It will then be
|
|
followed by the normal syslog output. In this case, the
|
|
interrupt level SYSLOG output will interrupt the normal
|
|
output stream and the interrupt level SYSLOG output will be
|
|
inserted into the correct position in the SYSLOG output when
|
|
the next normal SYSLOG output is generated.
|
|
|
|
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:
|
|
|
|
- ``CONFIG_DEV_CONSOLE``. This setting indicates that the system
|
|
supports a console device, i.e., that the character device
|
|
``/dev/console`` exists.
|
|
|
|
- ``CONFIG_SERIAL_CONSOLE``. This configuration option is
|
|
automatically selected when a UART or USART is configured as
|
|
the system console. There is no user selection.
|
|
|
|
- ``CONFIG_SYSLOG_CONSOLE``. This configuration option is
|
|
manually selected from the SYSLOG menu. This is the option that
|
|
actually enables the SYSLOG console device. It depends on
|
|
``CONFIG_DEV_CONSOLE``.
|
|
|
|
- ``CONFIG_ARCH_LOWPUTC``. This is an indication from the
|
|
architecture configuration that the platform supports the
|
|
``up_putc()`` interface. ``up_putc()`` is a very low level UART
|
|
interface that can even be used from interrupt handling.
|
|
|
|
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 from the SYSLOG console
|
|
channel include:
|
|
|
|
- ``CONFIG_SYSLOG_DEVPATH``. This configuration option string
|
|
must be set provide the full path to the character device to be
|
|
used.
|
|
|
|
- The forced SYSLOG output always goes to the bit-bucket. This
|
|
means that interrupt level SYSLOG output will be lost unless
|
|
the interrupt buffer is enabled to support serialization.
|
|
|
|
- ``CONFIG_SYSLOG_CHAR_CRLF``. If ``CONFIG_SYSLOG_CHAR_CRLF`` is
|
|
selected, then linefeeds in the SYSLOG output will be expanded
|
|
to Carriage Return plus Linefeed. Since the character device is
|
|
not a console device, the addition of carriage returns to line
|
|
feeds would not be performed otherwise. You would probably want
|
|
this expansion if you use a serial terminal program with the
|
|
character device output.
|
|
|
|
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:
|
|
|
|
.. c:function:: int syslog_file_channel(FAR const char *devpath);
|
|
|
|
Configure to use a file in a mounted file system
|
|
at ``devpath`` as the SYSLOG channel.
|
|
|
|
This tiny function is simply a wrapper around
|
|
``syslog_dev_initialize()`` and ``syslog_channel()``. It calls
|
|
``syslog_dev_initialize()`` to configure the character file at
|
|
``devpath`` then calls ``syslog_channel()`` to use that device as
|
|
the SYSLOG output channel.
|
|
|
|
File SYSLOG channels differ from other SYSLOG channels in that
|
|
they cannot be established until after fully booting and mounting
|
|
the target file system. This function would need to be called from
|
|
board-specific bring-up logic AFTER mounting the file system
|
|
containing ``devpath``.
|
|
|
|
SYSLOG data generated prior to calling ``syslog_file_channel()``
|
|
will, of course, not be included in the file.
|
|
|
|
NOTE interrupt level SYSLOG output will be lost in this case
|
|
unless the interrupt buffer is used.
|
|
|
|
:param devpath:
|
|
The full path to the file to be used for SYSLOG
|
|
output. This may be an existing file or not. If the file
|
|
exists, ``syslog_file_channel()`` will append new SYSLOG data
|
|
to the end of the file. If it does not, then
|
|
``syslog_file_channel()`` will create the file.
|
|
|
|
:return:
|
|
Zero (``OK``) is returned on success; a
|
|
negated ``errno`` value is returned on any failure.
|
|
|
|
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`` command
|
|
-----------------
|
|
|
|
When the RAMLOG (with SYSLOG) is enabled, a new NuttShell (NSH)
|
|
command will appear: ``dmesg``. The ``dmesg`` command will dump
|
|
the contents of the circular buffer to the console (and also clear
|
|
the circular buffer).
|
|
|
|
RAMLOG Configuration options
|
|
----------------------------
|
|
|
|
- ``CONFIG_RAMLOG``: Enables the RAM logging feature
|
|
|
|
- ``CONFIG_RAMLOG_SYSLOG``: Use the RAM logging device for the
|
|
SYSLOG interface. If this feature is enabled, then all debug
|
|
output will be re-directed to the circular buffer in RAM. This
|
|
RAM log can be viewed from NSH using the ``dmesg`` command.
|
|
NOTE: Unlike the limited, generic character driver SYSLOG
|
|
device, the RAMLOG *can* be used to capture debug output from
|
|
interrupt level handlers.
|
|
|
|
- ``CONFIG_RAMLOG_NPOLLWAITERS``: The number of threads than can
|
|
be waiting for this driver on ``poll()``. Default: 4
|
|
|
|
- ``CONFIG_RAMLOG_BUFSIZE``: The size of the circular buffer to
|
|
use. Default: 1024 bytes.
|
|
|
|
Other miscellaneous settings
|
|
|
|
- ``CONFIG_RAMLOG_CRLF``: Pre-pend a carriage return before every
|
|
linefeed that goes into the RAM log.
|
|
|
|
- ``CONFIG_RAMLOG_NONBLOCKING``: Reading from the RAMLOG will
|
|
never block if the RAMLOG is empty. If the RAMLOG is empty,
|
|
then zero is returned (usually interpreted as end-of-file). If
|
|
you do not define this, the NSH ``dmesg`` command will lock up
|
|
when called! So you probably do want this!
|
|
|
|
- ``CONFIG_RAMLOG_NPOLLWAITERS``: The maximum number of threads
|
|
that may be waiting on the poll method.
|