updated uuid libs

This commit is contained in:
Proddy
2023-01-05 15:05:30 +01:00
parent 6370296c53
commit 3b196fc90d
27 changed files with 2013 additions and 1411 deletions

View File

@@ -38,20 +38,19 @@ static constexpr const char * pstr_level_lowercase_debug = "debug";
static constexpr const char * pstr_level_lowercase_trace = "trace";
static constexpr const char * pstr_level_lowercase_all = "all";
static const __FlashStringHelper * log_level_lowercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(uint32_t))))
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_off),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_emerg),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_crit),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_alert),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_err),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_warning),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_notice),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_info),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_debug),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_trace),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_all)};
static const char * log_level_lowercase[(int)Level::ALL - (int)Level::OFF + 1] = {pstr_level_lowercase_off,
pstr_level_lowercase_emerg,
pstr_level_lowercase_crit,
pstr_level_lowercase_alert,
pstr_level_lowercase_err,
pstr_level_lowercase_warning,
pstr_level_lowercase_notice,
pstr_level_lowercase_info,
pstr_level_lowercase_debug,
pstr_level_lowercase_trace,
pstr_level_lowercase_all};
const __FlashStringHelper * format_level_lowercase(Level level) {
const char * format_level_lowercase(Level level) {
return log_level_lowercase[(int)level + 1];
}

View File

@@ -38,20 +38,19 @@ static constexpr const char * pstr_level_uppercase_debug = "DEBUG";
static constexpr const char * pstr_level_uppercase_trace = "TRACE";
static constexpr const char * pstr_level_uppercase_all = "ALL";
static const __FlashStringHelper * log_level_uppercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(uint32_t))))
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_off),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_emerg),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_crit),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_alert),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_err),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_warning),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_notice),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_info),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_debug),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_trace),
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_all)};
static const char * log_level_uppercase[(int)Level::ALL - (int)Level::OFF + 1] = {pstr_level_uppercase_off,
pstr_level_uppercase_emerg,
pstr_level_uppercase_crit,
pstr_level_uppercase_alert,
pstr_level_uppercase_err,
pstr_level_uppercase_warning,
pstr_level_uppercase_notice,
pstr_level_uppercase_info,
pstr_level_uppercase_debug,
pstr_level_uppercase_trace,
pstr_level_uppercase_all};
const __FlashStringHelper * format_level_uppercase(Level level) {
const char * format_level_uppercase(Level level) {
return log_level_uppercase[(int)level + 1];
}

View File

@@ -20,6 +20,7 @@
#include <Arduino.h>
#include <array>
#include <cstdint>
#include <string>
@@ -45,7 +46,7 @@ std::string format_timestamp_ms(uint64_t timestamp_ms, unsigned int days_width)
milliseconds = timestamp_ms;
static std::vector<char> text(10 + 1 /* days */ + 2 + 1 /* hours */ + 2 + 1 /* minutes */ + 2 + 1 /* seconds */ + 3 /* milliseconds */ + 1);
std::array<char, 12 + 1 /* days */ + 2 + 1 /* hours */ + 2 + 1 /* minutes */ + 2 + 1 /* seconds */ + 3 /* milliseconds */ + 1> text;
snprintf(text.data(), text.size(), ("%0*lu+%02u:%02u:%02u.%03u"), std::min(days_width, 10U), days, hours, minutes, seconds, milliseconds);

View File

@@ -0,0 +1,31 @@
/*
* uuid-log - Microcontroller logging framework
* Copyright 2021 Simon Arlott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uuid/log.h>
namespace uuid {
namespace log {
Handler::~Handler() {
Logger::unregister_handler(this);
}
} // namespace log
} // namespace uuid

View File

@@ -27,17 +27,17 @@ namespace uuid {
namespace log {
std::vector<std::string> levels_lowercase() {
return {uuid::read_flash_string(format_level_lowercase(Level::OFF)),
uuid::read_flash_string(format_level_lowercase(Level::EMERG)),
uuid::read_flash_string(format_level_lowercase(Level::ALERT)),
uuid::read_flash_string(format_level_lowercase(Level::CRIT)),
uuid::read_flash_string(format_level_lowercase(Level::ERR)),
uuid::read_flash_string(format_level_lowercase(Level::WARNING)),
uuid::read_flash_string(format_level_lowercase(Level::NOTICE)),
uuid::read_flash_string(format_level_lowercase(Level::INFO)),
uuid::read_flash_string(format_level_lowercase(Level::DEBUG)),
uuid::read_flash_string(format_level_lowercase(Level::TRACE)),
uuid::read_flash_string(format_level_lowercase(Level::ALL))};
return {format_level_lowercase(Level::OFF),
format_level_lowercase(Level::EMERG),
format_level_lowercase(Level::ALERT),
format_level_lowercase(Level::CRIT),
format_level_lowercase(Level::ERR),
format_level_lowercase(Level::WARNING),
format_level_lowercase(Level::NOTICE),
format_level_lowercase(Level::INFO),
format_level_lowercase(Level::DEBUG),
format_level_lowercase(Level::TRACE),
format_level_lowercase(Level::ALL)};
}
} // namespace log

View File

@@ -27,17 +27,17 @@ namespace uuid {
namespace log {
std::vector<std::string> levels_uppercase() {
return {uuid::read_flash_string(format_level_uppercase(Level::OFF)),
uuid::read_flash_string(format_level_uppercase(Level::EMERG)),
uuid::read_flash_string(format_level_uppercase(Level::ALERT)),
uuid::read_flash_string(format_level_uppercase(Level::CRIT)),
uuid::read_flash_string(format_level_uppercase(Level::ERR)),
uuid::read_flash_string(format_level_uppercase(Level::WARNING)),
uuid::read_flash_string(format_level_uppercase(Level::NOTICE)),
uuid::read_flash_string(format_level_uppercase(Level::INFO)),
uuid::read_flash_string(format_level_uppercase(Level::DEBUG)),
uuid::read_flash_string(format_level_uppercase(Level::TRACE)),
uuid::read_flash_string(format_level_uppercase(Level::ALL))};
return {format_level_uppercase(Level::OFF),
format_level_uppercase(Level::EMERG),
format_level_uppercase(Level::ALERT),
format_level_uppercase(Level::CRIT),
format_level_uppercase(Level::ERR),
format_level_uppercase(Level::WARNING),
format_level_uppercase(Level::NOTICE),
format_level_uppercase(Level::INFO),
format_level_uppercase(Level::DEBUG),
format_level_uppercase(Level::TRACE),
format_level_uppercase(Level::ALL)};
}
} // namespace log

View File

@@ -1,6 +1,6 @@
/*
* uuid-log - Microcontroller logging framework
* Copyright 2019 Simon Arlott
* Copyright 2019,2021-2022 Simon Arlott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,11 +20,15 @@
#include <Arduino.h>
#include <atomic>
#include <cstdarg>
#include <cstdint>
#include <list>
#include <map>
#include <memory>
#if UUID_LOG_THREAD_SAFE
#include <mutex>
#endif
#include <string>
#include <utility>
#include <vector>
@@ -33,8 +37,21 @@ namespace uuid {
namespace log {
std::map<Handler *, Level> Logger::handlers_;
Level Logger::level_ = Level::OFF;
std::atomic<Level> Logger::global_level_{Level::OFF};
#if UUID_LOG_THREAD_SAFE
std::mutex Logger::mutex_;
#endif
//! @cond false
static Level constrain_level(Level level) {
if (level < Level::EMERG) {
level = Level::EMERG;
} else if (level > Level::TRACE) {
level = Level::TRACE;
}
return level;
}
//! @endcond
Message::Message(uint64_t uptime_ms, Level level, Facility facility, const char * name, const std::string && text)
: uptime_ms(uptime_ms)
@@ -50,20 +67,46 @@ Logger::Logger(const char * name, Facility facility)
};
std::shared_ptr<std::map<Handler *, Level>> & Logger::registered_handlers() {
static std::shared_ptr<std::map<Handler *, Level>> handlers = std::make_shared<std::map<Handler *, Level>>();
return handlers;
}
void Logger::register_handler(Handler * handler, Level level) {
handlers_[handler] = level;
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
auto & handlers = registered_handlers();
handler->handlers_ = handlers;
(*handlers)[handler] = level;
refresh_log_level();
};
void Logger::unregister_handler(Handler * handler) {
handlers_.erase(handler);
refresh_log_level();
auto handlers = handler->handlers_.lock();
if (handlers) {
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
if (handlers->erase(handler)) {
refresh_log_level();
}
}
};
Level Logger::get_log_level(const Handler * handler) {
const auto level = handlers_.find(const_cast<Handler *>(handler));
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
auto & handlers = registered_handlers();
if (level != handlers_.end()) {
const auto level = handlers->find(const_cast<Handler *>(handler));
if (level != handlers->end()) {
return level->second;
}
@@ -80,16 +123,6 @@ void Logger::emerg(const char * format, ...) const {
}
};
void Logger::emerg(const __FlashStringHelper * format, ...) const {
if (enabled(Level::EMERG)) {
va_list ap;
va_start(ap, format);
vlog(Level::EMERG, format, ap);
va_end(ap);
}
};
void Logger::crit(const char * format, ...) const {
if (enabled(Level::CRIT)) {
va_list ap;
@@ -100,16 +133,6 @@ void Logger::crit(const char * format, ...) const {
}
};
void Logger::crit(const __FlashStringHelper * format, ...) const {
if (enabled(Level::CRIT)) {
va_list ap;
va_start(ap, format);
vlog(Level::CRIT, format, ap);
va_end(ap);
}
};
void Logger::alert(const char * format, ...) const {
if (enabled(Level::ALERT)) {
va_list ap;
@@ -120,15 +143,6 @@ void Logger::alert(const char * format, ...) const {
}
};
void Logger::alert(const __FlashStringHelper * format, ...) const {
if (enabled(Level::ALERT)) {
va_list ap;
va_start(ap, format);
vlog(Level::ALERT, format, ap);
va_end(ap);
}
};
void Logger::err(const char * format, ...) const {
if (enabled(Level::ERR)) {
va_list ap;
@@ -139,16 +153,6 @@ void Logger::err(const char * format, ...) const {
}
};
void Logger::err(const __FlashStringHelper * format, ...) const {
if (enabled(Level::ERR)) {
va_list ap;
va_start(ap, format);
vlog(Level::ERR, format, ap);
va_end(ap);
}
};
void Logger::warning(const char * format, ...) const {
if (enabled(Level::WARNING)) {
va_list ap;
@@ -159,16 +163,6 @@ void Logger::warning(const char * format, ...) const {
}
};
void Logger::warning(const __FlashStringHelper * format, ...) const {
if (enabled(Level::WARNING)) {
va_list ap;
va_start(ap, format);
vlog(Level::WARNING, format, ap);
va_end(ap);
}
};
void Logger::notice(const char * format, ...) const {
if (enabled(Level::NOTICE)) {
va_list ap;
@@ -179,16 +173,6 @@ void Logger::notice(const char * format, ...) const {
}
};
void Logger::notice(const __FlashStringHelper * format, ...) const {
if (enabled(Level::NOTICE)) {
va_list ap;
va_start(ap, format);
vlog(Level::NOTICE, format, ap);
va_end(ap);
}
};
void Logger::info(const char * format, ...) const {
if (enabled(Level::INFO)) {
va_list ap;
@@ -199,16 +183,6 @@ void Logger::info(const char * format, ...) const {
}
};
void Logger::info(const __FlashStringHelper * format, ...) const {
if (enabled(Level::INFO)) {
va_list ap;
va_start(ap, format);
vlog(Level::INFO, format, ap);
va_end(ap);
}
};
void Logger::debug(const char * format, ...) const {
if (enabled(Level::DEBUG)) {
va_list ap;
@@ -219,16 +193,6 @@ void Logger::debug(const char * format, ...) const {
}
};
void Logger::debug(const __FlashStringHelper * format, ...) const {
if (enabled(Level::DEBUG)) {
va_list ap;
va_start(ap, format);
vlog(Level::DEBUG, format, ap);
va_end(ap);
}
};
void Logger::trace(const char * format, ...) const {
if (enabled(Level::TRACE)) {
va_list ap;
@@ -239,38 +203,20 @@ void Logger::trace(const char * format, ...) const {
}
};
void Logger::trace(const __FlashStringHelper * format, ...) const {
if (enabled(Level::TRACE)) {
va_list ap;
va_start(ap, format);
vlog(Level::TRACE, format, ap);
va_end(ap);
}
};
void Logger::log(Level level, Facility facility, const char * format, ...) const {
if (level < Level::EMERG) {
level = Level::EMERG;
} else if (level > Level::TRACE) {
level = Level::TRACE;
}
void Logger::log(Level level, const char * format, ...) const {
level = constrain_level(level);
if (enabled(level)) {
va_list ap;
va_start(ap, format);
vlog(level, facility, format, ap);
vlog(level, format, ap);
va_end(ap);
}
};
void Logger::log(Level level, Facility facility, const __FlashStringHelper * format, ...) const {
if (level < Level::EMERG) {
level = Level::EMERG;
} else if (level > Level::TRACE) {
level = Level::TRACE;
}
void Logger::log(Level level, Facility facility, const char * format, ...) const {
level = constrain_level(level);
if (enabled(level)) {
va_list ap;
@@ -295,41 +241,34 @@ void Logger::vlog(Level level, Facility facility, const char * format, va_list a
dispatch(level, facility, text);
}
void Logger::vlog(Level level, const __FlashStringHelper * format, va_list ap) const {
vlog(level, facility_, format, ap);
}
void Logger::vlog(Level level, Facility facility, const __FlashStringHelper * format, va_list ap) const {
std::vector<char> text(MAX_LOG_LENGTH + 1);
if (vsnprintf_P(text.data(), text.size(), reinterpret_cast<PGM_P>(format), ap) <= 0) {
return;
}
dispatch(level, facility, text);
}
void Logger::dispatch(Level level, Facility facility, std::vector<char> & text) const {
std::shared_ptr<Message> message = std::make_shared<Message>(get_uptime_ms(), level, facility, name_, text.data());
text.resize(0);
for (auto & handler : handlers_) {
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
for (auto & handler : *registered_handlers()) {
if (level <= handler.second) {
*handler.first << message;
}
}
}
/* Mutex already locked by caller. */
void Logger::refresh_log_level() {
level_ = Level::OFF;
Level level = Level::OFF;
for (auto & handler : handlers_) {
if (level_ < handler.second) {
level_ = handler.second;
for (auto & handler : *registered_handlers()) {
if (level < handler.second) {
level = handler.second;
}
}
global_level_ = level;
}
} // namespace log
} // namespace uuid
} // namespace uuid

View File

@@ -28,7 +28,7 @@ namespace log {
bool parse_level_lowercase(const std::string & name, Level & level) {
for (auto value : levels()) {
if (!strcmp_P(name.c_str(), reinterpret_cast<PGM_P>(format_level_lowercase(value)))) {
if (!strcmp(name.c_str(), format_level_lowercase(value))) {
level = value;
return true;
}

View File

@@ -28,7 +28,7 @@ namespace log {
bool parse_level_uppercase(const std::string & name, Level & level) {
for (auto value : levels()) {
if (!strcmp_P(name.c_str(), reinterpret_cast<PGM_P>(format_level_uppercase(value)))) {
if (!strcmp(name.c_str(), format_level_uppercase(value))) {
level = value;
return true;
}

View File

@@ -0,0 +1,106 @@
/*
* uuid-log - Microcontroller logging framework
* Copyright 2022 Simon Arlott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uuid/log.h>
#include <Arduino.h>
#include <memory>
#if UUID_LOG_THREAD_SAFE
#include <mutex>
#endif
namespace uuid {
namespace log {
PrintHandler::PrintHandler(::Print & print)
: print_(print) {
}
size_t PrintHandler::maximum_log_messages() const {
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
return maximum_log_messages_;
}
void PrintHandler::maximum_log_messages(size_t count) {
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
maximum_log_messages_ = std::max((size_t)1, count);
while (log_messages_.size() > maximum_log_messages_) {
log_messages_.pop_front();
}
}
void PrintHandler::loop(size_t count) {
#if UUID_LOG_THREAD_SAFE
std::unique_lock<std::mutex> lock{mutex_};
#endif
count = std::max((size_t)1, count);
while (!log_messages_.empty()) {
auto message = log_messages_.front();
log_messages_.pop_front();
#if UUID_LOG_THREAD_SAFE
lock.unlock();
#endif
print_.print(uuid::log::format_timestamp_ms(message->uptime_ms, 3).c_str());
print_.print(' ');
print_.print(uuid::log::format_level_char(message->level));
print_.print(" [");
print_.print(message->name);
print_.print("] ");
print_.println(message->text.c_str());
count--;
if (count == 0) {
break;
}
::yield();
#if UUID_LOG_THREAD_SAFE
lock.lock();
#endif
}
}
void PrintHandler::operator<<(std::shared_ptr<Message> message) {
#if UUID_LOG_THREAD_SAFE
std::lock_guard<std::mutex> lock{mutex_};
#endif
if (log_messages_.size() >= maximum_log_messages_) {
log_messages_.pop_front();
}
log_messages_.emplace_back(std::move(message));
}
} // namespace log
} // namespace uuid

View File

@@ -1,6 +1,6 @@
/*
* uuid-log - Microcontroller logging framework
* Copyright 2019 Simon Arlott
* Copyright 2019,2021-2022 Simon Arlott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
#include <Arduino.h>
#include <algorithm>
#include <atomic>
#include <cstdarg>
#include <cstdint>
#include <list>
@@ -31,6 +33,24 @@
#include <uuid/common.h>
#ifndef UUID_COMMON_THREAD_SAFE
#define UUID_COMMON_THREAD_SAFE 0
#endif
#ifndef UUID_COMMON_STD_MUTEX_AVAILABLE
#define UUID_COMMON_STD_MUTEX_AVAILABLE 0
#endif
#if UUID_COMMON_STD_MUTEX_AVAILABLE
#define UUID_LOG_THREAD_SAFE 1
#else
#define UUID_LOG_THREAD_SAFE 0
#endif
#if UUID_LOG_THREAD_SAFE
#include <mutex>
#endif
namespace uuid {
/**
@@ -70,6 +90,17 @@ namespace uuid {
namespace log {
/**
* Thread-safe status of the library.
*
* @since 2.3.0
*/
#if UUID_COMMON_THREAD_SAFE && UUID_LOG_THREAD_SAFE
static constexpr bool thread_safe = true;
#else
static constexpr bool thread_safe = false;
#endif
/**
* Severity level of log messages.
*
@@ -158,10 +189,10 @@ char format_level_char(Level level);
* Format a log level as an uppercase string.
*
* @param[in] level Log level.
* @return Uppercase name of the log level (flash string).
* @return Uppercase name of the log level
* @since 1.0.0
*/
const __FlashStringHelper * format_level_uppercase(Level level);
const char * format_level_uppercase(Level level);
/**
* Get all log levels as uppercase strings.
@@ -187,10 +218,10 @@ bool parse_level_uppercase(const std::string & name, Level & level);
* Format a log level as a lowercase string.
*
* @param[in] level Log level.
* @return Lowercase name of the log level (flash string).
* @return Lowercase name of the log level
* @since 1.0.0
*/
const __FlashStringHelper * format_level_lowercase(Level level);
const char * format_level_lowercase(Level level);
/**
* Get all log levels as lowercase strings.
@@ -227,7 +258,7 @@ struct Message {
* @param[in] uptime_ms System uptime, see uuid::get_uptime_ms().
* @param[in] level Severity level of the message.
* @param[in] facility Facility type of the process logging the message.
* @param[in] name Logger name (flash string).
* @param[in] name Logger name
* @param[in] text Log message text.
* @since 1.0.0
*/
@@ -257,7 +288,7 @@ struct Message {
const Facility facility;
/**
* Name of the logger used (flash string).
* Name of the logger used
*
* @since 1.0.0
*/
@@ -274,14 +305,24 @@ struct Message {
const std::string text;
};
class Logger;
/**
* Logger handler used to process log messages.
*
* @since 1.0.0
*/
class Handler {
/**
* Logger needs to be able to access the private reference to
* the registered log handlers.
*
* @since 2.1.2
*/
friend Logger;
public:
virtual ~Handler() = default;
virtual ~Handler();
/**
* Add a new log message.
@@ -290,9 +331,20 @@ class Handler {
* processed immediately so that log messages have minimal impact
* at the time of use.
*
* Handlers must avoid holding a lock on a mutex used for adding
* messages while processing those messages. Release the lock while
* performing the processing.
*
* Queues should have a maximum size and discard the oldest message
* when full.
*
* It is not safe for the handler to directly or indirectly do any
* of the following while this function is being called:
* - Log a message.
* - Read the log level of any handler.
* - Modify the log level of any handler.
* - Unregister any handler.
*
* @param[in] message New log message, shared by all handlers.
* @since 1.0.0
*/
@@ -300,6 +352,17 @@ class Handler {
protected:
Handler() = default;
private:
/**
* Reference to registered log handlers.
*
* Used in the destructor to safely unregister the handler even if
* the underlying map has already been destroyed.
*
* @since 2.1.2
*/
std::weak_ptr<std::map<Handler *, Level>> handlers_;
};
/**
@@ -309,7 +372,7 @@ class Handler {
*/
class Logger {
public:
/**
/**
* This is the maximum length of any log message.
*
* Determines the size of the buffer used for format string
@@ -317,16 +380,12 @@ class Logger {
*
* @since 1.0.0
*/
#if defined(EMSESP_STANDALONE)
static constexpr size_t MAX_LOG_LENGTH = 500;
#else
static constexpr size_t MAX_LOG_LENGTH = 255;
#endif
/**
* Create a new logger with the given name and logging facility.
*
* @param[in] name Logger name (flash string).
* @param[in] name Logger name
* @param[in] facility Default logging facility for messages.
*
* @since 1.0.0
@@ -339,8 +398,6 @@ class Logger {
*
* Call again to change the log level.
*
* Do not call this function from a static initializer.
*
* @param[in] handler Handler object that will handle log
* messages.
* @param[in] level Minimum log level that the handler is
@@ -354,8 +411,6 @@ class Logger {
*
* It is safe to call this with a handler that is not registered.
*
* Do not call this function from a static initializer.
*
* @param[in] handler Handler object that will no longer handle
* log messages.
* @since 1.0.0
@@ -367,8 +422,6 @@ class Logger {
*
* It is safe to call this with a handler that is not registered.
*
* Do not call this function from a static initializer.
*
* @param[in] handler Handler object that may handle log
* messages.
* @return The current log level of the specified handler.
@@ -377,17 +430,71 @@ class Logger {
static Level get_log_level(const Handler * handler);
/**
* Determine if the current log level is enabled by any registered
* handlers.
* Get the current global log level.
*
* @return The current minimum global log level across all
* handlers.
* @since 1.0.0
* @return The minimum log level across all handlers.
* @since 3.0.0
*/
static inline bool enabled(Level level) {
return level <= level_;
static Level global_level() {
return global_level_;
};
/**
* Determine if the specified log level is enabled by the effective
* log level.
*
* @param[in] level Log level to check.
* @return If the specified log level is enabled on this logger.
* @since 3.0.0
*/
inline bool enabled(Level level) const {
return level <= global_level_ && level <= local_level_;
}
/**
* Get the default logging facility for new messages of this logger.
*
* @return The default logging facility for messages.
* @since 2.3.0
*/
inline Facility facility() const {
return facility_;
}
/**
* Get the log level.
*
* The effective log level will be depend on handlers.
*
* @return The log level of this logger.
* @since 3.0.0
*/
inline Level level() const {
return local_level_;
}
/**
* Set the log level.
*
* The effective log level will be depend on handlers.
*
* @param[in] level Log level for this logger.
* @since 3.0.0
*/
inline void level(Level level) {
local_level_ = level;
}
/**
* Get the effective log level.
*
* @return The effective log level for this logger.
* @since 3.0.0
*/
Level effective_level() const {
return std::min(global_level(), local_level_);
};
/**
* Log a message at level Level::EMERG.
*
@@ -396,14 +503,6 @@ class Logger {
* @since 1.0.0
*/
void emerg(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::EMERG.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void emerg(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::ALERT.
@@ -413,14 +512,6 @@ class Logger {
* @since 1.0.0
*/
void alert(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::ALERT.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void alert(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::CRIT.
@@ -430,14 +521,6 @@ class Logger {
* @since 1.0.0
*/
void crit(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::CRIT.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void crit(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::ERR.
@@ -447,14 +530,6 @@ class Logger {
* @since 1.0.0
*/
void err(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::ERR.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void err(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::WARNING.
@@ -464,14 +539,6 @@ class Logger {
* @since 1.0.0
*/
void warning(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::WARNING.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void warning(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::NOTICE.
@@ -481,14 +548,6 @@ class Logger {
* @since 1.0.0
*/
void notice(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::NOTICE.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void notice(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::INFO.
@@ -498,13 +557,6 @@ class Logger {
* @since 1.0.0
*/
void info(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::INFO.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
*/
void info(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::DEBUG.
@@ -514,14 +566,6 @@ class Logger {
* @since 1.0.0
*/
void debug(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::DEBUG.
*
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void debug(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::TRACE.
@@ -531,14 +575,16 @@ class Logger {
* @since 1.0.0
*/
void trace(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
/**
* Log a message at level Level::TRACE.
* Log a message with default facility.
*
* @param[in] format Format string (flash string).
* @param[in] level Severity level of the message.
* @param[in] format Format string.
* @param[in] ... Format string arguments.
* @since 1.0.0
* @since 3.0.0
*/
void trace(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
void log(Level level, const char * format, ...) const /* __attribute__((format (printf, 3, 4))) */;
/**
* Log a message with a custom facility.
@@ -549,17 +595,7 @@ class Logger {
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void log(Level level, Facility facility, const char * format, ...) const /* __attribute__((format (printf, 3, 4))) */;
/**
* Log a message with a custom facility.
*
* @param[in] level Severity level of the message.
* @param[in] facility Facility type of the process logging the message.
* @param[in] format Format string (flash string).
* @param[in] ... Format string arguments.
* @since 1.0.0
*/
void log(Level level, Facility facility, const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 4, 5))) */;
void log(Level level, Facility facility, const char * format, ...) const /* __attribute__((format (printf, 4, 5))) */;
private:
/**
@@ -568,6 +604,13 @@ class Logger {
* @since 1.0.0
*/
static void refresh_log_level();
/**
* Get registered log handlers.
*
* @return The registered log handlers.
* @since 2.1.2
*/
static std::shared_ptr<std::map<Handler *, Level>> & registered_handlers();
/**
* Log a message at the specified level.
@@ -578,15 +621,6 @@ class Logger {
* @since 1.0.0
*/
void vlog(Level level, const char * format, va_list ap) const;
/**
* Log a message at the specified level.
*
* @param[in] level Severity level of the message.
* @param[in] format Format string (flash string).
* @param[in] ap Variable arguments pointer for format string.
* @since 1.0.0
*/
void vlog(Level level, const __FlashStringHelper * format, va_list ap) const;
/**
* Log a message at the specified level and facility.
@@ -598,16 +632,6 @@ class Logger {
* @since 1.0.0
*/
void vlog(Level level, Facility facility, const char * format, va_list ap) const;
/**
* Log a message at the specified level and facility.
*
* @param[in] level Severity level of the message.
* @param[in] facility Facility type of the process logging the message.
* @param[in] format Format string (flash string).
* @param[in] ap Variable arguments pointer for format string.
* @since 1.0.0
*/
void vlog(Level level, Facility facility, const __FlashStringHelper * format, va_list ap) const;
/**
* Dispatch a log message to all handlers that are registered to
@@ -623,15 +647,87 @@ class Logger {
*/
void dispatch(Level level, Facility facility, std::vector<char> & text) const;
static std::map<Handler *, Level> handlers_; /*!< Registered log handlers. @since 1.0.0 */
static Level level_; /*!< Minimum global log level across all handlers. @since 1.0.0 */
static std::atomic<Level> global_level_; /*!< Minimum global log level across all handlers. @since 3.0.0 */
#if UUID_LOG_THREAD_SAFE
static std::mutex mutex_; /*!< Mutex for handlers. @since 2.3.0 */
#endif
const char * name_; /*!< Logger name (flash string). @since 1.0.0 */
const Facility facility_; /*!< Default logging facility for messages. @since 1.0.0 */
const char * name_; /*!< Logger name */
const Facility facility_; /*!< Default logging facility for messages. @since 1.0.0 */
Level local_level_{Level::ALL}; /*!< Logger level. @since 3.0.0 */
};
/**
* Basic log handler for writing messages to any object supporting the
* Print interface.
*
* Outputs all queued messages by default, which may result in the
* application blocking until writes complete if the Print destination
* buffer is full.
*
* @since 2.2.0
*/
class PrintHandler : public uuid::log::Handler {
public:
static constexpr size_t MAX_LOG_MESSAGES = 50; /*!< Maximum number of log messages to buffer before they are output. @since 2.2.0 */
/**
* Create a new Print log handler.
*
* @param[in] print Destination for output of log messages.
* @since 2.2.0
*/
PrintHandler(Print & print);
~PrintHandler() = default;
/**
* Get the maximum number of queued log messages.
*
* @return The maximum number of queued log messages.
* @since 2.2.0
*/
size_t maximum_log_messages() const;
/**
* Set the maximum number of queued log messages.
*
* Defaults to PrintHandler::MAX_LOG_MESSAGES.
*
* @since 2.2.0
*/
void maximum_log_messages(size_t count);
/**
* Dispatch queued log messages.
*
* @param[in] count Maximum number of messages to output.
* @since 2.2.0
*/
void loop(size_t count = SIZE_MAX);
/**
* Add a new log message.
*
* This will be put in a queue for output at the next loop()
* process. The queue has a maximum size of
* get_maximum_log_messages() and will discard the oldest message
* first.
*
* @param[in] message New log message, shared by all handlers.
* @since 2.2.0
*/
virtual void operator<<(std::shared_ptr<Message> message);
private:
Print & print_; /*!< Destination for output of log messages. @since 2.2.0 */
#if UUID_LOG_THREAD_SAFE
mutable std::mutex mutex_; /*!< Mutex for configuration, state and queued log messages. @since 2.3.0 */
#endif
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum number of log messages to buffer before they are output. @since 2.2.0 */
std::list<std::shared_ptr<Message>> log_messages_; /*!< Queued log messages, in the order they were received. @since 2.2.0 */
};
} // namespace log
} // namespace uuid
#endif
#endif