From 4d41913d14378aff5a72ee1a8cbc23d43579836a Mon Sep 17 00:00:00 2001 From: Per Kjellander Date: Fri, 30 Sep 2022 12:50:41 +0200 Subject: [PATCH] Implement RTC_LOG_IF and RTC_DLOG_IF and RTC_LOG_IF_F and RTC_DLOG_IF_F Bug: webrtc:14505 Change-Id: I5df1e920831f545752f6d7433f0ae853e58c0b9f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/277441 Reviewed-by: Tomas Gunnarsson Commit-Queue: Per Kjellander Reviewed-by: Evan Shrubsole Cr-Commit-Position: refs/heads/main@{#38258} --- rtc_base/logging.h | 16 +++++++++++++ rtc_base/logging_unittest.cc | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/rtc_base/logging.h b/rtc_base/logging.h index 2c3a6dcb22..d59b9a0ef7 100644 --- a/rtc_base/logging.h +++ b/rtc_base/logging.h @@ -21,9 +21,13 @@ // RTC_LOG(sev) logs the given stream at severity "sev", which must be a // compile-time constant of the LoggingSeverity type, without the namespace // prefix. +// RTC_LOG_IF(sev, condition) logs the given stream at severitye "sev" if +// "condition" is true. // RTC_LOG_V(sev) Like RTC_LOG(), but sev is a run-time variable of the // LoggingSeverity type (basically, it just doesn't prepend the namespace). // RTC_LOG_F(sev) Like RTC_LOG(), but includes the name of the current function. +// RTC_LOG_IF_F(sev, condition), Like RTC_LOG_IF(), but includes the name of +// the current function. // RTC_LOG_T(sev) Like RTC_LOG(), but includes the this pointer. // RTC_LOG_T_F(sev) Like RTC_LOG_F(), but includes the this pointer. // RTC_LOG_GLE(sev [, mod]) attempt to add a string description of the @@ -647,6 +651,10 @@ class LogMessage { !rtc::LogMessage::IsNoop<::rtc::sev>() && \ RTC_LOG_FILE_LINE(::rtc::sev, __FILE__, __LINE__) +#define RTC_LOG_IF(sev, condition) \ + !rtc::LogMessage::IsNoop<::rtc::sev>() && (condition) && \ + RTC_LOG_FILE_LINE(::rtc::sev, __FILE__, __LINE__) + // The _V version is for when a variable is passed in. #define RTC_LOG_V(sev) \ !rtc::LogMessage::IsNoop(sev) && RTC_LOG_FILE_LINE(sev, __FILE__, __LINE__) @@ -654,10 +662,14 @@ class LogMessage { // The _F version prefixes the message with the current function name. #if (defined(__GNUC__) && !defined(NDEBUG)) || defined(WANT_PRETTY_LOG_F) #define RTC_LOG_F(sev) RTC_LOG(sev) << __PRETTY_FUNCTION__ << ": " +#define RTC_LOG_IF_F(sev, condition) \ + RTC_LOG_IF(sev, condition) << __PRETTY_FUNCTION__ << ": " #define RTC_LOG_T_F(sev) \ RTC_LOG(sev) << this << ": " << __PRETTY_FUNCTION__ << ": " #else #define RTC_LOG_F(sev) RTC_LOG(sev) << __FUNCTION__ << ": " +#define RTC_LOG_IF_F(sev, condition) \ + RTC_LOG_IF(sev, condition) << __FUNCTION__ << ": " #define RTC_LOG_T_F(sev) RTC_LOG(sev) << this << ": " << __FUNCTION__ << ": " #endif @@ -725,16 +737,20 @@ inline const char* AdaptString(const std::string& str) { // they only generate code in debug builds. #if RTC_DLOG_IS_ON #define RTC_DLOG(sev) RTC_LOG(sev) +#define RTC_DLOG_IF(sev, condition) RTC_LOG_IF(sev, condition) #define RTC_DLOG_V(sev) RTC_LOG_V(sev) #define RTC_DLOG_F(sev) RTC_LOG_F(sev) +#define RTC_DLOG_IF_F(sev, condition) RTC_LOG_IF_F(sev, condition) #else #define RTC_DLOG_EAT_STREAM_PARAMS() \ while (false) \ ::rtc::webrtc_logging_impl::LogMessageVoidify() & \ (::rtc::webrtc_logging_impl::LogStreamer<>()) #define RTC_DLOG(sev) RTC_DLOG_EAT_STREAM_PARAMS() +#define RTC_DLOG_IF(sev, condition) RTC_DLOG_EAT_STREAM_PARAMS() #define RTC_DLOG_V(sev) RTC_DLOG_EAT_STREAM_PARAMS() #define RTC_DLOG_F(sev) RTC_DLOG_EAT_STREAM_PARAMS() +#define RTC_DLOG_IF_F(sev, condition) RTC_DLOG_EAT_STREAM_PARAMS() #endif } // namespace rtc diff --git a/rtc_base/logging_unittest.cc b/rtc_base/logging_unittest.cc index 70c1fefaf7..b05907e74a 100644 --- a/rtc_base/logging_unittest.cc +++ b/rtc_base/logging_unittest.cc @@ -144,6 +144,52 @@ TEST(LogTest, SingleStream) { EXPECT_EQ(sev, LogMessage::GetLogToStream(nullptr)); } +TEST(LogTest, LogIfLogIfConditionIsTrue) { + std::string str; + LogSinkImpl stream(&str); + LogMessage::AddLogToStream(&stream, LS_INFO); + + RTC_LOG_IF(LS_INFO, true) << "Hello"; + EXPECT_NE(std::string::npos, str.find("Hello")); + + LogMessage::RemoveLogToStream(&stream); +} + +TEST(LogTest, LogIfDontLogIfConditionIsFalse) { + std::string str; + LogSinkImpl stream(&str); + LogMessage::AddLogToStream(&stream, LS_INFO); + + RTC_LOG_IF(LS_INFO, false) << "Hello"; + EXPECT_EQ(std::string::npos, str.find("Hello")); + + LogMessage::RemoveLogToStream(&stream); +} + +TEST(LogTest, LogIfFLogIfConditionIsTrue) { + std::string str; + LogSinkImpl stream(&str); + LogMessage::AddLogToStream(&stream, LS_INFO); + + RTC_LOG_IF_F(LS_INFO, true) << "Hello"; + EXPECT_NE(std::string::npos, str.find(__FUNCTION__)); + EXPECT_NE(std::string::npos, str.find("Hello")); + + LogMessage::RemoveLogToStream(&stream); +} + +TEST(LogTest, LogIfFDontLogIfConditionIsFalse) { + std::string str; + LogSinkImpl stream(&str); + LogMessage::AddLogToStream(&stream, LS_INFO); + + RTC_LOG_IF_F(LS_INFO, false) << "Not"; + EXPECT_EQ(std::string::npos, str.find(__FUNCTION__)); + EXPECT_EQ(std::string::npos, str.find("Not")); + + LogMessage::RemoveLogToStream(&stream); +} + // Test using multiple log streams. The INFO stream should get the INFO message, // the VERBOSE stream should get the INFO and the VERBOSE. // We should restore the correct global state at the end.