Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 41 additions & 27 deletions components/logger/include/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class Logger {
NONE, /**< No verbosity - logger will not print anything. */
};

using clock_t = std::chrono::steady_clock; /**< The clock type used for rate limiting. */

/**
* @brief Configuration struct for the logger.
*/
Expand All @@ -110,7 +112,7 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
*/
explicit Logger(const Config &config)
: tag_(config.tag)
, rate_limit_(config.rate_limit)
, rate_limit_(std::chrono::duration_cast<clock_t::duration>(config.rate_limit))
, include_time_(config.include_time)
, level_(config.level) {}

Expand All @@ -135,8 +137,8 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
std::scoped_lock lock(other.tag_mutex_);
return std::move(other.tag_);
}())
, rate_limit_(std::move(other.rate_limit_))
, last_print_(std::move(other.last_print_))
, rate_limit_(other.rate_limit_)
, last_print_(other.last_print_.load())
, include_time_(other.include_time_.load())
, level_(other.level_.load()) {}

Expand Down Expand Up @@ -167,8 +169,8 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
if (this != &other) {
std::scoped_lock lock(tag_mutex_, other.tag_mutex_);
tag_ = std::move(other.tag_);
rate_limit_ = std::move(other.rate_limit_);
last_print_ = std::move(other.last_print_);
rate_limit_ = other.rate_limit_;
last_print_.store(other.last_print_.load());
include_time_ = other.include_time_.load();
level_ = other.level_.load();
}
Expand Down Expand Up @@ -217,13 +219,17 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
* @param rate_limit The new rate limit.
* @note Only calls that have _rate_limited suffixed will be rate limited.
*/
void set_rate_limit(const std::chrono::duration<float> rate_limit) { rate_limit_ = rate_limit; }
void set_rate_limit(const std::chrono::duration<float> rate_limit) {
rate_limit_ = std::chrono::duration_cast<clock_t::duration>(rate_limit);
}
Comment on lines +222 to +224

/**
* @brief Get the current rate limit for the logger.
* @return The current rate limit.
*/
std::chrono::duration<float> get_rate_limit() const { return rate_limit_; }
std::chrono::duration<float> get_rate_limit() const {
return std::chrono::duration_cast<std::chrono::duration<float>>(rate_limit_);
}

/**
* @brief Format args into string according to format string. From:
Expand Down Expand Up @@ -329,11 +335,13 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
#if ESPP_LOGGER_DEBUG_ENABLED
if (level_ > espp::Logger::Verbosity::DEBUG)
return;
if (rate_limit_ > std::chrono::duration<float>::zero()) {
auto now = std::chrono::high_resolution_clock::now();
if (now - last_print_ < rate_limit_)
if (rate_limit_ > clock_t::duration::zero()) {
const auto now = clock_t::now().time_since_epoch().count();
// last_print_ is an atomic timestamp (clock_t rep) so the check/update is
// free of data races when logging from multiple threads.
if (clock_t::duration(now - last_print_.load()) < rate_limit_)
return;
last_print_ = now;
last_print_.store(now);
}
// forward the arguments to the debug function
debug(rt_fmt_str, std::forward<Args>(args)...);
Expand All @@ -351,11 +359,13 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
#if ESPP_LOGGER_INFO_ENABLED
if (level_ > espp::Logger::Verbosity::INFO)
return;
if (rate_limit_ > std::chrono::duration<float>::zero()) {
auto now = std::chrono::high_resolution_clock::now();
if (now - last_print_ < rate_limit_)
if (rate_limit_ > clock_t::duration::zero()) {
const auto now = clock_t::now().time_since_epoch().count();
// last_print_ is an atomic timestamp (clock_t rep) so the check/update is
// free of data races when logging from multiple threads.
if (clock_t::duration(now - last_print_.load()) < rate_limit_)
return;
last_print_ = now;
last_print_.store(now);
}
// forward the arguments to the info function
info(rt_fmt_str, std::forward<Args>(args)...);
Expand All @@ -373,11 +383,13 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
#if ESPP_LOGGER_WARN_ENABLED
if (level_ > espp::Logger::Verbosity::WARN)
return;
if (rate_limit_ > std::chrono::duration<float>::zero()) {
auto now = std::chrono::high_resolution_clock::now();
if (now - last_print_ < rate_limit_)
if (rate_limit_ > clock_t::duration::zero()) {
const auto now = clock_t::now().time_since_epoch().count();
// last_print_ is an atomic timestamp (clock_t rep) so the check/update is
// free of data races when logging from multiple threads.
if (clock_t::duration(now - last_print_.load()) < rate_limit_)
return;
last_print_ = now;
last_print_.store(now);
}
// forward the arguments to the warn function
warn(rt_fmt_str, std::forward<Args>(args)...);
Expand All @@ -395,11 +407,13 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit
#if ESPP_LOGGER_ERROR_ENABLED
if (level_ > espp::Logger::Verbosity::ERROR)
return;
if (rate_limit_ > std::chrono::duration<float>::zero()) {
auto now = std::chrono::high_resolution_clock::now();
if (now - last_print_ < rate_limit_)
if (rate_limit_ > clock_t::duration::zero()) {
const auto now = clock_t::now().time_since_epoch().count();
// last_print_ is an atomic timestamp (clock_t rep) so the check/update is
// free of data races when logging from multiple threads.
if (clock_t::duration(now - last_print_.load()) < rate_limit_)
return;
last_print_ = now;
last_print_.store(now);
}
// forward the arguments to the error function
error(rt_fmt_str, std::forward<Args>(args)...);
Expand Down Expand Up @@ -480,10 +494,10 @@ rate limit. @note Only calls that have _rate_limited suffixed will be rate limit

mutable std::mutex tag_mutex_; ///< Mutex for the tag.
std::string tag_; ///< Name of the logger to be prepended to all logs.
std::chrono::duration<float> rate_limit_{
0.0f}; ///< Rate limit for the logger. If set to 0, no rate limiting will be performed.
std::chrono::high_resolution_clock::time_point
last_print_{}; ///< Last time a log was printed. Used for rate limiting.
clock_t::duration rate_limit_{
clock_t::duration::zero()}; ///< Rate limit for the logger. If zero, no rate limiting is done.
std::atomic<clock_t::rep> last_print_{
0}; ///< Epoch count (clock_t rep) of the last printed log. Used for rate limiting.
std::atomic<bool> include_time_{true}; ///< Whether to include the time in the log.
std::atomic<espp::Logger::Verbosity> level_ =
espp::Logger::Verbosity::WARN; ///< Current verbosity level of the logger.
Expand Down
Loading