diff --git a/include/elklog/elk_logger.h b/include/elklog/elk_logger.h index 31d64bb..8adca05 100644 --- a/include/elklog/elk_logger.h +++ b/include/elklog/elk_logger.h @@ -250,77 +250,157 @@ class ElkLogger } template - void debug(const char* format_str, Args&&... args) + void debug(spdlog::format_string_t format_str, Args&&... args) { - if (_closed == true) return; - - if (twine::is_current_thread_realtime()) + if (!_closed) { - _rt_logger->log_debug(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_debug(format_str, std::forward(args)...); + } + else + { + _logger_instance->debug(format_str, std::forward(args)...); + } } - else + } + + void debug(spdlog::string_view_t msg) + { + if (!_closed) { - _logger_instance->debug(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_debug(msg); + } + else + { + _logger_instance->debug(msg); + } } } template - void info(const char* format_str, Args&&... args) + void info(spdlog::format_string_t format_str, Args&&... args) { - if (_closed == true) return; - - if (twine::is_current_thread_realtime()) + if (!_closed) { - _rt_logger->log_info(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_info(format_str, std::forward(args)...); + } + else + { + _logger_instance->info(format_str, std::forward(args)...); + } } - else + } + + void info(spdlog::string_view_t msg) + { + if (!_closed) { - _logger_instance->info(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_info(msg); + } + else + { + _logger_instance->info(msg); + } } } template - void warning(const char* format_str, Args&&... args) + void warning(spdlog::format_string_t format_str, Args&&... args) { - if (_closed == true) return; - - if (twine::is_current_thread_realtime()) + if (!_closed) { - _rt_logger->log_warning(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_warning(format_str, std::forward(args)...); + } + else + { + _logger_instance->warn(format_str, std::forward(args)...); + } } - else + } + + void warning(spdlog::string_view_t msg) + { + if (!_closed) { - _logger_instance->warn(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_warning(msg); + } + else + { + _logger_instance->warn(msg); + } } } template - void error(const char* format_str, Args&&... args) + void error(spdlog::format_string_t format_str, Args&&... args) { - if (_closed == true) return; - - if (twine::is_current_thread_realtime()) + if (!_closed) { - _rt_logger->log_error(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_error(format_str, std::forward(args)...); + } + else + { + _logger_instance->error(format_str, std::forward(args)...); + } } - else + } + + void error(spdlog::string_view_t msg) + { + if (!_closed) { - _logger_instance->error(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_error(msg); + } + else + { + _logger_instance->error(msg); + } } } template - void critical(const char* format_str, Args&&... args) + void critical(spdlog::format_string_t format_str, Args&&... args) { - if (_closed == true) return; - - if (twine::is_current_thread_realtime()) + if (!_closed) { - _rt_logger->log_error(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_error(format_str, std::forward(args)...); + } + else + { + _logger_instance->critical(format_str, std::forward(args)...); + } } - else + } + + void critical(spdlog::string_view_t msg) + { + if (!_closed) { - _logger_instance->critical(format_str, args...); + if (twine::is_current_thread_realtime()) + { + _rt_logger->log_error(msg); + } + else + { + _logger_instance->critical(msg); + } } } diff --git a/include/elklog/rtlogger.h b/include/elklog/rtlogger.h index 16ffb41..8ea2d96 100644 --- a/include/elklog/rtlogger.h +++ b/include/elklog/rtlogger.h @@ -26,6 +26,7 @@ #include #include +#include #include "rtlogmessage.h" @@ -37,6 +38,8 @@ #include #include +#include "spdlog/spdlog.h" + #include "fifo/circularfifo_memory_relaxed_aquire_release.h" #include "twine/twine.h" @@ -92,14 +95,29 @@ class RtLogger } template - void log(const char* format_str, Args&&... args) + void log(spdlog::format_string_t format_str, Args&&... args) + { + if (_min_log_level < level) + { + return; + } + RtLogMessage message; + message.set_message(level, twine::current_rt_time(), format_str, std::forward(args)...); + + _lock.lock(); + _queue.push(message); + _lock.unlock(); + } + + template + void log(spdlog::string_view_t msg) { if (_min_log_level < level) { return; } RtLogMessage message; - message.set_message(level, twine::current_rt_time(), format_str, args...); + message.set_message(level, twine::current_rt_time(), msg); _lock.lock(); _queue.push(message); @@ -107,29 +125,48 @@ class RtLogger } template - void log_debug(const char* format_str, Args&&... args) + void log_debug(spdlog::format_string_t format_str, Args&&... args) + { + log(format_str, std::forward(args)...); + } + + void log_debug(spdlog::string_view_t msg) { - log(format_str, args...); + log(msg); } template - void log_info(const char* format_str, Args&&... args) + void log_info(spdlog::format_string_t format_str, Args&&... args) + { + log(format_str, std::forward(args)...); + } + + void log_info(spdlog::string_view_t msg) { - log(format_str, args...); + log(msg); } template - void log_warning(const char* format_str, Args&&... args) + void log_warning(spdlog::format_string_t format_str, Args&&... args) + { + log(format_str, std::forward(args)...); + } + + void log_warning(spdlog::string_view_t msg) { - log(format_str, args...); + log(msg); } template - void log_error(const char* format_str, Args&&... args) + void log_error(spdlog::format_string_t format_str, Args&&... args) { - log(format_str, args...); + log(format_str, std::forward(args)...); } + void log_error(spdlog::string_view_t msg) + { + log(msg); + } private: void _consumer_worker() diff --git a/include/elklog/rtlogmessage.h b/include/elklog/rtlogmessage.h index 7990c88..04e7895 100644 --- a/include/elklog/rtlogmessage.h +++ b/include/elklog/rtlogmessage.h @@ -37,6 +37,7 @@ ELK_DISABLE_DEPRECATED #include ELK_POP_WARNING +#include "spdlog/spdlog.h" #include "rtloglevel.h" namespace elklog { @@ -101,17 +102,33 @@ class RtLogMessage */ template void set_message(RtLogLevel level, std::chrono::nanoseconds timestamp, - const char* format_str, Args&&... args) + spdlog::format_string_t format_str, Args&&... args) { _level = level; _timestamp = timestamp; - auto end = fmt::format_to_n(_buffer.data(), buffer_len - 1, format_str, args...); + auto end = fmt::format_to_n(_buffer.data(), buffer_len - 1, format_str, std::forward(args)...); // Add null-termination character *end.out = '\0'; _length = static_cast(std::distance(_buffer.data(), end.out)); } + void set_message(RtLogLevel level, std::chrono::nanoseconds timestamp, + spdlog::string_view_t msg) + { + _level = level; + _timestamp = timestamp; + // This specialization is for single string messages without need for formatting + // In this case we simply copy the string to the buffer without invoking fmt::format() + auto end = std::copy_n(msg.begin(), std::min(msg.size(), buffer_len - 1), _buffer.data()); + + // Add null-termination character + *end = '\0'; + _length = static_cast(msg.size()) + 1; + } + + + private: RtLogLevel _level; std::chrono::nanoseconds _timestamp; diff --git a/test/unittests/rtlogmessage_test.cpp b/test/unittests/rtlogmessage_test.cpp index 5b8d162..ab57e20 100644 --- a/test/unittests/rtlogmessage_test.cpp +++ b/test/unittests/rtlogmessage_test.cpp @@ -14,7 +14,7 @@ TEST(RtLogMessageTest, TestCreation) ASSERT_STREQ("", module_under_test.message()); } -TEST(RtLogMessageTest, TestCopyingAndAssignment) +TEST(RtLogMessageTest, TestCopyingAndAssignmentFormatted) { RtLogMessage<512> module_under_test; @@ -33,6 +33,18 @@ TEST(RtLogMessageTest, TestCopyingAndAssignment) EXPECT_STREQ(module_under_test.message(), msg_2.message()); } +TEST(RtLogMessageTest, TestCopyingAndAssignment) +{ + RtLogMessage<512> module_under_test; + + module_under_test.set_message(RtLogLevel::INFO, std::chrono::nanoseconds(456), "Test single message"); + + EXPECT_STREQ("Test single message", module_under_test.message()); + EXPECT_EQ(std::chrono::nanoseconds(456), module_under_test.timestamp()); + EXPECT_EQ(RtLogLevel::INFO, module_under_test.level()); + EXPECT_EQ(20, module_under_test.length()); +} + TEST(RtLogMessageTest, TestMaxSize) { RtLogMessage<24> module_under_test;