proxygen
folly::GlogStyleFormatter Class Reference

#include <GlogStyleFormatter.h>

Inheritance diagram for folly::GlogStyleFormatter:
folly::LogFormatter

Public Member Functions

std::string formatMessage (const LogMessage &message, const LogCategory *handlerCategory) override
 
- Public Member Functions inherited from folly::LogFormatter
virtual ~LogFormatter ()
 

Detailed Description

A LogFormatter implementation that produces messages in a format similar to that produced by the Google logging library.

The glog message format is:

LmmDD HH:MM:SS.USECS THREAD [THREADNAME] (THREADCTX) FILE:LINE] MSG

L: A 1-character code describing the log level (e.g., E, W, I, V) mm: 2-digit month DD: 2-digit day HH: 2-digit hour, 24-hour format MM: 2-digit minute SS: 2-digit second USECS: 6-digit microseconds THREAD: Thread ID FILE: Filename (just the last component) LINE: Line number MSG: The actual log message

[THREADNAME] is the thread name, and is only included if –logthreadnames was enabled on the command line.

(THREADCTX) is thread-local log context data, if it has been set. (This is a Facebook-specific modification, and is disabled unless –logthreadcontext was enabled on the command line.)

Exception information and a custom log prefix may also appear after the file name and line number, before the ']' character.

Definition at line 53 of file GlogStyleFormatter.h.

Member Function Documentation

std::string folly::GlogStyleFormatter::formatMessage ( const LogMessage message,
const LogCategory handlerCategory 
)
overridevirtual

Serialze a LogMessage object.

Parameters
messageThe LogMessage object to serialze.
handlerCategoryThe LogCategory that is currently handling this message. Note that this is likely different from the LogCategory where the message was originally logged, which can be accessed as message->getCategory()

Implements folly::LogFormatter.

Definition at line 45 of file GlogStyleFormatter.cpp.

References buffer(), folly::LogMessage::containsNewlines(), folly::test::end(), folly::format(), folly::LogMessage::getFileBaseName(), folly::LogMessage::getLevel(), folly::LogMessage::getLineNumber(), folly::LogMessage::getMessage(), folly::LogMessage::getThreadID(), folly::LogMessage::getTimestamp(), folly::Range< const char * >::npos, and string.

47  {
48  // Get the local time info
49  struct tm ltime;
50  auto timeSinceEpoch = message.getTimestamp().time_since_epoch();
51  auto epochSeconds =
52  std::chrono::duration_cast<std::chrono::seconds>(timeSinceEpoch);
53  std::chrono::microseconds usecs =
54  std::chrono::duration_cast<std::chrono::microseconds>(timeSinceEpoch) -
55  epochSeconds;
56  time_t unixTimestamp = epochSeconds.count();
57  if (!localtime_r(&unixTimestamp, &ltime)) {
58  memset(&ltime, 0, sizeof(ltime));
59  }
60 
61  auto basename = message.getFileBaseName();
62  auto headerFormatter = folly::format(
63  "{}{:02d}{:02d} {:02d}:{:02d}:{:02d}.{:06d} {:5d} {}:{}] ",
64  getGlogLevelName(message.getLevel())[0],
65  ltime.tm_mon + 1,
66  ltime.tm_mday,
67  ltime.tm_hour,
68  ltime.tm_min,
69  ltime.tm_sec,
70  usecs.count(),
71  message.getThreadID(),
72  basename,
73  message.getLineNumber());
74 
75  // TODO: Support including thread names and thread context info.
76 
77  // The fixed portion of the header takes up 31 bytes.
78  //
79  // The variable portions that we can't account for here include the line
80  // number and the thread ID (just in case it is larger than 6 digits long).
81  // Here we guess that 40 bytes will be long enough to include room for this.
82  //
83  // If this still isn't long enough the string will grow as necessary, so the
84  // code will still be correct, but just slightly less efficient than if we
85  // had allocated a large enough buffer the first time around.
86  size_t headerLengthGuess = 40 + basename.size();
87 
88  // Format the data into a buffer.
90  StringPiece msgData{message.getMessage()};
91  if (message.containsNewlines()) {
92  // If there are multiple lines in the log message, add a header
93  // before each one.
94  std::string header;
95  header.reserve(headerLengthGuess);
96  headerFormatter.appendTo(header);
97 
98  // Make a guess at how many lines will be in the message, just to make an
99  // initial buffer allocation. If the guess is too small then the string
100  // will reallocate and grow as necessary, it will just be slightly less
101  // efficient than if we had guessed enough space.
102  size_t numLinesGuess = 4;
103  buffer.reserve(((header.size() + 1) * numLinesGuess) + msgData.size());
104 
105  size_t idx = 0;
106  while (true) {
107  auto end = msgData.find('\n', idx);
108  if (end == StringPiece::npos) {
109  end = msgData.size();
110  }
111 
112  buffer.append(header);
113  auto line = msgData.subpiece(idx, end - idx);
114  buffer.append(line.data(), line.size());
115  buffer.push_back('\n');
116 
117  if (end == msgData.size()) {
118  break;
119  }
120  idx = end + 1;
121  }
122  } else {
123  buffer.reserve(headerLengthGuess + msgData.size());
124  headerFormatter.appendTo(buffer);
125  buffer.append(msgData.data(), msgData.size());
126  buffer.push_back('\n');
127  }
128 
129  return buffer;
130 }
std::vector< uint8_t > buffer(kBufferSize+16)
Definition: test.c:42
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
static const size_type npos
Definition: Range.h:197
const char * string
Definition: Conv.cpp:212
Formatter< false, Args... > format(StringPiece fmt, Args &&...args)
Definition: Format.h:271
Range< const char * > StringPiece

The documentation for this class was generated from the following files: