mirror of
https://github.com/apache/nuttx.git
synced 2026-06-01 16:59:28 +08:00
driver/ramlog: Implement the rate limiting function for ramlog driver.
Limit the maximum number of log entries allowed within the specified time interval in seconds. Signed-off-by: yukangzhi <yukangzhi@xiaomi.com>
This commit is contained in:
@@ -539,6 +539,73 @@ Other miscellaneous settings
|
|||||||
- ``CONFIG_RAMLOG_NPOLLWAITERS``: The maximum number of threads
|
- ``CONFIG_RAMLOG_NPOLLWAITERS``: The maximum number of threads
|
||||||
that may be waiting on the poll method.
|
that may be waiting on the poll method.
|
||||||
|
|
||||||
|
RAMLOG Rate Limiting
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The RAMLOG SYSLOG channel supports rate limiting to prevent log flooding.
|
||||||
|
You can set or get the rate limit using the following IOCTLs:
|
||||||
|
|
||||||
|
- ``SYSLOGIOC_SETRATELIMIT``: Set the rate limit.
|
||||||
|
- ``SYSLOGIOC_GETRATELIMIT``: Get the current rate limit.
|
||||||
|
|
||||||
|
The argument is a pointer to:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct syslog_ratelimit_s
|
||||||
|
{
|
||||||
|
unsigned int interval; /* The interval in seconds */
|
||||||
|
unsigned int burst; /* The max allowed log entries during interval */
|
||||||
|
};
|
||||||
|
|
||||||
|
**Example (C code):**
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct syslog_ratelimit_s limit = { .interval = 1, .burst = 100 };
|
||||||
|
ioctl(fd, SYSLOGIOC_SETRATELIMIT, (unsigned long)&limit);
|
||||||
|
|
||||||
|
**NSH Tool Example: setlograte**
|
||||||
|
|
||||||
|
You can implement a simple NSH command to control the RAMLOG rate limit at runtime, similar to setlogmask:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
int cmd_setlograte(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct syslog_ratelimit_s limit;
|
||||||
|
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
printf("Usage: setlograte <interval_sec> <burst>\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
limit.interval = atoi(argv[1]);
|
||||||
|
limit.burst = atoi(argv[2]);
|
||||||
|
|
||||||
|
fd = open("/dev/ramlog", O_RDWR);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
printf("Failed to open /dev/ramlog\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, SYSLOGIOC_SETRATELIMIT, (unsigned long)&limit) < 0)
|
||||||
|
{
|
||||||
|
printf("Failed to set rate limit\n");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Set RAMLOG rate limit: interval=%u sec, burst=%u\n", limit.interval, limit.burst);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
This command allows you to set the maximum number of log entries (burst) allowed in a given interval (seconds) for the RAMLOG device at runtime.
|
||||||
|
|
||||||
SYSLOG Protocol (RFC 5424)
|
SYSLOG Protocol (RFC 5424)
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
|||||||
+109
-2
@@ -65,6 +65,14 @@
|
|||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct ramlog_ratelimit_s
|
||||||
|
{
|
||||||
|
unsigned int interval; /* The interval in seconds */
|
||||||
|
unsigned int burst; /* The max allowed note number during interval */
|
||||||
|
unsigned int printed; /* The number of printed note during interval */
|
||||||
|
unsigned long begin; /* The timestamp in seconds */
|
||||||
|
};
|
||||||
|
|
||||||
struct ramlog_header_s
|
struct ramlog_header_s
|
||||||
{
|
{
|
||||||
uint32_t rl_magic; /* The rl_magic number for ramlog buffer init */
|
uint32_t rl_magic; /* The rl_magic number for ramlog buffer init */
|
||||||
@@ -98,8 +106,9 @@ struct ramlog_dev_s
|
|||||||
|
|
||||||
FAR struct ramlog_header_s *rl_header;
|
FAR struct ramlog_header_s *rl_header;
|
||||||
|
|
||||||
uint32_t rl_bufsize; /* Size of the Circular RAM buffer */
|
uint32_t rl_bufsize; /* Size of the circular buffer */
|
||||||
struct list_node rl_list; /* The head of ramlog_user_s list */
|
struct list_node rl_list; /* The list of ramlog_user_s */
|
||||||
|
struct ramlog_ratelimit_s rl_ratelimit; /* The ratelimit for ramlog */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -173,6 +182,65 @@ static struct ramlog_dev_s g_sysdev =
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ramlog_ratelimit
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check whether the log is limited.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - The pointer of ramlog device.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* True is returned if the log is limited.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static bool ramlog_ratelimit(FAR struct ramlog_dev_s *dev)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
clock_t ticks;
|
||||||
|
uint32_t seconds;
|
||||||
|
FAR struct ramlog_ratelimit_s *limit;
|
||||||
|
|
||||||
|
limit = &dev->rl_ratelimit;
|
||||||
|
|
||||||
|
if (limit->interval == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ticks = clock_systime_ticks();
|
||||||
|
seconds = ticks * CONFIG_USEC_PER_TICK / 1000000;
|
||||||
|
|
||||||
|
if (limit->begin == 0)
|
||||||
|
{
|
||||||
|
limit->begin = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset statistical information */
|
||||||
|
|
||||||
|
if ((seconds - limit->begin) >= limit->interval)
|
||||||
|
{
|
||||||
|
limit->begin = seconds;
|
||||||
|
limit->printed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the note is limited */
|
||||||
|
|
||||||
|
if (limit->burst && limit->burst > limit->printed)
|
||||||
|
{
|
||||||
|
limit->printed++;
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: ramlog_bufferused
|
* Name: ramlog_bufferused
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -301,6 +369,12 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
|
|||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
if (ramlog_ratelimit(priv))
|
||||||
|
{
|
||||||
|
leave_critical_section(flags);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_RAMLOG_SYSLOG
|
#ifdef CONFIG_RAMLOG_SYSLOG
|
||||||
if (header->rl_magic != RAMLOG_MAGIC_NUMBER && priv == &g_sysdev)
|
if (header->rl_magic != RAMLOG_MAGIC_NUMBER && priv == &g_sysdev)
|
||||||
{
|
{
|
||||||
@@ -521,6 +595,39 @@ static int ramlog_file_ioctl(FAR struct file *filep, int cmd,
|
|||||||
case BIOC_FLUSH:
|
case BIOC_FLUSH:
|
||||||
ramlog_bufferflush(priv);
|
ramlog_bufferflush(priv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SYSLOGIOC_SETRATELIMIT:
|
||||||
|
if (arg == 0)
|
||||||
|
{
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FAR struct syslog_ratelimit_s *limit =
|
||||||
|
(FAR struct syslog_ratelimit_s *)arg;
|
||||||
|
|
||||||
|
priv->rl_ratelimit.interval = limit->interval;
|
||||||
|
priv->rl_ratelimit.burst = limit->burst;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYSLOGIOC_GETRATELIMIT:
|
||||||
|
if (arg == 0)
|
||||||
|
{
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FAR struct syslog_ratelimit_s *limit =
|
||||||
|
(FAR struct syslog_ratelimit_s *)arg;
|
||||||
|
|
||||||
|
limit->interval = priv->rl_ratelimit.interval;
|
||||||
|
limit->burst = priv->rl_ratelimit.burst;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = -ENOTTY;
|
ret = -ENOTTY;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -88,6 +88,11 @@
|
|||||||
|
|
||||||
#define SYSLOGIOC_SETFILTER _SYSLOGIOC(0x0002)
|
#define SYSLOGIOC_SETFILTER _SYSLOGIOC(0x0002)
|
||||||
|
|
||||||
|
/* Set/Get syslog ratelimit */
|
||||||
|
|
||||||
|
#define SYSLOGIOC_SETRATELIMIT _SYSLOGIOC(0x0003)
|
||||||
|
#define SYSLOGIOC_GETRATELIMIT _SYSLOGIOC(0x0004)
|
||||||
|
|
||||||
#define SYSLOG_CHANNEL_NAME_LEN 32
|
#define SYSLOG_CHANNEL_NAME_LEN 32
|
||||||
|
|
||||||
#define SYSLOG_CHANNEL_DISABLE 0x01
|
#define SYSLOG_CHANNEL_DISABLE 0x01
|
||||||
@@ -127,6 +132,12 @@ struct syslog_channel_ops_s
|
|||||||
syslog_close_t sc_close; /* Channel close callback */
|
syslog_close_t sc_close; /* Channel close callback */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct syslog_ratelimit_s
|
||||||
|
{
|
||||||
|
unsigned int interval; /* The interval in seconds */
|
||||||
|
unsigned int burst; /* The max allowed note number during interval */
|
||||||
|
};
|
||||||
|
|
||||||
struct syslog_channel_info_s
|
struct syslog_channel_info_s
|
||||||
{
|
{
|
||||||
char sc_name[SYSLOG_CHANNEL_NAME_LEN];
|
char sc_name[SYSLOG_CHANNEL_NAME_LEN];
|
||||||
|
|||||||
Reference in New Issue
Block a user