proxygen
LogMessage.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
17 
18 #include <folly/system/ThreadId.h>
19 
20 using std::chrono::system_clock;
21 
22 namespace folly {
23 
25  const LogCategory* category,
26  LogLevel level,
27  StringPiece filename,
28  unsigned int lineNumber,
29  StringPiece functionName,
30  std::string&& msg)
31  : category_{category},
32  level_{level},
35  filename_{filename},
36  lineNumber_{lineNumber},
37  functionName_{functionName},
38  rawMessage_{std::move(msg)} {
40 }
41 
43  const LogCategory* category,
44  LogLevel level,
45  system_clock::time_point timestamp,
46  StringPiece filename,
47  unsigned int lineNumber,
48  StringPiece functionName,
49  std::string&& msg)
50  : category_{category},
51  level_{level},
53  timestamp_{timestamp},
54  filename_{filename},
55  lineNumber_{lineNumber},
56  functionName_{functionName},
57  rawMessage_{std::move(msg)} {
59 }
60 
62 #if _WIN32
63  // Windows allows either backwards or forwards slash as path separator
64  auto idx1 = filename_.rfind('\\');
65  auto idx2 = filename_.rfind('/');
67  if (idx1 == StringPiece::npos) {
68  idx = idx2;
69  } else if (idx2 == StringPiece::npos) {
70  idx = idx1;
71  } else {
72  idx = std::max(idx1, idx2);
73  }
74 #else
75  auto idx = filename_.rfind('/');
76 #endif
77  if (idx == StringPiece::npos) {
78  return filename_;
79  }
80  return filename_.subpiece(idx + 1);
81 }
82 
84  // Compute how long the sanitized string will be.
85  size_t sanitizedLength = 0;
86  for (const char c : rawMessage_) {
87  if (c == '\\') {
88  // Backslashes are escaped as two backslashes
89  sanitizedLength += 2;
90  } else if (static_cast<unsigned char>(c) < 0x20) {
91  // Newlines and tabs are emitted directly with no escaping.
92  // All other control characters are emitted as \xNN (4 characters)
93  if (c == '\n') {
94  sanitizedLength += 1;
95  containsNewlines_ = true;
96  } else if (c == '\t') {
97  sanitizedLength += 1;
98  } else {
99  sanitizedLength += 4;
100  }
101  } else if (c == 0x7f) {
102  // Bytes above the ASCII range are emitted as \xNN (4 characters)
103  sanitizedLength += 4;
104  } else {
105  // This character will be emitted as-is, with no escaping.
106  ++sanitizedLength;
107  }
108  }
109 
110  // If nothing is different, just use rawMessage_ directly,
111  // and don't populate message_.
112  if (sanitizedLength == rawMessage_.size()) {
113  return;
114  }
115 
116  message_.reserve(sanitizedLength);
117  for (const char c : rawMessage_) {
118  if (c == '\\') {
119  message_.push_back('\\');
120  message_.push_back('\\');
121  } else if (static_cast<unsigned char>(c) < 0x20) {
122  if (c == '\n' || c == '\t') {
123  message_.push_back(c);
124  } else {
125  static constexpr StringPiece hexdigits{"0123456789abcdef"};
126  std::array<char, 4> data{
127  {'\\', 'x', hexdigits[(c >> 4) & 0xf], hexdigits[c & 0xf]}};
128  message_.append(data.data(), data.size());
129  }
130  } else if (c == 0x7f) {
131  constexpr std::array<char, 4> data{{'\\', 'x', '7', 'f'}};
132  message_.append(data.data(), data.size());
133  } else {
134  message_.push_back(c);
135  }
136  }
137 }
138 } // namespace folly
LogLevel max
Definition: LogLevel.cpp:31
LogLevel const level_
Definition: LogMessage.h:125
unsigned int const lineNumber_
Definition: LogMessage.h:137
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::chrono::steady_clock::time_point now()
std::string const rawMessage_
Definition: LogMessage.h:158
folly::StringPiece const filename_
Definition: LogMessage.h:132
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
uint64_t getOSThreadID()
Definition: ThreadId.h:80
const LogCategory *const category_
Definition: LogMessage.h:124
void sanitizeMessage()
Definition: LogMessage.cpp:83
size_type rfind(value_type c) const
Definition: Range.h:761
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
Range subpiece(size_type first, size_type length=npos) const
Definition: Range.h:686
std::chrono::system_clock::time_point const timestamp_
Definition: LogMessage.h:127
std::string message_
Definition: LogMessage.h:168
LogLevel
Definition: LogLevel.h:38
static const size_type npos
Definition: Range.h:197
const char * string
Definition: Conv.cpp:212
LogMessage(const LogCategory *category, LogLevel level, folly::StringPiece filename, unsigned int lineNumber, folly::StringPiece functionName, std::string &&msg)
Definition: LogMessage.cpp:24
folly::StringPiece getFileBaseName() const
Definition: LogMessage.cpp:61
folly::StringPiece const functionName_
Definition: LogMessage.h:142
uint64_t const threadID_
Definition: LogMessage.h:126
char c