From 48adc084c3a0c200ee10a94b3359f4cda5139310 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 29 Dec 2022 06:32:01 +0100 Subject: [PATCH] Logging Module improved a LOT --- src/log.cc | 301 +++++++++++++++++++++++++++++++++++++++++++ src/log.h | 127 ++++++++++++++++++ src/valog.cc | 170 ------------------------ src/valog.h | 17 --- src/valog.hh | 49 ------- src/valog_internal.h | 35 ----- 6 files changed, 428 insertions(+), 271 deletions(-) create mode 100644 src/log.cc create mode 100644 src/log.h delete mode 100644 src/valog.cc delete mode 100644 src/valog.h delete mode 100644 src/valog.hh delete mode 100644 src/valog_internal.h diff --git a/src/log.cc b/src/log.cc new file mode 100644 index 0000000..424d614 --- /dev/null +++ b/src/log.cc @@ -0,0 +1,301 @@ +#include "log.h" +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------------------------- +// Private functions Prototypes +//------------------------------------------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + const char* _orca_log_level_to_string(const ORCA_LOG_LEVEL* level); +#ifdef __cplusplus +} +#endif + +namespace Orca { + namespace Utils { + std::string _to_termcol(const ORCA_LOG_COLOR& col); + std::string _decorate_three_lines(const std::string& msg, char decoration = '-'); + std::string _decorate_centered(const std::string& msg, char decoration = '-'); + } // namespace Utils + namespace Log { + std::mutex _mtx_raw_log{}; + std::mutex _mtx_log{}; + std::atomic _log_level{ ORCA_LOG_LEVEL_NONE }; + std::atomic _log_color{ ORCA_LOG_COLOR_WHITE }; + namespace Backend { + void _log_stderr(const std::string& msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); + } + } // namespace Log +} // namespace Orca + +//------------------------------------------------------------------------------------------------- +// C linkage functions +//------------------------------------------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif + + void orca_log_set_level(ORCA_LOG_LEVEL level) + { + Orca::Log::_log_level.store(level); + } + + ORCA_LOG_LEVEL orca_log_get_level() + { + return Orca::Log::_log_level.load(); + } + + void orca_log_set_color(ORCA_LOG_COLOR col) + { + if (col == ORCA_LOG_COLOR_DEFAULT) { + col = ORCA_LOG_COLOR_RESET; + } + Orca::Log::_log_color.store(col); + } + + ORCA_LOG_COLOR orca_log_get_color() + { + return Orca::Log::_log_color.load(); + } + + void orca_log(const char* msg) + { + Orca::Log::Backend::_log_stderr(msg, Orca::Log::_log_color.load()); + } + + void orca_log_h1(const char* msg) + { + Orca::Log::Backend::_log_stderr( + Orca::Utils::_decorate_three_lines(msg, '='), + Orca::Log::_log_color.load()); + } + + void orca_log_h2(const char* msg) + { + Orca::Log::Backend::_log_stderr( + "\n" + Orca::Utils::_decorate_centered(msg, '='), + Orca::Log::_log_color.load()); + } + + void orca_log_h3(const char* msg) + { + Orca::Log::Backend::_log_stderr(Orca::Utils::_decorate_centered(msg, '-'), Orca::Log::_log_color.load()); + } + + + void _orca_log_for_macro( + ORCA_LOG_LEVEL level, + const char* file, + int line, + const char* funcname, + const char* fmt, + ...) + { + std::lock_guard l{ Orca::Log::_mtx_log }; + if (level > Orca::Log::_log_level) { + return; + } + std::string msg{ "orca log subsystem error" }; + va_list var_args; + va_start(var_args, fmt); + + char* msg_fmtd = nullptr; + int size = vasprintf(&msg_fmtd, fmt, var_args); + if (size >= 0) { + std::stringstream header{}; + header << _orca_log_level_to_string(&level) << " "; + header << getpid() << " "; + header << std::this_thread::get_id() << " "; + header << file << ":"; + header << line << " "; + header << funcname << " "; + msg = header.str(); + if (!std::string(msg_fmtd).empty()) { + msg += "- " + std::string(msg_fmtd); + } + } + free(msg_fmtd); + Orca::Log::log(msg); + va_end(var_args); + } + + const char* _orca_log_level_to_string(const ORCA_LOG_LEVEL* level) + { + switch (*level) { + case ORCA_LOG_LEVEL_NONE: + return "NONE"; + case ORCA_LOG_LEVEL_ERROR: + return "ERROR"; + case ORCA_LOG_LEVEL_WARN: + return "WARN"; + case ORCA_LOG_LEVEL_INFO: + return "INFO"; + case ORCA_LOG_LEVEL_ALL: + return "ALL"; + default: + return "invalid log level"; + } + } +#ifdef __cplusplus +} +#endif + +//------------------------------------------------------------------------------------------------- +// C++ Linkage functions +//------------------------------------------------------------------------------------------------- + +namespace Orca { + namespace Log { + // for C++ some functions are just wrappers for the + // C linkage functions + // to be nicely available in the namespace + + void set_level(ORCA_LOG_LEVEL level) + { + ::orca_log_set_level(level); + } + + ORCA_LOG_LEVEL get_level() + { + return ::orca_log_get_level(); + } + + void set_color(ORCA_LOG_COLOR col) + { + ::orca_log_set_color(col); + } + + ORCA_LOG_COLOR get_color() + { + return ::orca_log_get_color(); + } + + void _log_for_macro( + ORCA_LOG_LEVEL level, + const std::string& file, + int line, + const std::string& funcname, + const std::string& msg) + { + ::_orca_log_for_macro(level, file.c_str(), line, funcname.c_str(), "%s", msg.c_str()); + } + + void log(const std::string& msg, ORCA_LOG_COLOR col) + { + Backend::_log_stderr(msg, col); + } + + void logH1(const std::string& msg, ORCA_LOG_COLOR col) + { + Backend::_log_stderr(Utils::_decorate_three_lines(msg, '='), col); + } + + void logH2(const std::string& msg, ORCA_LOG_COLOR col) + { + Backend::_log_stderr("\n" + Utils::_decorate_centered(msg, '='), col); + } + + void logH3(const std::string& msg, ORCA_LOG_COLOR col) + { + Backend::_log_stderr(Utils::_decorate_centered(msg, '-'), col); + } + + namespace Backend { + // TODO: add file backend + void _log_stderr(const std::string& msg, ORCA_LOG_COLOR col) + { + std::lock_guard l{ _mtx_raw_log }; + std::cerr << Utils::_to_termcol(col) << msg + << Utils::_to_termcol(ORCA_LOG_COLOR_RESET) + << std::endl; //endl also flushes, but cerr is unbuffered anyways + } + } + } // namespace Log + + + + namespace Utils { + int termsize_x = 120; + + std::string _to_termcol(const ORCA_LOG_COLOR& col) + { + switch (col) { + case ORCA_LOG_COLOR_DEFAULT: + return _to_termcol(Orca::Log::_log_color); + case ORCA_LOG_COLOR_RESET: + return "\033[0m"; + case ORCA_LOG_COLOR_BLACK: + return "\033[30m"; + case ORCA_LOG_COLOR_RED: + return "\033[31m"; + case ORCA_LOG_COLOR_GREEN: + return "\033[32m"; + case ORCA_LOG_COLOR_YELLOW: + return "\033[33m"; + case ORCA_LOG_COLOR_BLUE: + return "\033[34m"; + case ORCA_LOG_COLOR_MAGENTA: + return "\033[35m"; + case ORCA_LOG_COLOR_CYAN: + return "\033[36m"; + case ORCA_LOG_COLOR_WHITE: + return "\033[37m"; + default: + return _to_termcol(ORCA_LOG_COLOR_RESET); + } + } + + std::string _decorate_three_lines(const std::string& msg, char decoration) + { + std::stringstream tmp; + tmp << std::string(termsize_x, decoration) << std::endl + << msg << std::endl + << std::string(termsize_x, decoration); + return tmp.str(); + } + + std::string _decorate_centered(const std::string& msg, char decoration) + { + std::stringstream tmp; + size_t max_len = termsize_x - 10; + // truncate msg + std::string msg_truncated = msg; + if (msg.length() >= max_len) { + msg_truncated = msg.substr(0, max_len); + msg_truncated += "..."; + } + + // define decolen + int decolen = static_cast(floor((double(termsize_x - msg_truncated.length()))) / 2.0); + + tmp << std::string(decolen, decoration) << ' ' << msg_truncated << ' ' + << std::string(decolen, decoration); + return tmp.str(); + } + } // namespace Utils +} // namespace Orca + +//------------------------------------------------------------------------------------------------- +// C++ Linkage global namespace members +//------------------------------------------------------------------------------------------------- +std::ostream& operator<<(std::ostream& o, const ORCA_LOG_LEVEL* level) +{ + return o << std::string(_orca_log_level_to_string(level)); +} + +// Stuff like that would be fucking handy +// TODO: make a lib with operator<< for ALL libstc++ types +template std::ostream& operator<<(std::ostream& o, std::vector& vec) +{ + std::stringstream ss{}; + for (const T& elem : vec) { + o << elem; + } + return o; +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..8ee0808 --- /dev/null +++ b/src/log.h @@ -0,0 +1,127 @@ +#ifndef _ORCA_VALOG_H +#define _ORCA_VALOG_H + +#define ORCA_LOG_FUNCTION_ENTRY 1 + +//TODO implement compile time max level/disable +#ifndef ORCA_LOG_LEVEL_MAXIMUM + #define ORCA_LOG_LEVEL_MAXIMUM ORCA_LOG_LEVEL_INFO +#endif + +//TODO auto detect via compiler +#ifdef ORCA_LOG_HAVE_PRETTY_FUNCTION + #define ORCA_LOG_MACRO_FUNCNAME __PRETTY_FUNCTION__ +#else + #define ORCA_LOG_MACRO_FUNCNAME __func__ +#endif + + +typedef enum { + ORCA_LOG_LEVEL_NONE = 0, // Logging Disabled + ORCA_LOG_LEVEL_ERROR = 100, + ORCA_LOG_LEVEL_WARN = 200, + ORCA_LOG_LEVEL_INFO = 300, + ORCA_LOG_LEVEL_ALL = 1000000 // Convenience +} ORCA_LOG_LEVEL; + +typedef enum { + ORCA_LOG_COLOR_DEFAULT, + ORCA_LOG_COLOR_RESET, + ORCA_LOG_COLOR_BLACK, + ORCA_LOG_COLOR_RED, + ORCA_LOG_COLOR_GREEN, + ORCA_LOG_COLOR_YELLOW, + ORCA_LOG_COLOR_BLUE, + ORCA_LOG_COLOR_MAGENTA, + ORCA_LOG_COLOR_CYAN, + ORCA_LOG_COLOR_WHITE, +} ORCA_LOG_COLOR; + + +//--------------------------------------------------------------------------------------- +// C99 +//--------------------------------------------------------------------------------------- +#ifndef __cplusplus + #include + + #define ORCA_LOG_ERR(...) ORCA_LOG(ORCA_LOG_LEVEL_ERROR, __VA_ARGS__) + + #define ORCA_LOG_WARN(...) ORCA_LOG(ORCA_LOG_LEVEL_WARN, __VA_ARGS__) + + #define ORCA_LOG_INFO(...) ORCA_LOG(ORCA_LOG_LEVEL_INFO, __VA_ARGS__) + + #define ORCA_LOG(level, ...) \ + do { \ + _orca_log_for_macro(level, __FILE__, __LINE__, ORCA_LOG_MACRO_FUNCNAME, "" __VA_ARGS__); \ + } while (0) + +// config/settings +void orca_log_set_level(ORCA_LOG_LEVEL level); +ORCA_LOG_LEVEL orca_log_get_level(); +void orca_log_set_color(ORCA_LOG_COLOR col); +ORCA_LOG_COLOR orca_log_get_color(); + +// logging +void orca_log(const char* msg); +void orca_log_h1(const char* msg); +void orca_log_h2(const char* msg); +void orca_log_h3(const char* msg); + +// helper function for macro use only +void _orca_log_for_macro( + ORCA_LOG_LEVEL level, + const char* file, + int line, + const char* funcname, + const char* fmt, + ...); + +#endif // NOT __cplusplus + +//--------------------------------------------------------------------------------------- +// C++ +//--------------------------------------------------------------------------------------- +#ifdef __cplusplus + #include + #include + + #define ORCA_LOG_ERR(msg) ORCA_LOG(ORCA_LOG_LEVEL_ERROR, msg) + + #define ORCA_LOG_WARN(msg) ORCA_LOG(ORCA_LOG_LEVEL_WARN, msg) + + #define ORCA_LOG_INFO(msg) ORCA_LOG(ORCA_LOG_LEVEL_INFO, msg) + + #define ORCA_LOG(level, msg) \ + do { \ + std::stringstream ss{}; \ + ss << msg; \ + ::Orca::Log::_log_for_macro(level, __FILE__, __LINE__, ORCA_LOG_MACRO_FUNCNAME, ss.str()); \ + } while (0) + +namespace Orca { + namespace Log { + // config/settings + void set_level(ORCA_LOG_LEVEL level); + ORCA_LOG_LEVEL get_level(); + void set_color(ORCA_LOG_COLOR col); + ORCA_LOG_COLOR get_color(); + + // logging + void log(const std::string& msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); + void logH1(const std::string& msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); + void logH2(const std::string& msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); + void logH3(const std::string& msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); + + // helper function for macro use only + void _log_for_macro( + ORCA_LOG_LEVEL level, + const std::string& file, + int line, + const std::string& funcname, + const std::string& msg); + } // namespace Log +} // namespace Orca + +std::ostream& operator<<(std::ostream& o, const ORCA_LOG_LEVEL* level); +#endif //__cplusplus +#endif diff --git a/src/valog.cc b/src/valog.cc deleted file mode 100644 index 7177033..0000000 --- a/src/valog.cc +++ /dev/null @@ -1,170 +0,0 @@ -#include "valog.h" -#include "valog.hh" -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - const char* _orca_log_level_to_string(const ORCA_LOG_LEVEL* level) - { - switch (*level) { - case ORCA_LOG_LEVEL_ERROR: - return "ERROR"; - case ORCA_LOG_LEVEL_WARNING: - return "WARN"; - case ORCA_LOG_LEVEL_TRACE: - return "TRACE"; - default: - return "invalid log level"; - } - } - - void _orca_log( - ORCA_LOG_LEVEL level, - const char* file, - int line, - const char* funcname, - const char* fmt, - ...) - { - std::string msg{ "orca log subsystem error" }; - va_list var_args; - va_start(var_args, fmt); - - char* msg_fmtd = nullptr; - int size = vasprintf(&msg_fmtd, fmt, var_args); - if (size >= 0) { - std::stringstream header{}; - header << _orca_log_level_to_string(&level) << " "; - header << getpid() << " "; - header << std::this_thread::get_id() << " "; - header << file << ":"; - header << line << " "; - header << funcname << " "; - msg = header.str() + " - " + std::string(msg_fmtd); - } - free(msg_fmtd); - Orca::Log::log(msg); - va_end(var_args); - } - -#ifdef __cplusplus -} -#endif - -std::ostream& operator<<(std::ostream& o, const ORCA_LOG_LEVEL* level) -{ - return o << std::string(_orca_log_level_to_string(level)); -} - -namespace Orca { - namespace Utils { - std::string to_termcol(const Color& col) - { - switch (col) { - case Color::RESET: - return "\033[0m"; - case Color::BLACK: - return "\033[30m"; - case Color::RED: - return "\033[31m"; - case Color::GREEN: - return "\033[32m"; - case Color::YELLOW: - return "\033[33m"; - case Color::BLUE: - return "\033[34m"; - case Color::MAGENTA: - return "\033[35m"; - case Color::CYAN: - return "\033[36m"; - case Color::WHITE: - return "\033[37m"; - default: - return "\033[0m"; - } - } - } // namespace Utils -} // namespace Orca - -namespace Orca { - namespace Log { - int line_width = 120; - - // NON CLASS - std::mutex mtx; - std::atomic_bool is_enabled{ false }; - - void set_enabled(const bool& enabled) - { - is_enabled.store(enabled); - } - - bool get_enabled() - { - return is_enabled.load(); - } - - // Common "print" function implementing the actual "backends" - void _log(const std::string& msg, Utils::Color col = Utils::Color::WHITE) - { - std::lock_guard l(mtx); - std::cerr << Utils::to_termcol(col) << msg << Utils::to_termcol(Utils::Color::RESET) - << std::endl; //endl also flushes, but cerr is unbuffered anyways - } - - void log(const std::string& msg, Utils::Color col) - { - _log(msg, col); - } - - void logH1(const std::string& msg, Utils::Color col) - { - log(decorate_three_lines(msg, '='), col); - } - - void logH2(const std::string& msg, Utils::Color col) - { - log("\n" + decorate_centered(msg, '='), col); - } - - void logH3(const std::string& msg, Utils::Color col) - { - log(decorate_centered(msg, '-'), col); - } - - std::string decorate_three_lines(const std::string& msg, char decoration) - { - std::stringstream tmp; - tmp << std::string(line_width, decoration) << std::endl - << msg << std::endl - << std::string(line_width, decoration); - return tmp.str(); - } - - std::string decorate_centered(const std::string& msg, char decoration) - { - std::stringstream tmp; - size_t max_len = line_width - 10; - // truncate msg - std::string msg_truncated = msg; - if (msg.length() >= max_len) { - msg_truncated = msg.substr(0, max_len); - msg_truncated += "..."; - } - - // define decolen - int decolen = static_cast(floor((double(line_width - msg_truncated.length()))) / 2.0); - - tmp << std::string(decolen, decoration) << ' ' << msg_truncated << ' ' - << std::string(decolen, decoration); - return tmp.str(); - } - } // namespace Log -} // namespace Orca diff --git a/src/valog.h b/src/valog.h deleted file mode 100644 index cb923cd..0000000 --- a/src/valog.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ORCA_VALOG_H -#define _ORCA_VALOG_H - -#include "valog_internal.h" - -#define ORCA_LOG_ERR(...) ORCA_LOG(ORCA_LOG_LEVEL_ERROR, __VA_ARGS__) - -#define ORCA_LOG_WARN(...) ORCA_LOG(ORCA_LOG_LEVEL_WARN, __VA_ARGS__) - -#define ORCA_LOG_TRACE(...) ORCA_LOG(ORCA_LOG_LEVEL_TRACE, __VA_ARGS__) - -#define ORCA_LOG(level, ...) \ - do { \ - _orca_log(level, __FILE__, __LINE__, ORCA_MACRO_FUNCNAME, "" __VA_ARGS__); \ - } while (0) - -#endif diff --git a/src/valog.hh b/src/valog.hh deleted file mode 100644 index 524ddb1..0000000 --- a/src/valog.hh +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _ORCA_VALOG_HH -#define _ORCA_VALOG_HH - -#include -#include "valog_internal.h" - -#define ORCA_LOG_ERR(...) ORCA_LOG(ORCA_LOG_LEVEL_ERROR, __VA_ARGS__) - -#define ORCA_LOG_WARN(...) ORCA_LOG(ORCA_LOG_LEVEL_WARN, __VA_ARGS__) - -#define ORCA_LOG_TRACE(...) ORCA_LOG(ORCA_LOG_LEVEL_TRACE, __VA_ARGS__) - -#define ORCA_LOG(level, ...) \ - do { \ - _orca_log(level, __FILE__, __LINE__, ORCA_MACRO_FUNCNAME, "" __VA_ARGS__); \ - } while (0) - - -namespace Orca { - namespace Utils { - enum class Color { - RESET, - BLACK, - RED, - GREEN, - YELLOW, - BLUE, - MAGENTA, - CYAN, - WHITE, - }; - std::string to_termcol(const Color& col); - } // namespace Utils - - namespace Log { - void set_enabled(const bool& is_enabled); - bool get_enabled(); - void log(const std::string& msg, Utils::Color col = Utils::Color::WHITE); - void logH1(const std::string& msg, Utils::Color col = Utils::Color::WHITE); - void logH2(const std::string& msg, Utils::Color col = Utils::Color::WHITE); - void logH3(const std::string& msg, Utils::Color col = Utils::Color::WHITE); - std::string decorate_three_lines(const std::string& msg, char decoration = '-'); - std::string decorate_centered(const std::string& msg, char decoration = '-'); - } // namespace Log -} // namespace Orca - -std::ostream& operator<<(std::ostream& o, const ORCA_LOG_LEVEL* level); - -#endif diff --git a/src/valog_internal.h b/src/valog_internal.h deleted file mode 100644 index 113db1b..0000000 --- a/src/valog_internal.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _ORCA_VALOG_INTERNAL_H -#define _ORCA_VALOG_INTERNAL_H - -#define ORCA_HAVE_PRETTY_FUNCTION 1 -#ifdef ORCA_HAVE_PRETTY_FUNCTION - #define ORCA_MACRO_FUNCNAME __PRETTY_FUNCTION__ -#else - #define ORCA_func_OR_PRETTY_FUNCTION __func__ -#endif - -typedef enum { - ORCA_LOG_LEVEL_ERROR = 100, - ORCA_LOG_LEVEL_WARNING = 200, - ORCA_LOG_LEVEL_TRACE = 300, -} ORCA_LOG_LEVEL; - - -#ifdef __cplusplus -extern "C" { -#endif - - void _orca_log( - ORCA_LOG_LEVEL level, - const char* file, - int line, - const char* funcname, - const char* fmt, - ...); - -#ifdef __cplusplus -} -#endif - - -#endif