Commit 980baaf5 authored by Harsh Poddar's avatar Harsh Poddar Committed by Facebook Github Bot

Add function name property to LogMessage

Summary: This update adds the name of the function which called the LOG() to the `LogMessage` object so that a custom formatter could use it to show method name with logs.

Reviewed By: simpkins

Differential Revision: D9071926

fbshipit-source-id: 9d5359d84cf2544371c6f1826f99d8b47a272dd1
parent daf5e5df
......@@ -26,6 +26,7 @@ LogMessage::LogMessage(
LogLevel level,
StringPiece filename,
unsigned int lineNumber,
StringPiece functionName,
std::string&& msg)
: category_{category},
level_{level},
......@@ -33,6 +34,7 @@ LogMessage::LogMessage(
timestamp_{system_clock::now()},
filename_{filename},
lineNumber_{lineNumber},
functionName_{functionName},
rawMessage_{std::move(msg)} {
sanitizeMessage();
}
......@@ -43,6 +45,7 @@ LogMessage::LogMessage(
system_clock::time_point timestamp,
StringPiece filename,
unsigned int lineNumber,
StringPiece functionName,
std::string&& msg)
: category_{category},
level_{level},
......@@ -50,6 +53,7 @@ LogMessage::LogMessage(
timestamp_{timestamp},
filename_{filename},
lineNumber_{lineNumber},
functionName_{functionName},
rawMessage_{std::move(msg)} {
sanitizeMessage();
}
......
......@@ -42,14 +42,22 @@ class LogMessage {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
std::string&& msg);
LogMessage(
const LogCategory* category,
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
folly::StringPiece msg)
: LogMessage(category, level, filename, lineNumber, msg.str()) {}
: LogMessage(
category,
level,
filename,
lineNumber,
functionName,
msg.str()) {}
/**
* Construct a LogMessage with an explicit timestamp.
......@@ -62,6 +70,7 @@ class LogMessage {
std::chrono::system_clock::time_point timestamp,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
std::string&& msg);
const LogCategory* getCategory() const {
......@@ -81,6 +90,10 @@ class LogMessage {
return lineNumber_;
}
folly::StringPiece getFunctionName() const {
return functionName_;
}
std::chrono::system_clock::time_point getTimestamp() const {
return timestamp_;
}
......@@ -123,6 +136,11 @@ class LogMessage {
*/
unsigned int const lineNumber_{0};
/**
* The name of the function that generated this log message.
*/
folly::StringPiece const functionName_;
/**
* containsNewlines_ will be true if the message contains internal newlines.
*
......
......@@ -25,12 +25,14 @@ LogStreamProcessor::LogStreamProcessor(
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept
: LogStreamProcessor(
category,
level,
filename,
lineNumber,
functionName,
INTERNAL,
std::string()) {}
......@@ -41,6 +43,7 @@ LogStreamProcessor::LogStreamProcessor(
bool isCategoryNameOverridden,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept
: LogStreamProcessor(
categoryInfo,
......@@ -49,6 +52,7 @@ LogStreamProcessor::LogStreamProcessor(
isCategoryNameOverridden,
filename,
lineNumber,
functionName,
INTERNAL,
std::string()) {}
......@@ -57,12 +61,14 @@ LogStreamProcessor::LogStreamProcessor(
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
InternalType,
std::string&& msg) noexcept
: category_{category},
level_{level},
filename_{filename},
lineNumber_{lineNumber},
functionName_{functionName},
message_{std::move(msg)},
stream_{this} {}
......@@ -92,6 +98,7 @@ LogStreamProcessor::LogStreamProcessor(
bool isCategoryNameOverridden,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
InternalType,
std::string&& msg) noexcept
: category_{getXlogCategory(
......@@ -101,6 +108,7 @@ LogStreamProcessor::LogStreamProcessor(
level_{level},
filename_{filename},
lineNumber_{lineNumber},
functionName_{functionName},
message_{std::move(msg)},
stream_{this} {}
......@@ -132,12 +140,14 @@ LogStreamProcessor::LogStreamProcessor(
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
InternalType,
std::string&& msg) noexcept
: category_{getXlogCategory(fileScopeInfo)},
level_{level},
filename_{filename},
lineNumber_{lineNumber},
functionName_{functionName},
message_{std::move(msg)},
stream_{this} {}
......@@ -146,12 +156,14 @@ LogStreamProcessor::LogStreamProcessor(
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept
: LogStreamProcessor(
fileScopeInfo,
level,
filename,
lineNumber,
functionName,
INTERNAL,
std::string()) {}
#endif
......@@ -182,6 +194,7 @@ void LogStreamProcessor::logNow() noexcept {
level_,
filename_,
lineNumber_,
functionName_,
extractMessageString(stream_)});
}
......
......@@ -105,6 +105,7 @@ class LogStreamProcessor {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept;
/**
......@@ -122,6 +123,7 @@ class LogStreamProcessor {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType,
Args&&... args) noexcept
: LogStreamProcessor(
......@@ -129,6 +131,7 @@ class LogStreamProcessor {
level,
filename,
lineNumber,
functionName,
INTERNAL,
createLogString(std::forward<Args>(args)...)) {}
......@@ -147,6 +150,7 @@ class LogStreamProcessor {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
FormatType,
folly::StringPiece fmt,
Args&&... args) noexcept
......@@ -155,6 +159,7 @@ class LogStreamProcessor {
level,
filename,
lineNumber,
functionName,
INTERNAL,
formatLogString(fmt, std::forward<Args>(args)...)) {}
......@@ -174,6 +179,7 @@ class LogStreamProcessor {
bool isCategoryNameOverridden,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept;
template <typename... Args>
LogStreamProcessor(
......@@ -183,6 +189,7 @@ class LogStreamProcessor {
bool isCategoryNameOverridden,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType,
Args&&... args) noexcept
: LogStreamProcessor(
......@@ -192,6 +199,7 @@ class LogStreamProcessor {
isCategoryNameOverridden,
filename,
lineNumber,
functionName,
INTERNAL,
createLogString(std::forward<Args>(args)...)) {}
template <typename... Args>
......@@ -202,6 +210,7 @@ class LogStreamProcessor {
bool isCategoryNameOverridden,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
FormatType,
folly::StringPiece fmt,
Args&&... args) noexcept
......@@ -212,6 +221,7 @@ class LogStreamProcessor {
isCategoryNameOverridden,
filename,
lineNumber,
functionName,
INTERNAL,
formatLogString(fmt, std::forward<Args>(args)...)) {}
......@@ -231,6 +241,7 @@ class LogStreamProcessor {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept;
LogStreamProcessor(
XlogFileScopeInfo* fileScopeInfo,
......@@ -239,9 +250,15 @@ class LogStreamProcessor {
bool /* isCategoryNameOverridden */,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType) noexcept
: LogStreamProcessor(fileScopeInfo, level, filename, lineNumber, APPEND) {
}
: LogStreamProcessor(
fileScopeInfo,
level,
filename,
lineNumber,
functionName,
APPEND) {}
template <typename... Args>
LogStreamProcessor(
XlogFileScopeInfo* fileScopeInfo,
......@@ -250,6 +267,7 @@ class LogStreamProcessor {
bool /* isCategoryNameOverridden */,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
AppendType,
Args&&... args) noexcept
: LogStreamProcessor(
......@@ -257,6 +275,7 @@ class LogStreamProcessor {
level,
filename,
lineNumber,
functionName,
INTERNAL,
createLogString(std::forward<Args>(args)...)) {}
template <typename... Args>
......@@ -267,6 +286,7 @@ class LogStreamProcessor {
bool /* isCategoryNameOverridden */,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
FormatType,
folly::StringPiece fmt,
Args&&... args) noexcept
......@@ -275,6 +295,7 @@ class LogStreamProcessor {
level,
filename,
lineNumber,
functionName,
INTERNAL,
formatLogString(fmt, std::forward<Args>(args)...)) {}
#endif
......@@ -308,6 +329,7 @@ class LogStreamProcessor {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
InternalType,
std::string&& msg) noexcept;
LogStreamProcessor(
......@@ -317,6 +339,7 @@ class LogStreamProcessor {
bool isCategoryNameOverridden,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
InternalType,
std::string&& msg) noexcept;
LogStreamProcessor(
......@@ -324,6 +347,7 @@ class LogStreamProcessor {
LogLevel level,
folly::StringPiece filename,
unsigned int lineNumber,
folly::StringPiece functionName,
InternalType,
std::string&& msg) noexcept;
......@@ -411,6 +435,7 @@ class LogStreamProcessor {
LogLevel const level_;
folly::StringPiece filename_;
unsigned int lineNumber_;
folly::StringPiece functionName_;
std::string message_;
LogStream stream_;
};
......
......@@ -72,28 +72,31 @@
* LogLevel variable. (This differs from FB_LOG() and FB_LOGF() which accept
* an unqualified LogLevel name.)
*/
#define FB_LOG_RAW(logger, level, filename, linenumber, ...) \
FB_LOG_RAW_IMPL( \
logger, \
level, \
filename, \
linenumber, \
::folly::LogStreamProcessor::APPEND, \
#define FB_LOG_RAW(logger, level, filename, linenumber, functionName, ...) \
FB_LOG_RAW_IMPL( \
logger, \
level, \
filename, \
linenumber, \
functionName, \
::folly::LogStreamProcessor::APPEND, \
##__VA_ARGS__)
/**
* FB_LOGF_RAW() is similar to FB_LOG_RAW(), but formats the log arguments
* using folly::format().
*/
#define FB_LOGF_RAW(logger, level, filename, linenumber, fmt, arg1, ...) \
FB_LOG_RAW_IMPL( \
logger, \
level, \
filename, \
linenumber, \
::folly::LogStreamProcessor::FORMAT, \
fmt, \
arg1, \
#define FB_LOGF_RAW( \
logger, level, filename, linenumber, functionName, fmt, arg1, ...) \
FB_LOG_RAW_IMPL( \
logger, \
level, \
filename, \
linenumber, \
functionName, \
::folly::LogStreamProcessor::FORMAT, \
fmt, \
arg1, \
##__VA_ARGS__)
/**
......@@ -110,6 +113,7 @@
(level), \
__FILE__, \
__LINE__, \
__func__, \
(type), \
##__VA_ARGS__} \
.stream()
......@@ -123,16 +127,18 @@
* instead of a compile-time constant, we cannot detect at compile time if this
* is a fatal log message or not.
*/
#define FB_LOG_RAW_IMPL(logger, level, filename, line, type, ...) \
(!(logger).getCategory()->logCheck(level)) \
? static_cast<void>(0) \
: ::folly::LogStreamVoidify<false>{} & \
::folly::LogStreamProcessor{(logger).getCategory(), \
(level), \
(filename), \
(line), \
(type), \
##__VA_ARGS__} \
#define FB_LOG_RAW_IMPL( \
logger, level, filename, line, functionName, type, ...) \
(!(logger).getCategory()->logCheck(level)) \
? static_cast<void>(0) \
: ::folly::LogStreamVoidify<false>{} & \
::folly::LogStreamProcessor{(logger).getCategory(), \
(level), \
(filename), \
(line), \
(functionName), \
(type), \
##__VA_ARGS__} \
.stream()
namespace folly {
......
......@@ -41,6 +41,7 @@ std::string formatMsg(
StringPiece msg,
StringPiece filename,
unsigned int lineNumber,
StringPiece functionName,
// Default timestamp: 2017-04-17 13:45:56.123456 UTC
uint64_t timestampNS = 1492436756123456789ULL) {
LoggerDB db{LoggerDB::TESTING};
......@@ -50,8 +51,13 @@ std::string formatMsg(
std::chrono::system_clock::time_point logTimePoint{
std::chrono::duration_cast<std::chrono::system_clock::duration>(
std::chrono::nanoseconds{timestampNS})};
LogMessage logMessage{
category, level, logTimePoint, filename, lineNumber, msg.str()};
LogMessage logMessage{category,
level,
logTimePoint,
filename,
lineNumber,
functionName,
msg.str()};
return formatter.formatMessage(logMessage, category);
}
......@@ -64,7 +70,9 @@ TEST(GlogFormatter, log) {
auto expected = folly::sformat(
"W0417 13:45:56.123456 {:5d} myfile.cpp:1234] hello world\n", tid);
EXPECT_EQ(
expected, formatMsg(LogLevel::WARN, "hello world", "myfile.cpp", 1234));
expected,
formatMsg(
LogLevel::WARN, "hello world", "myfile.cpp", 1234, "testFunction"));
}
TEST(GlogFormatter, filename) {
......@@ -79,7 +87,8 @@ TEST(GlogFormatter, filename) {
LogLevel::WARN,
"hello world",
"src/test/logging/code/myfile.cpp",
1234));
1234,
"testFunction"));
// Log a message with a very long file name.
expected = folly::sformat(
......@@ -94,7 +103,8 @@ TEST(GlogFormatter, filename) {
"oh noes",
"this_is_a_really_long_file_name_that_will_probably_exceed_"
"our_buffer_allocation_guess.cpp",
123456789));
123456789,
"testFunction"));
}
TEST(GlogFormatter, multiline) {
......@@ -126,7 +136,8 @@ TEST(GlogFormatter, multiline) {
"\n"
"=============",
"src/rodent.cpp",
777));
777,
"testFunction"));
}
TEST(GlogFormatter, singleNewline) {
......@@ -139,7 +150,9 @@ TEST(GlogFormatter, singleNewline) {
"V0417 13:45:56.123456 {tid:>5s} foo.txt:123] \n"
"V0417 13:45:56.123456 {tid:>5s} foo.txt:123] \n",
formatMap);
EXPECT_EQ(expected, formatMsg(LogLevel::DBG9, "\n", "foo.txt", 123));
EXPECT_EQ(
expected,
formatMsg(LogLevel::DBG9, "\n", "foo.txt", 123, "testFunction"));
}
TEST(GlogFormatter, unprintableChars) {
......@@ -151,17 +164,28 @@ TEST(GlogFormatter, unprintableChars) {
tid);
EXPECT_EQ(
expected,
formatMsg(LogLevel::ERR, "foo\abar\x1btest", "escapes.cpp", 97));
formatMsg(
LogLevel::ERR,
"foo\abar\x1btest",
"escapes.cpp",
97,
"testFunction"));
expected = folly::sformat(
"I0417 13:45:56.123456 {:5d} escapes.cpp:98] foo\\\\bar\"test\n", tid);
EXPECT_EQ(
expected, formatMsg(LogLevel::INFO, "foo\\bar\"test", "escapes.cpp", 98));
expected,
formatMsg(
LogLevel::INFO, "foo\\bar\"test", "escapes.cpp", 98, "testFunction"));
expected = folly::sformat(
"C0417 13:45:56.123456 {:5d} escapes.cpp:99] nul\\x00byte\n", tid);
EXPECT_EQ(
expected,
formatMsg(
LogLevel::CRITICAL, std::string("nul\0byte", 8), "escapes.cpp", 99));
LogLevel::CRITICAL,
std::string("nul\0byte", 8),
"escapes.cpp",
99,
"testFunction"));
}
int main(int argc, char* argv[]) {
......
......@@ -26,8 +26,12 @@ using namespace folly;
{ \
SCOPED_TRACE( \
"input string: \"" + folly::backslashify<std::string>(value) + "\""); \
LogMessage checkMsg{ \
category, LogLevel::ERR, __FILE__, __LINE__, std::string{value}}; \
LogMessage checkMsg{category, \
LogLevel::ERR, \
__FILE__, \
__LINE__, \
__func__, \
std::string{value}}; \
EXPECT_EQ(expected, checkMsg.getMessage()); \
EXPECT_EQ(static_cast<int>(hasNewlines), checkMsg.containsNewlines()); \
EXPECT_EQ(__FILE__, checkMsg.getFileName()); \
......
......@@ -357,7 +357,15 @@ TEST_F(LoggerTest, logRawMacros) {
auto& messages = handler_->getMessages();
FB_LOG_RAW(foobar, LogLevel::DBG1, "src/some/file.c", 1234, "hello", ' ', 1)
FB_LOG_RAW(
foobar,
LogLevel::DBG1,
"src/some/file.c",
1234,
"testFunction",
"hello",
' ',
1)
<< " world";
ASSERT_EQ(1, messages.size());
EXPECT_EQ("hello 1 world", messages[0].first.getMessage());
......@@ -367,7 +375,15 @@ TEST_F(LoggerTest, logRawMacros) {
messages.clear();
auto level = LogLevel::DBG1;
FB_LOGF_RAW(foobar, level, "test/mytest.c", 99, "{}: num={}", "test", 42)
FB_LOGF_RAW(
foobar,
level,
"test/mytest.c",
99,
"testFunction",
"{}: num={}",
"test",
42)
<< " plus extra stuff";
ASSERT_EQ(1, messages.size());
EXPECT_EQ("test: num=42 plus extra stuff", messages[0].first.getMessage());
......
......@@ -82,6 +82,7 @@ TEST(StandardLogHandler, simple) {
LogLevel::DBG8,
"src/test.cpp",
1234,
"testMethod",
std::string{"hello world"}};
handler.handleMessage(msg, handlerCategory);
ASSERT_EQ(1, writer->getMessages().size());
......@@ -100,7 +101,8 @@ TEST(StandardLogHandler, levelCheck) {
auto handlerCategory = db.getCategory("handler_cat");
auto logMsg = [&](LogLevel level, folly::StringPiece message) {
LogMessage msg{logCategory, level, "src/test.cpp", 1234, message};
LogMessage msg{
logCategory, level, "src/test.cpp", 1234, "testMethod", message};
handler.handleMessage(msg, handlerCategory);
};
......
......@@ -228,6 +228,7 @@
xlog_detail::isXlogCategoryOverridden(0), \
XLOG_FILENAME, \
__LINE__, \
__func__, \
(type), \
##__VA_ARGS__) \
.stream()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment