proxygen
LogStreamProcessor.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 
19 #include <folly/logging/xlog.h>
20 
21 namespace folly {
22 
24  const LogCategory* category,
25  LogLevel level,
26  folly::StringPiece filename,
27  unsigned int lineNumber,
28  folly::StringPiece functionName,
31  category,
32  level,
33  filename,
34  lineNumber,
35  functionName,
36  INTERNAL,
37  std::string()) {}
38 
40  XlogCategoryInfo<true>* categoryInfo,
41  LogLevel level,
42  folly::StringPiece categoryName,
43  bool isCategoryNameOverridden,
44  folly::StringPiece filename,
45  unsigned int lineNumber,
46  folly::StringPiece functionName,
49  categoryInfo,
50  level,
51  categoryName,
52  isCategoryNameOverridden,
53  filename,
54  lineNumber,
55  functionName,
56  INTERNAL,
57  std::string()) {}
58 
60  const LogCategory* category,
61  LogLevel level,
62  folly::StringPiece filename,
63  unsigned int lineNumber,
64  folly::StringPiece functionName,
66  std::string&& msg) noexcept
67  : category_{category},
68  level_{level},
69  filename_{filename},
70  lineNumber_{lineNumber},
71  functionName_{functionName},
72  message_{std::move(msg)},
73  stream_{this} {}
74 
75 namespace {
76 LogCategory* getXlogCategory(
77  XlogCategoryInfo<true>* categoryInfo,
78  folly::StringPiece categoryName,
79  bool isCategoryNameOverridden) {
80  if (!categoryInfo->isInitialized()) {
81  return categoryInfo->init(categoryName, isCategoryNameOverridden);
82  }
83  return categoryInfo->getCategory(&xlog_detail::xlogFileScopeInfo);
84 }
85 } // namespace
86 
95  XlogCategoryInfo<true>* categoryInfo,
96  LogLevel level,
97  folly::StringPiece categoryName,
98  bool isCategoryNameOverridden,
99  folly::StringPiece filename,
100  unsigned int lineNumber,
101  folly::StringPiece functionName,
102  InternalType,
103  std::string&& msg) noexcept
104  : category_{getXlogCategory(
105  categoryInfo,
106  categoryName,
107  isCategoryNameOverridden)},
108  level_{level},
109  filename_{filename},
110  lineNumber_{lineNumber},
111  functionName_{functionName},
112  message_{std::move(msg)},
113  stream_{this} {}
114 
115 #ifdef __INCLUDE_LEVEL__
116 namespace {
117 LogCategory* getXlogCategory(XlogFileScopeInfo* fileScopeInfo) {
118  // By the time a LogStreamProcessor is created, the XlogFileScopeInfo object
119  // should have already been initialized to perform the log level check.
120  // Therefore we never need to check if it is initialized here.
121  return fileScopeInfo->category;
122 }
123 } // namespace
124 
139  XlogFileScopeInfo* fileScopeInfo,
140  LogLevel level,
141  folly::StringPiece filename,
142  unsigned int lineNumber,
143  folly::StringPiece functionName,
144  InternalType,
145  std::string&& msg) noexcept
146  : category_{getXlogCategory(fileScopeInfo)},
147  level_{level},
148  filename_{filename},
149  lineNumber_{lineNumber},
150  functionName_{functionName},
151  message_{std::move(msg)},
152  stream_{this} {}
153 
155  XlogFileScopeInfo* fileScopeInfo,
156  LogLevel level,
157  folly::StringPiece filename,
158  unsigned int lineNumber,
159  folly::StringPiece functionName,
162  fileScopeInfo,
163  level,
164  filename,
165  lineNumber,
166  functionName,
167  INTERNAL,
168  std::string()) {}
169 #endif
170 
171 /*
172  * We intentionally define the LogStreamProcessor destructor in
173  * LogStreamProcessor.cpp instead of LogStreamProcessor.h to avoid having it
174  * emitted inline at every log statement site. This helps reduce the emitted
175  * code size for each log statement.
176  */
178  // The LogStreamProcessor destructor is responsible for logging the message.
179  // Doing this in the destructor avoids an separate function call to log the
180  // message being emitted inline at every log statement site.
181  logNow();
182 }
183 
185  // Note that admitMessage() is not noexcept and theoretically may throw.
186  // However, the only exception that should be possible is std::bad_alloc if
187  // we fail to allocate memory. We intentionally let our noexcept specifier
188  // crash in that case, since the program likely won't be able to continue
189  // anyway.
190  //
191  // Any other error here is unexpected and we also want to fail hard
192  // in that situation too.
194  level_,
195  filename_,
196  lineNumber_,
199 }
200 
203  if (stream.empty()) {
204  return std::move(message_);
205  }
206 
207  if (message_.empty()) {
208  return stream.extractString();
209  }
210  message_.append(stream.extractString());
211  return std::move(message_);
212 }
213 
215  // Non-fatal log messages wait until the LogStreamProcessor destructor to log
216  // the message. However for fatal messages we log immediately in the &
217  // operator, since it is marked noreturn.
218  //
219  // This does result in slightly larger emitted code for fatal log messages
220  // (since the operator & call cannot be completely omitted). However, fatal
221  // log messages should typically be much more rare than non-fatal messages,
222  // so the small amount of extra overhead shouldn't be a big deal.
223  auto& logStream = static_cast<LogStream&>(stream);
224  logStream.getProcessor()->logNow();
225  abort();
226 }
227 
229  // This function can only be reached if we had a disabled fatal log message.
230  // This should never happen: LogCategory::setLevelLocked() does not allow
231  // setting the threshold for a category lower than FATAL (in production
232  // builds) or DFATAL (in debug builds).
233  abort();
234 }
235 } // namespace folly
folly::StringPiece filename_
std::ostream & stream() noexcept
void logDisabledHelper(std::true_type) noexcept
void operator&(std::ostream &) noexcept
const LogCategory *const category_
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
LogCategory * init(folly::StringPiece categoryName, bool isOverridden)
Definition: xlog.cpp:86
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
LogStreamProcessor(const LogCategory *category, LogLevel level, folly::StringPiece filename, unsigned int lineNumber, folly::StringPiece functionName, AppendType) noexcept
bool_constant< true > true_type
Definition: gtest-port.h:2210
LogCategory * getCategory(XlogFileScopeInfo *)
Definition: xlog.h:427
std::string extractMessageString(LogStream &stream) noexcept
LogLevel
Definition: LogLevel.h:38
LogStreamProcessor * getProcessor() const
Definition: LogStream.h:78
const char * string
Definition: Conv.cpp:212
bool isInitialized() const
Definition: xlog.h:421
folly::StringPiece functionName_
void admitMessage(const LogMessage &message) const
Definition: LogCategory.cpp:49