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;

Reply via email to