mirror of
https://github.com/tbnobody/OpenDTU.git
synced 2025-12-10 16:59:52 +01:00
syslog: implement rate limiting
enabling a lot of logging messages, e.g., by setting verbose as the default level, can make the system unresponsive if syslogging is enabled. to protect against this, a rate limiting algorithm is implemented in the syslogger.
This commit is contained in:
committed by
Thomas Basler
parent
5ba3446ad4
commit
20003a0f92
@@ -20,6 +20,7 @@ private:
|
|||||||
return _address != INADDR_NONE;
|
return _address != INADDR_NONE;
|
||||||
}
|
}
|
||||||
static uint8_t calculatePrival(uint8_t facility, char errorCode);
|
static uint8_t calculatePrival(uint8_t facility, char errorCode);
|
||||||
|
bool consumeToken();
|
||||||
|
|
||||||
Task _loopTask;
|
Task _loopTask;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
@@ -30,6 +31,14 @@ private:
|
|||||||
String _header;
|
String _header;
|
||||||
uint16_t _port;
|
uint16_t _port;
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
|
|
||||||
|
static constexpr uint32_t RATE_LIMIT_WINDOW_MS = 1000;
|
||||||
|
static constexpr size_t RATE_LIMIT_MAX_TOKENS = 100;
|
||||||
|
size_t _available_tokens = RATE_LIMIT_MAX_TOKENS;
|
||||||
|
uint32_t _last_token_refill_millis = 0;
|
||||||
|
size_t _rate_limited_packets = 0;
|
||||||
|
uint32_t _last_rate_limit_warning_millis = 0;
|
||||||
|
static constexpr uint32_t RATE_LIMIT_WARNING_INTERVAL_MS = 1000;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SyslogLogger Syslog;
|
extern SyslogLogger Syslog;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#undef TAG
|
#undef TAG
|
||||||
static const char* TAG = "syslog";
|
static const char* TAG = "syslog";
|
||||||
@@ -65,6 +66,27 @@ void SyslogLogger::write(const uint8_t* buffer, size_t size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check rate limiting using token bucket
|
||||||
|
if (!consumeToken()) {
|
||||||
|
if (_rate_limited_packets == 0) {
|
||||||
|
_last_rate_limit_warning_millis = millis();
|
||||||
|
}
|
||||||
|
++_rate_limited_packets;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_rate_limited_packets > 0) {
|
||||||
|
uint32_t elapsed = (millis() - _last_rate_limit_warning_millis);
|
||||||
|
if (elapsed > RATE_LIMIT_WARNING_INTERVAL_MS) {
|
||||||
|
char buffer[128];
|
||||||
|
snprintf(buffer, sizeof(buffer), "Rate limited %d packets in the last %dms",
|
||||||
|
_rate_limited_packets, elapsed);
|
||||||
|
Serial.println(buffer);
|
||||||
|
_rate_limited_packets = 0;
|
||||||
|
_last_rate_limit_warning_millis = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String header = "<";
|
String header = "<";
|
||||||
header += String(calculatePrival(1, buffer[0]));
|
header += String(calculatePrival(1, buffer[0]));
|
||||||
|
|
||||||
@@ -82,6 +104,26 @@ void SyslogLogger::write(const uint8_t* buffer, size_t size)
|
|||||||
_udp.endPacket();
|
_udp.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SyslogLogger::consumeToken()
|
||||||
|
{
|
||||||
|
uint32_t now = millis();
|
||||||
|
|
||||||
|
uint32_t elapsed = now - _last_token_refill_millis;
|
||||||
|
size_t new_tokens = RATE_LIMIT_MAX_TOKENS * elapsed / RATE_LIMIT_WINDOW_MS;
|
||||||
|
|
||||||
|
if (new_tokens > 0) {
|
||||||
|
_available_tokens = std::min(_available_tokens + new_tokens, RATE_LIMIT_MAX_TOKENS);
|
||||||
|
_last_token_refill_millis = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_available_tokens > 0) {
|
||||||
|
--_available_tokens;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SyslogLogger::disable()
|
void SyslogLogger::disable()
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Disable");
|
ESP_LOGI(TAG, "Disable");
|
||||||
@@ -103,6 +145,8 @@ void SyslogLogger::enable()
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_enabled = true;
|
_enabled = true;
|
||||||
|
_available_tokens = RATE_LIMIT_MAX_TOKENS;
|
||||||
|
_last_token_refill_millis = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SyslogLogger::resolveAndStart()
|
bool SyslogLogger::resolveAndStart()
|
||||||
|
|||||||
Reference in New Issue
Block a user