Add %N pattern formatter for logging the thread name using pthreads

This commit adds the SPDLOG_NO_PTHREAD_ID CMake option for enabling
saving of the pthread handle. This can be used in conjunction with the
%N pattern formatter for logging the name of the thread. This can be
really useful if you have a large application with many threads that are
hard to differentiate.

The option is disabled by default as I'm sure this won't work on
windows.

This patch also adds a test for testing the new flag.
pull/2149/head
VayuDev 4 years ago
parent 6aafa89d20
commit 911480e1c3

@ -105,6 +105,7 @@ endif()
option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF)
option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF)
option(SPDLOG_NO_PTHREAD_ID "prevent spdlog from querying the pthread id on each log call if pthread id is not needed (required for %N)" ON)
option(SPDLOG_NO_TLS "prevent spdlog from using thread local storage" OFF)
option(
SPDLOG_NO_ATOMIC_LEVELS
@ -220,6 +221,7 @@ foreach(
SPDLOG_CLOCK_COARSE
SPDLOG_PREVENT_CHILD_FD
SPDLOG_NO_THREAD_ID
SPDLOG_NO_PTHREAD_ID
SPDLOG_NO_TLS
SPDLOG_NO_ATOMIC_LEVELS
SPDLOG_DISABLE_DEFAULT_LOGGER)

@ -19,6 +19,9 @@ SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::s
, time(log_time)
#ifndef SPDLOG_NO_THREAD_ID
, thread_id(os::thread_id())
#endif
#ifndef SPDLOG_NO_PTHREAD_ID
, pthread_id(pthread_self())
#endif
, source(loc)
, payload(msg)

@ -22,6 +22,10 @@ struct SPDLOG_API log_msg
log_clock::time_point time;
size_t thread_id{0};
#ifndef SPDLOG_NO_PTHREAD_ID
pthread_t pthread_id{0};
#endif
// wrapping the formatted text with color (updated by pattern_formatter).
mutable size_t color_range_start{0};
mutable size_t color_range_end{0};

@ -658,6 +658,29 @@ public:
}
};
// Thread name
template<typename ScopedPadder>
class N_formatter final : public flag_formatter
{
public:
explicit N_formatter(padding_info padinfo)
: flag_formatter(padinfo)
{}
void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override
{
char threadNameBuffer[16] = { 0 };
#ifndef SPDLOG_NO_PTHREAD_ID
pthread_getname_np(msg.pthread_id, threadNameBuffer, 16);
#endif
threadName_ = threadNameBuffer;
ScopedPadder p(threadName_.size(), padinfo_, dest);
fmt_helper::append_string_view(threadName_, dest);
}
private:
std::string threadName_;
};
// Current pid
template<typename ScopedPadder>
class pid_formatter final : public flag_formatter
@ -1115,6 +1138,10 @@ SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_i
formatters_.push_back(details::make_unique<details::t_formatter<Padder>>(padding));
break;
case ('N'): // thread name
formatters_.push_back(details::make_unique<details::N_formatter<Padder>>(padding));
break;
case ('v'): // the message text
formatters_.push_back(details::make_unique<details::v_formatter<Padder>>(padding));
break;

@ -59,6 +59,23 @@ TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
REQUIRE(log_to_str("Some message", "%D %v", spdlog::pattern_time_type::local, "\n") == oss.str());
}
#ifndef SPDLOG_NO_PTHREAD_ID
TEST_CASE("thread name formatter", "[pattern_formatter]")
{
char originalName[16] = { 0 };
pthread_getname_np(pthread_self(), originalName, 16);
std::string expected = "[";
expected += originalName;
expected += "] Some message\n";
REQUIRE(log_to_str("Some message", "[%N] %v", spdlog::pattern_time_type::local, "\n") == expected);
pthread_setname_np(pthread_self(), "Testname");
REQUIRE(log_to_str("Some message", "[%N] %v", spdlog::pattern_time_type::local, "\n") == "[Testname] Some message\n");
pthread_setname_np(pthread_self(), originalName);
}
#endif
TEST_CASE("color range test1", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%v%$", spdlog::pattern_time_type::local, "\n");

Loading…
Cancel
Save