Skip to content

Commit

Permalink
Merged in f/EL20-403_Passing_compile_time_format_strings_correctly (p…
Browse files Browse the repository at this point in the history
…ull request #14)

F/EL20-403 Passing compile time format strings correctly

Approved-by: Stefano Zambon
Approved-by: Ilias Bergstrom
Approved-by: Marco Del Fiasco
  • Loading branch information
noizebox committed Mar 27, 2024
2 parents e48a465 + 0196aeb commit 3f4dbee
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 48 deletions.
150 changes: 115 additions & 35 deletions include/elklog/elk_logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,77 +250,157 @@ class ElkLogger
}

template<typename... Args>
void debug(const char* format_str, Args&&... args)
void debug(spdlog::format_string_t<Args...> 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>(args)...);
}
else
{
_logger_instance->debug(format_str, std::forward<Args>(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<typename... Args>
void info(const char* format_str, Args&&... args)
void info(spdlog::format_string_t<Args...> 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>(args)...);
}
else
{
_logger_instance->info(format_str, std::forward<Args>(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<typename... Args>
void warning(const char* format_str, Args&&... args)
void warning(spdlog::format_string_t<Args...> 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>(args)...);
}
else
{
_logger_instance->warn(format_str, std::forward<Args>(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<typename... Args>
void error(const char* format_str, Args&&... args)
void error(spdlog::format_string_t<Args...> 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>(args)...);
}
else
{
_logger_instance->error(format_str, std::forward<Args>(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<typename... Args>
void critical(const char* format_str, Args&&... args)
void critical(spdlog::format_string_t<Args...> 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>(args)...);
}
else
{
_logger_instance->critical(format_str, std::forward<Args>(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);
}
}
}

Expand Down
57 changes: 47 additions & 10 deletions include/elklog/rtlogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <string>
#include <functional>
#include <type_traits>

#include "rtlogmessage.h"

Expand All @@ -37,6 +38,8 @@
#include <thread>
#include <atomic>

#include "spdlog/spdlog.h"

#include "fifo/circularfifo_memory_relaxed_aquire_release.h"
#include "twine/twine.h"

Expand Down Expand Up @@ -92,44 +95,78 @@ class RtLogger
}

template<RtLogLevel level, typename... Args>
void log(const char* format_str, Args&&... args)
void log(spdlog::format_string_t<Args...> format_str, Args&&... args)
{
if (_min_log_level < level)
{
return;
}
RtLogMessage<message_len> message;
message.set_message(level, twine::current_rt_time(), format_str, std::forward<Args>(args)...);

_lock.lock();
_queue.push(message);
_lock.unlock();
}

template<RtLogLevel level>
void log(spdlog::string_view_t msg)
{
if (_min_log_level < level)
{
return;
}
RtLogMessage<message_len> 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);
_lock.unlock();
}

template<typename... Args>
void log_debug(const char* format_str, Args&&... args)
void log_debug(spdlog::format_string_t<Args...> format_str, Args&&... args)
{
log<RtLogLevel::DBG>(format_str, std::forward<Args>(args)...);
}

void log_debug(spdlog::string_view_t msg)
{
log<RtLogLevel::DBG>(format_str, args...);
log<RtLogLevel::DBG>(msg);
}

template<typename... Args>
void log_info(const char* format_str, Args&&... args)
void log_info(spdlog::format_string_t<Args...> format_str, Args&&... args)
{
log<RtLogLevel::INFO>(format_str, std::forward<Args>(args)...);
}

void log_info(spdlog::string_view_t msg)
{
log<RtLogLevel::INFO>(format_str, args...);
log<RtLogLevel::INFO>(msg);
}

template<typename... Args>
void log_warning(const char* format_str, Args&&... args)
void log_warning(spdlog::format_string_t<Args...> format_str, Args&&... args)
{
log<RtLogLevel::WARNING>(format_str, std::forward<Args>(args)...);
}

void log_warning(spdlog::string_view_t msg)
{
log<RtLogLevel::WARNING>(format_str, args...);
log<RtLogLevel::WARNING>(msg);
}

template<typename... Args>
void log_error(const char* format_str, Args&&... args)
void log_error(spdlog::format_string_t<Args...> format_str, Args&&... args)
{
log<RtLogLevel::ERROR>(format_str, args...);
log<RtLogLevel::ERROR>(format_str, std::forward<Args>(args)...);
}

void log_error(spdlog::string_view_t msg)
{
log<RtLogLevel::ERROR>(msg);
}

private:
void _consumer_worker()
Expand Down
21 changes: 19 additions & 2 deletions include/elklog/rtlogmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ ELK_DISABLE_DEPRECATED
#include <spdlog/fmt/bundled/chrono.h>
ELK_POP_WARNING

#include "spdlog/spdlog.h"
#include "rtloglevel.h"

namespace elklog {
Expand Down Expand Up @@ -101,17 +102,33 @@ class RtLogMessage
*/
template<typename... Args>
void set_message(RtLogLevel level, std::chrono::nanoseconds timestamp,
const char* format_str, Args&&... args)
spdlog::format_string_t<Args...> 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>(args)...);

// Add null-termination character
*end.out = '\0';
_length = static_cast<int>(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<int>(msg.size()) + 1;
}



private:
RtLogLevel _level;
std::chrono::nanoseconds _timestamp;
Expand Down
14 changes: 13 additions & 1 deletion test/unittests/rtlogmessage_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ TEST(RtLogMessageTest, TestCreation)
ASSERT_STREQ("", module_under_test.message());
}

TEST(RtLogMessageTest, TestCopyingAndAssignment)
TEST(RtLogMessageTest, TestCopyingAndAssignmentFormatted)
{
RtLogMessage<512> module_under_test;

Expand All @@ -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;
Expand Down

0 comments on commit 3f4dbee

Please sign in to comment.