This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 22ab1280ae0e657efec4c2190b294708c14a3788 Author: Marco Casaroli <[email protected]> AuthorDate: Thu Oct 29 20:25:50 2026 +0100 drivers/syslog: Let a channel drop messages by priority. setlogmask() selects the messages for all syslog channels together, and a channel gets only the bytes of a message, not its priority. Thus the console cannot show only the urgent messages while the RAMLOG keeps all of them. The new option SYSLOG_DROPMASK (default n) gives struct syslog_channel_s the field sc_dropmask: an OR of LOG_MASK() values, the priorities that the channel does not write. Zero writes all messages. nx_vsyslog() gives the priority of the message to the syslog stream, and the stream writes with the new syslog_write_priority(). Output without a priority (syslog_write(), the interrupt buffer) goes to all channels, as before. A channel that drops a message counts as a full write, so the write does not fail with -EIO when all channels drop it. The new option SYSLOG_CONSOLE_LEVEL sets the mask of the console channels (SYSLOG_DEFAULT and SYSLOG_CONSOLE). The default 7 writes all messages. Without SYSLOG_DROPMASK the behavior is the same as before; only the priority argument of syslog_write_foreach() stays (8 to 32 bytes of text). The change is the same in the flat, protected and kernel builds and has no architecture code. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- drivers/syslog/Kconfig | 26 ++++++++++ drivers/syslog/syslog.h | 23 +++++++-- drivers/syslog/syslog_channel.c | 6 +++ drivers/syslog/syslog_consolechannel.c | 6 +++ drivers/syslog/syslog_intbuffer.c | 4 +- drivers/syslog/syslog_write.c | 91 ++++++++++++++++++++++++++-------- drivers/syslog/vsyslog.c | 6 +++ drivers/syslog/vsyslog_rfc5424.c | 6 +++ include/nuttx/streams.h | 3 ++ include/nuttx/syslog/syslog.h | 40 +++++++++++++++ libs/libc/stream/lib_syslograwstream.c | 21 ++++++-- 11 files changed, 203 insertions(+), 29 deletions(-) diff --git a/drivers/syslog/Kconfig b/drivers/syslog/Kconfig index 30a87feddda..42b7ccd7ac8 100644 --- a/drivers/syslog/Kconfig +++ b/drivers/syslog/Kconfig @@ -72,6 +72,15 @@ config SYSLOG_MAX_CHANNELS ---help--- Maximum number of supported SYSLOG channels. +config SYSLOG_DROPMASK + bool "Channels can drop messages by priority" + default n + ---help--- + Each SYSLOG channel gets a mask of the message priorities that it + does not write (sc_dropmask). For example, the console can write + only the urgent messages while the RAMLOG keeps all of them. See + SYSLOG_CONSOLE_LEVEL. + config RAMLOG bool "RAM log device support" default n @@ -352,6 +361,23 @@ config SYSLOG_DEFAULT syslog() interfaces will be present, but all output will go to the up_putc(ARCH_LOWPUTC == y) or bit-bucket(ARCH_LOWPUTC == n). +config SYSLOG_CONSOLE_LEVEL + int "Lowest message priority on the console" + default 7 + range 0 7 + depends on SYSLOG_DROPMASK + depends on SYSLOG_DEFAULT || SYSLOG_CONSOLE + ---help--- + The console channels (SYSLOG_DEFAULT and SYSLOG_CONSOLE) write + only the messages of this priority and of the more urgent + priorities: 0 is LOG_EMERG, 3 is LOG_ERR, 7 is LOG_DEBUG. The + other channels (for example the RAMLOG) get all messages. With + 7 (the default), the console gets all messages. + + A message that comes without a priority (for example a write to + /dev/log or output that the interrupt buffer saved) goes to all + channels. + endif if RAMLOG_SYSLOG diff --git a/drivers/syslog/syslog.h b/drivers/syslog/syslog.h index 2f039e32272..e6d65b44f80 100644 --- a/drivers/syslog/syslog.h +++ b/drivers/syslog/syslog.h @@ -30,6 +30,7 @@ #include <nuttx/config.h> #include <stdbool.h> +#include <stdint.h> #include <stdio.h> #include <syslog.h> @@ -37,6 +38,17 @@ #include <nuttx/sched.h> #include <nuttx/tls.h> +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The message priorities that the console channels do not write */ + +#ifdef CONFIG_SYSLOG_CONSOLE_LEVEL +# define SYSLOG_CONSOLE_DROPMASK \ + ((uint8_t)~LOG_UPTO(CONFIG_SYSLOG_CONSOLE_LEVEL)) +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -295,9 +307,12 @@ void syslog_flush_intbuffer(bool force); * one character at a time. * * Input Parameters: - * buffer - The buffer containing the data to be output - * buflen - The number of bytes in the buffer - * force - Use the force() method of the channel vs. the putc() method. + * priority - The priority of the message, or SYSLOG_PRIORITY_NONE. + * A channel does not write the data if its sc_dropmask has + * the bit of the priority. + * buffer - The buffer containing the data to be output + * buflen - The number of bytes in the buffer + * force - Use the force() method of the channel vs. the putc() method. * * Returned Value: * On success, the number of characters written is returned. A negated @@ -305,7 +320,7 @@ void syslog_flush_intbuffer(bool force); * ****************************************************************************/ -ssize_t syslog_write_foreach(FAR const char *buffer, +ssize_t syslog_write_foreach(int priority, FAR const char *buffer, size_t buflen, bool force); #endif /* CONFIG_SYSLOG */ diff --git a/drivers/syslog/syslog_channel.c b/drivers/syslog/syslog_channel.c index 9519c7cbcd6..6981fdff91a 100644 --- a/drivers/syslog/syslog_channel.c +++ b/drivers/syslog/syslog_channel.c @@ -179,6 +179,12 @@ static syslog_channel_t g_default_channel = # ifdef CONFIG_SYSLOG_IOCTL , "default" # endif +# ifdef CONFIG_SYSLOG_CONSOLE_LEVEL +# if defined(CONFIG_SYSLOG_IOCTL) || defined(CONFIG_SYSLOG_CRLF) + , 0 +# endif + , SYSLOG_CONSOLE_DROPMASK +# endif }; #endif diff --git a/drivers/syslog/syslog_consolechannel.c b/drivers/syslog/syslog_consolechannel.c index bd53d7cce2e..8e9c8e827ab 100644 --- a/drivers/syslog/syslog_consolechannel.c +++ b/drivers/syslog/syslog_consolechannel.c @@ -87,6 +87,12 @@ FAR syslog_channel_t *syslog_console_channel(void) return NULL; } +#ifdef CONFIG_SYSLOG_CONSOLE_LEVEL + /* The console writes only the urgent messages */ + + console_channel->sc_dropmask = SYSLOG_CONSOLE_DROPMASK; +#endif + /* Use the character driver as the SYSLOG channel */ if (syslog_channel_register(console_channel) != OK) diff --git a/drivers/syslog/syslog_intbuffer.c b/drivers/syslog/syslog_intbuffer.c index ec639a88425..b6beb3a0387 100644 --- a/drivers/syslog/syslog_intbuffer.c +++ b/drivers/syslog/syslog_intbuffer.c @@ -109,7 +109,7 @@ static void syslog_flush_internal(bool force, size_t buflen) if (size > 0) { size = (size >= buflen) ? buflen : size; - syslog_write_foreach(buffer, size, force); + syslog_write_foreach(SYSLOG_PRIORITY_NONE, buffer, size, force); circbuf_readcommit(&g_syslog_intbuffer.circ, size); buflen -= size; } @@ -167,7 +167,7 @@ void syslog_add_intbuffer(FAR const char *buffer, size_t buflen) { syslog_flush_internal(true, sizeof(g_syslog_intbuffer.buffer)); space = buflen - sizeof(g_syslog_intbuffer.buffer); - syslog_write_foreach(buffer, space, true); + syslog_write_foreach(SYSLOG_PRIORITY_NONE, buffer, space, true); circbuf_write(&g_syslog_intbuffer.circ, buffer + space, buflen - space); } diff --git a/drivers/syslog/syslog_write.c b/drivers/syslog/syslog_write.c index 51ac92d6363..8a86e2074e1 100644 --- a/drivers/syslog/syslog_write.c +++ b/drivers/syslog/syslog_write.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include <assert.h> +#include <syslog.h> #include <nuttx/arch.h> #include <nuttx/sched.h> @@ -79,6 +80,34 @@ static bool syslog_safe_to_block(void) return true; } +/**************************************************************************** + * Name: syslog_write_internal + ****************************************************************************/ + +static ssize_t syslog_write_internal(int priority, FAR const char *buffer, + size_t buflen) +{ + bool force = !syslog_safe_to_block(); + +#ifdef CONFIG_SYSLOG_INTBUFFER + if (force) + { + syslog_add_intbuffer(buffer, buflen); + return buflen; + } + else + { + /* Flush any characters that may have been added to the interrupt + * buffer. + */ + + syslog_flush_intbuffer(false); + } +#endif + + return syslog_write_foreach(priority, buffer, buflen, force); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -92,8 +121,10 @@ static bool syslog_safe_to_block(void) * one character at a time. * * Input Parameters: - * buffer - The buffer containing the data to be output - * buflen - The number of bytes in the buffer + * priority - The priority of the message, or SYSLOG_PRIORITY_NONE + * buffer - The buffer containing the data to be output + * buflen - The number of bytes in the buffer + * force - Use the force() method of the channel vs. the putc() method * * Returned Value: * On success, the number of characters written is returned. A negated @@ -101,7 +132,7 @@ static bool syslog_safe_to_block(void) * ****************************************************************************/ -ssize_t syslog_write_foreach(FAR const char *buffer, +ssize_t syslog_write_foreach(int priority, FAR const char *buffer, size_t buflen, bool force) { syslog_write_t write; @@ -127,6 +158,17 @@ ssize_t syslog_write_foreach(FAR const char *buffer, } #endif +#ifdef CONFIG_SYSLOG_DROPMASK + /* A channel that drops this priority takes the whole message */ + + if (priority != SYSLOG_PRIORITY_NONE && + (channel->sc_dropmask & LOG_MASK(LOG_PRI(priority))) != 0) + { + nwritten_max = buflen; + continue; + } +#endif + write = !force ? channel->sc_ops->sc_write : channel->sc_ops->sc_write_force; if (write != NULL) @@ -242,23 +284,32 @@ ssize_t syslog_write_foreach(FAR const char *buffer, ssize_t syslog_write(FAR const char *buffer, size_t buflen) { - bool force = !syslog_safe_to_block(); - -#ifdef CONFIG_SYSLOG_INTBUFFER - if (force) - { - syslog_add_intbuffer(buffer, buflen); - return buflen; - } - else - { - /* Flush any characters that may have been added to the interrupt - * buffer. - */ + return syslog_write_internal(SYSLOG_PRIORITY_NONE, buffer, buflen); +} - syslog_flush_intbuffer(false); - } -#endif +#ifdef CONFIG_SYSLOG_DROPMASK +/**************************************************************************** + * Name: syslog_write_priority + * + * Description: + * This is syslog_write() for the text of a message with a priority. A + * channel does not write the text if its sc_dropmask has the bit of the + * priority. + * + * Input Parameters: + * priority - The priority of the message, or SYSLOG_PRIORITY_NONE + * buffer - The buffer containing the data to be output + * buflen - The number of bytes in the buffer + * + * Returned Value: + * On success, the number of characters written is returned. A negated + * errno value is returned on any failure. + * + ****************************************************************************/ - return syslog_write_foreach(buffer, buflen, force); +ssize_t syslog_write_priority(int priority, FAR const char *buffer, + size_t buflen) +{ + return syslog_write_internal(priority, buffer, buflen); } +#endif diff --git a/drivers/syslog/vsyslog.c b/drivers/syslog/vsyslog.c index a0bccbcfb06..cd609277abc 100644 --- a/drivers/syslog/vsyslog.c +++ b/drivers/syslog/vsyslog.c @@ -104,6 +104,12 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR va_list *ap) lib_syslograwstream_open(&stream); +#ifdef CONFIG_SYSLOG_DROPMASK + /* The channels select the messages by their priority */ + + stream.priority = LOG_PRI(priority); +#endif + #ifdef CONFIG_SYSLOG_TIMESTAMP ts.tv_sec = 0; ts.tv_nsec = 0; diff --git a/drivers/syslog/vsyslog_rfc5424.c b/drivers/syslog/vsyslog_rfc5424.c index f9f09cc4eb6..08761625019 100644 --- a/drivers/syslog/vsyslog_rfc5424.c +++ b/drivers/syslog/vsyslog_rfc5424.c @@ -114,6 +114,12 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR va_list *ap) lib_syslograwstream_open(&stream); +#ifdef CONFIG_SYSLOG_DROPMASK + /* The channels select the messages by their priority */ + + stream.priority = LOG_PRI(priority); +#endif + #ifdef CONFIG_SYSLOG_TIMESTAMP /* Get the current time. Since debug output may be generated very early diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h index 17875fb9889..1ee192af17a 100644 --- a/include/nuttx/streams.h +++ b/include/nuttx/streams.h @@ -280,6 +280,9 @@ struct lib_syslograwstream_s off_t offset; #endif int last_ch; +#ifdef CONFIG_SYSLOG_DROPMASK + int priority; /* Of the message, or SYSLOG_PRIORITY_NONE */ +#endif }; /* LZF compressed stream pipeline */ diff --git a/include/nuttx/syslog/syslog.h b/include/nuttx/syslog/syslog.h index e4db6b6b2ee..4f9cd98db22 100644 --- a/include/nuttx/syslog/syslog.h +++ b/include/nuttx/syslog/syslog.h @@ -98,6 +98,12 @@ #define SYSLOG_CHANNEL_DISABLE 0x01 #define SYSLOG_CHANNEL_DISABLE_CRLF 0x02 +/* The priority of output that does not come from syslog() (a raw write): + * every channel takes it. + */ + +#define SYSLOG_PRIORITY_NONE (-1) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -167,6 +173,15 @@ struct syslog_channel_s #if defined(CONFIG_SYSLOG_IOCTL) || defined(CONFIG_SYSLOG_CRLF) uint8_t sc_state; #endif + +#ifdef CONFIG_SYSLOG_DROPMASK + /* The message priorities that the channel does not write: an OR of + * LOG_MASK() values. Zero (the value of a channel that does not set it) + * means that the channel writes the messages of all priorities. + */ + + uint8_t sc_dropmask; +#endif }; /**************************************************************************** @@ -336,6 +351,31 @@ syslog_stream_channel(FAR struct lib_outstream_s *stream); ssize_t syslog_write(FAR const char *buffer, size_t buflen); +#ifdef CONFIG_SYSLOG_DROPMASK +/**************************************************************************** + * Name: syslog_write_priority + * + * Description: + * This is syslog_write() for the text of a message with a priority. A + * channel does not write the text if its sc_dropmask has the bit of the + * priority. + * + * Input Parameters: + * priority - The priority of the message (LOG_EMERG to LOG_DEBUG), or + * SYSLOG_PRIORITY_NONE: all channels write the text. + * buffer - The buffer containing the data to be output + * buflen - The number of bytes in the buffer + * + * Returned Value: + * On success, the number of characters written is returned. A negated + * errno value is returned on any failure. + * + ****************************************************************************/ + +ssize_t syslog_write_priority(int priority, FAR const char *buffer, + size_t buflen); +#endif + /**************************************************************************** * Name: syslog_flush * diff --git a/libs/libc/stream/lib_syslograwstream.c b/libs/libc/stream/lib_syslograwstream.c index bc01dcbed4f..55fbe1394d1 100644 --- a/libs/libc/stream/lib_syslograwstream.c +++ b/libs/libc/stream/lib_syslograwstream.c @@ -32,6 +32,17 @@ #include <nuttx/streams.h> #include <nuttx/syslog/syslog.h> +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_SYSLOG_DROPMASK +# define syslograwstream_write(s, b, n) \ + syslog_write_priority((s)->priority, b, n) +#else +# define syslograwstream_write(s, b, n) syslog_write(b, n) +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -71,7 +82,8 @@ static int syslograwstream_flush(FAR struct lib_outstream_s *self) do { - ret = syslog_write(stream->buffer + written, nbytes - written); + ret = syslograwstream_write(stream, stream->buffer + written, + nbytes - written); if (ret < 0) { if (ret != -EINTR) @@ -215,7 +227,7 @@ static void syslograwstream_putc(FAR struct lib_outstream_s *self, int ch) * failure, syslog_write returns a negated errno value. */ - ret = syslog_write(&c, 1); + ret = syslograwstream_write(stream, &c, 1); if (ret >= 0) { self->nput++; @@ -263,7 +275,7 @@ static ssize_t syslograwstream_puts(FAR struct lib_outstream_s *self, * failure, syslog_write returns a negated errno value. */ - ret = syslog_write(buff, len); + ret = syslograwstream_write(stream, buff, len); if (ret >= 0) { self->nput += ret; @@ -312,6 +324,9 @@ void lib_syslograwstream_open(FAR struct lib_syslograwstream_s *stream) stream->common.puts = syslograwstream_puts; stream->common.nput = 0; stream->last_ch = '\0'; +#ifdef CONFIG_SYSLOG_DROPMASK + stream->priority = SYSLOG_PRIORITY_NONE; +#endif #ifdef CONFIG_SYSLOG_BUFFER stream->common.flush = syslograwstream_flush;
