From 8d99374f1f02a4d229b49f6697247eb1e1f4f940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 6 Sep 2017 21:30:44 +0200 Subject: When biboumi is logging into journald, use sd_journal_send This makes sure that multi-lines messages are properly parsed as a single message by journald. fix #3268 --- src/logger/logger.cpp | 4 +++ src/logger/logger.hpp | 76 ++++++++++++++++++++++++++------------------------- 2 files changed, 43 insertions(+), 37 deletions(-) (limited to 'src/logger') diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index 92a3d9b..4287794 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -7,6 +7,10 @@ Logger::Logger(const int log_level): null_buffer{}, null_stream{&null_buffer} { +#ifdef SYSTEMD_FOUND + if (::getenv("JOURNAL_STREAM") != nullptr && this->use_stdout()) + this->use_systemd = true; +#endif } Logger::Logger(const int log_level, const std::string& log_file): diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp index ff6a82b..176726e 100644 --- a/src/logger/logger.hpp +++ b/src/logger/logger.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #define debug_lvl 0 #define info_lvl 1 @@ -19,7 +20,9 @@ #include "biboumi.h" #ifdef SYSTEMD_FOUND +#define SD_JOURNAL_SUPPRESS_LOCATION # include +# include #else # define SD_DEBUG "[DEBUG]: " # define SD_INFO "[INFO]: " @@ -57,6 +60,15 @@ public: Logger(Logger&&) = delete; Logger& operator=(Logger&&) = delete; +#ifdef SYSTEMD_FOUND + bool use_stdout() const + { + return this->stream.rdbuf() == std::cout.rdbuf(); + } + + bool use_systemd{false}; +#endif + private: const int log_level; std::ofstream ofstream{}; @@ -66,8 +78,6 @@ private: std::ostream null_stream; }; -#define WHERE __FILENAME__, ":", __LINE__, ":\t" - namespace logging_details { template @@ -84,45 +94,37 @@ namespace logging_details } template - void log_debug(U&&... args) - { - auto& os = Logger::instance()->get_stream(debug_lvl); - os << SD_DEBUG; - log(os, std::forward(args)...); - } - - template - void log_info(U&&... args) - { - auto& os = Logger::instance()->get_stream(info_lvl); - os << SD_INFO; - log(os, std::forward(args)...); - } - - template - void log_warning(U&&... args) - { - auto& os = Logger::instance()->get_stream(warning_lvl); - os << SD_WARNING; - log(os, std::forward(args)...); - } - - template - void log_error(U&&... args) + void do_logging(const int level, int syslog_level, const char* src_file, int line, U&&... args) { - auto& os = Logger::instance()->get_stream(error_lvl); - os << SD_ERR; - log(os, std::forward(args)...); + #ifdef SYSTEMD_FOUND + if (Logger::instance()->use_systemd) + { + (void)level; + std::ostringstream os; + log(os, std::forward(args)...); + sd_journal_send("MESSAGE=%s", os.str().data(), + "PRIORITY=%i", syslog_level, + "CODE_FILE=%s", src_file, + "CODE_LINE=%i", line, + nullptr); + } + else + { + #endif + static const char* priority_names[] = {"DEBUG", "INFO", "WARNING", "ERROR"}; + auto& os = Logger::instance()->get_stream(level); + os << '[' << priority_names[level] << "]: " << src_file << ':' << line << ":\t"; + log(os, std::forward(args)...); +#ifdef SYSTEMD_FOUND + } +#endif } } -#define log_info(...) logging_details::log_info(WHERE, __VA_ARGS__) - -#define log_warning(...) logging_details::log_warning(WHERE, __VA_ARGS__) - -#define log_error(...) logging_details::log_error(WHERE, __VA_ARGS__) - -#define log_debug(...) logging_details::log_debug(WHERE, __VA_ARGS__) +#define log_debug(...) logging_details::do_logging(debug_lvl, LOG_DEBUG, __FILENAME__, __LINE__, __VA_ARGS__) +#define log_info(...) logging_details::do_logging(info_lvl, LOG_INFO, __FILENAME__, __LINE__, __VA_ARGS__) +#define log_warning(...) logging_details::do_logging(warning_lvl, LOG_WARNING, __FILENAME__, __LINE__, __VA_ARGS__) +#define log_error(...) logging_details::do_logging(error_lvl, LOG_ERR, __FILENAME__, __LINE__, __VA_ARGS__) -- cgit v1.2.3 From e217a1978451ca0153fee36618ff4129ffcd2804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sat, 9 Sep 2017 17:21:51 +0200 Subject: Fix the build without systemd, by adding a few define --- src/logger/logger.hpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/logger') diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp index 176726e..a99648c 100644 --- a/src/logger/logger.hpp +++ b/src/logger/logger.hpp @@ -28,6 +28,10 @@ # define SD_INFO "[INFO]: " # define SD_WARNING "[WARNING]: " # define SD_ERR "[ERROR]: " +# define LOG_ERR 3 +# define LOG_WARNING 4 +# define LOG_INFO 6 +# define LOG_DEBUG 7 #endif // Macro defined to get the filename instead of the full path. But if it is @@ -111,6 +115,7 @@ namespace logging_details else { #endif + (void)syslog_level; static const char* priority_names[] = {"DEBUG", "INFO", "WARNING", "ERROR"}; auto& os = Logger::instance()->get_stream(level); os << '[' << priority_names[level] << "]: " << src_file << ':' << line << ":\t"; -- cgit v1.2.3 From 7c8a7176d196d4bb3724cfafd41980c16be5f404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 12 Jan 2018 03:59:46 +0100 Subject: Only use sd_journal_* if we really are outputing to journald We check that the device and inode numbers are actually the same as the JOURNAL_STREAM value, instead of just checking that the value exists. This fixes the logger unit tests --- src/logger/logger.cpp | 21 ++++++++++++++++++++- src/logger/logger.hpp | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src/logger') diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index 4287794..482cb18 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -1,6 +1,10 @@ #include #include +#include +#include +#include + Logger::Logger(const int log_level): log_level(log_level), stream(std::cout.rdbuf()), @@ -8,7 +12,22 @@ Logger::Logger(const int log_level): null_stream{&null_buffer} { #ifdef SYSTEMD_FOUND - if (::getenv("JOURNAL_STREAM") != nullptr && this->use_stdout()) + if (!this->use_stdout()) + return; + + // See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#%24JOURNAL_STREAM + const char* journal_stream = ::getenv("JOURNAL_STREAM"); + if (journal_stream == nullptr) + return; + + struct stat s{}; + const int res = ::fstat(STDOUT_FILENO, &s); + if (res == -1) + return; + + const auto stdout_stream = std::to_string(s.st_dev) + ":" + std::to_string(s.st_ino); + + if (stdout_stream == journal_stream) this->use_systemd = true; #endif } diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp index a99648c..1689866 100644 --- a/src/logger/logger.hpp +++ b/src/logger/logger.hpp @@ -9,6 +9,7 @@ */ #include +#include #include #include #include -- cgit v1.2.3 From b4b9828de50c09fea5503b3b3ead2ae9d5144404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 12 Jan 2018 19:54:14 +0100 Subject: Follow log_level even when using journald output fix #3328 --- src/logger/logger.hpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/logger') diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp index 1689866..315fc11 100644 --- a/src/logger/logger.hpp +++ b/src/logger/logger.hpp @@ -74,8 +74,8 @@ public: bool use_systemd{false}; #endif -private: const int log_level; +private: std::ofstream ofstream{}; std::ostream stream; @@ -105,13 +105,16 @@ namespace logging_details if (Logger::instance()->use_systemd) { (void)level; - std::ostringstream os; - log(os, std::forward(args)...); - sd_journal_send("MESSAGE=%s", os.str().data(), - "PRIORITY=%i", syslog_level, - "CODE_FILE=%s", src_file, - "CODE_LINE=%i", line, - nullptr); + if (level >= Logger::instance()->log_level) + { + std::ostringstream os; + log(os, std::forward(args)...); + sd_journal_send("MESSAGE=%s", os.str().data(), + "PRIORITY=%i", syslog_level, + "CODE_FILE=%s", src_file, + "CODE_LINE=%i", line, + nullptr); + } } else { -- cgit v1.2.3