unioil-loyalty-rn-app/ios/Pods/Flipper-Folly/folly/logging/LogStreamProcessor.cpp

236 lines
7.5 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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