mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 13:27:01 +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
|
||||
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)
|
||||
==========================
|
||||
|
||||
|
||||
+109
-2
@@ -65,6 +65,14 @@
|
||||
* 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
|
||||
{
|
||||
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;
|
||||
|
||||
uint32_t rl_bufsize; /* Size of the Circular RAM buffer */
|
||||
struct list_node rl_list; /* The head of ramlog_user_s list */
|
||||
uint32_t rl_bufsize; /* Size of the circular buffer */
|
||||
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
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
****************************************************************************/
|
||||
@@ -301,6 +369,12 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (ramlog_ratelimit(priv))
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RAMLOG_SYSLOG
|
||||
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:
|
||||
ramlog_bufferflush(priv);
|
||||
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:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
|
||||
@@ -88,6 +88,11 @@
|
||||
|
||||
#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_DISABLE 0x01
|
||||
@@ -127,6 +132,12 @@ struct syslog_channel_ops_s
|
||||
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
|
||||
{
|
||||
char sc_name[SYSLOG_CHANNEL_NAME_LEN];
|
||||
|
||||
Reference in New Issue
Block a user