123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- * Copyright 2017-present Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <folly/logging/LogStreamProcessor.h>
- #include <folly/logging/LogStream.h>
- #include <folly/logging/xlog.h>
- namespace folly {
- LogStreamProcessor::LogStreamProcessor(
- const LogCategory* category,
- LogLevel level,
- folly::StringPiece filename,
- unsigned int lineNumber,
- folly::StringPiece functionName,
- AppendType) noexcept
- : LogStreamProcessor(
- category,
- level,
- filename,
- lineNumber,
- functionName,
- INTERNAL,
- std::string()) {}
- LogStreamProcessor::LogStreamProcessor(
- XlogCategoryInfo<true>* categoryInfo,
- LogLevel level,
- folly::StringPiece categoryName,
- bool isCategoryNameOverridden,
- folly::StringPiece filename,
- unsigned int lineNumber,
- folly::StringPiece functionName,
- AppendType) noexcept
- : LogStreamProcessor(
- categoryInfo,
- level,
- categoryName,
- isCategoryNameOverridden,
- filename,
- lineNumber,
- functionName,
- INTERNAL,
- std::string()) {}
- LogStreamProcessor::LogStreamProcessor(
- const LogCategory* category,
- 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} {}
- namespace {
- LogCategory* getXlogCategory(
- XlogCategoryInfo<true>* categoryInfo,
- folly::StringPiece categoryName,
- bool isCategoryNameOverridden) {
- if (!categoryInfo->isInitialized()) {
- return categoryInfo->init(categoryName, isCategoryNameOverridden);
- }
- return categoryInfo->getCategory(&xlog_detail::xlogFileScopeInfo);
- }
- } // namespace
- /**
- * Construct a LogStreamProcessor from an XlogCategoryInfo.
- *
- * We intentionally define this in LogStreamProcessor.cpp instead of
- * LogStreamProcessor.h to avoid having it inlined at every XLOG() call site,
- * to reduce the emitted code size.
- */
- LogStreamProcessor::LogStreamProcessor(
- XlogCategoryInfo<true>* categoryInfo,
- LogLevel level,
- folly::StringPiece categoryName,
- bool isCategoryNameOverridden,
- folly::StringPiece filename,
- unsigned int lineNumber,
- folly::StringPiece functionName,
- InternalType,
- std::string&& msg) noexcept
- : category_{getXlogCategory(
- categoryInfo,
- categoryName,
- isCategoryNameOverridden)},
- level_{level},
- filename_{filename},
- lineNumber_{lineNumber},
- functionName_{functionName},
- message_{std::move(msg)},
- stream_{this} {}
- #ifdef __INCLUDE_LEVEL__
- namespace {
- LogCategory* getXlogCategory(XlogFileScopeInfo* fileScopeInfo) {
- // By the time a LogStreamProcessor is created, the XlogFileScopeInfo object
- // should have already been initialized to perform the log level check.
- // Therefore we never need to check if it is initialized here.
- return fileScopeInfo->category;
- }
- } // namespace
- /**
- * Construct a LogStreamProcessor from an XlogFileScopeInfo.
- *
- * We intentionally define this in LogStreamProcessor.cpp instead of
- * LogStreamProcessor.h to avoid having it inlined at every XLOG() call site,
- * to reduce the emitted code size.
- *
- * This is only defined if __INCLUDE_LEVEL__ is available. The
- * XlogFileScopeInfo APIs are only invoked if we can use __INCLUDE_LEVEL__ to
- * tell that an XLOG() statement occurs in a non-header file. For compilers
- * that do not support __INCLUDE_LEVEL__, the category information is always
- * passed in as XlogCategoryInfo<true> rather than as XlogFileScopeInfo.
- */
- LogStreamProcessor::LogStreamProcessor(
- XlogFileScopeInfo* fileScopeInfo,
- 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} {}
- LogStreamProcessor::LogStreamProcessor(
- XlogFileScopeInfo* fileScopeInfo,
- LogLevel level,
- folly::StringPiece filename,
- unsigned int lineNumber,
- folly::StringPiece functionName,
- AppendType) noexcept
- : LogStreamProcessor(
- fileScopeInfo,
- level,
- filename,
- lineNumber,
- functionName,
- INTERNAL,
- std::string()) {}
- #endif
- /*
- * We intentionally define the LogStreamProcessor destructor in
- * LogStreamProcessor.cpp instead of LogStreamProcessor.h to avoid having it
- * emitted inline at every log statement site. This helps reduce the emitted
- * code size for each log statement.
- */
- LogStreamProcessor::~LogStreamProcessor() noexcept {
- // The LogStreamProcessor destructor is responsible for logging the message.
- // Doing this in the destructor avoids an separate function call to log the
- // message being emitted inline at every log statement site.
- logNow();
- }
- void LogStreamProcessor::logNow() noexcept {
- // Note that admitMessage() is not noexcept and theoretically may throw.
- // However, the only exception that should be possible is std::bad_alloc if
- // we fail to allocate memory. We intentionally let our noexcept specifier
- // crash in that case, since the program likely won't be able to continue
- // anyway.
- //
- // Any other error here is unexpected and we also want to fail hard
- // in that situation too.
- category_->admitMessage(LogMessage{category_,
- level_,
- filename_,
- lineNumber_,
- functionName_,
- extractMessageString(stream_)});
- }
- std::string LogStreamProcessor::extractMessageString(
- LogStream& stream) noexcept {
- if (stream.empty()) {
- return std::move(message_);
- }
- if (message_.empty()) {
- return stream.extractString();
- }
- message_.append(stream.extractString());
- return std::move(message_);
- }
- void LogStreamVoidify<true>::operator&(std::ostream& stream) {
- // Non-fatal log messages wait until the LogStreamProcessor destructor to log
- // the message. However for fatal messages we log immediately in the &
- // operator, since it is marked noreturn.
- //
- // This does result in slightly larger emitted code for fatal log messages
- // (since the operator & call cannot be completely omitted). However, fatal
- // log messages should typically be much more rare than non-fatal messages,
- // so the small amount of extra overhead shouldn't be a big deal.
- auto& logStream = static_cast<LogStream&>(stream);
- logStream.getProcessor()->logNow();
- abort();
- }
- void logDisabledHelper(std::true_type) noexcept {
- // This function can only be reached if we had a disabled fatal log message.
- // This should never happen: LogCategory::setLevelLocked() does not allow
- // setting the threshold for a category lower than FATAL (in production
- // builds) or DFATAL (in debug builds).
- abort();
- }
- } // namespace folly
|