#include <folly/experimental/logging/LogCategory.h>
#include <cstdio>
+#include <cstdlib>
#include <folly/ExceptionString.h>
+#include <folly/FileUtil.h>
#include <folly/experimental/logging/LogHandler.h>
#include <folly/experimental/logging/LogMessage.h>
#include <folly/experimental/logging/LogName.h>
parent_->firstChild_ = this;
}
+void LogCategory::admitMessage(const LogMessage& message) const {
+ processMessage(message);
+
+ // If this is a fatal message, flush the handlers to make sure the log
+ // message was written out, then crash.
+ if (isLogLevelFatal(message.getLevel())) {
+ auto numHandlers = db_->flushAllHandlers();
+ if (numHandlers == 0) {
+ // No log handlers were configured.
+ // Print the message to stderr, to make sure we always print the reason
+ // we are crashing somewhere.
+ auto msg = folly::to<std::string>(
+ "FATAL:",
+ message.getFileName(),
+ ":",
+ message.getLineNumber(),
+ ": ",
+ message.getMessage(),
+ "\n");
+ folly::writeFull(STDERR_FILENO, msg.data(), msg.size());
+ }
+ std::abort();
+ }
+}
+
void LogCategory::processMessage(const LogMessage& message) const {
// Make a copy of any attached LogHandlers, so we can release the handlers_
// lock before holding them.
for (size_t n = 0; n < numHandlers; ++n) {
try {
- handlers[n]->log(message, this);
+ handlers[n]->handleMessage(message, this);
} catch (const std::exception& ex) {
- // If a LogHandler throws an exception, complain about this fact on
- // stderr to avoid swallowing the error information completely. We
- // don't propagate the exception up to our caller: most code does not
- // prepare for log statements to throw. We also want to continue
- // trying to log the message to any other handlers attached to ourself
- // or one of our parent categories.
- fprintf(
- stderr,
- "WARNING: log handler for category %s threw an error: %s\n",
- name_.c_str(),
- folly::exceptionStr(ex).c_str());
+ // Use LoggerDB::internalWarning() to report the error, but continue
+ // trying to log the message to any other handlers attached to ourself or
+ // one of our parent categories.
+ LoggerDB::internalWarning(
+ __FILE__,
+ __LINE__,
+ "log handler for category \"",
+ name_,
+ "\" threw an error: ",
+ folly::exceptionStr(ex));
}
}
// LogHandler destructors.
}
+std::vector<std::shared_ptr<LogHandler>> LogCategory::getHandlers() const {
+ return *(handlers_.rlock());
+}
+
void LogCategory::setLevel(LogLevel level, bool inherit) {
// We have to set the level through LoggerDB, since we require holding
// the LoggerDB lock to iterate through our children in case our effective