void admitMessage(const LogMessage& message) const;
/**
- * Note: setLevelLocked() may only be called while holding the main
- * LoggerDB lock.
+ * Note: setLevelLocked() may only be called while holding the
+ * LoggerDB loggersByName_ lock. It is safe to call this while holding the
+ * loggersByName_ lock in read-mode; holding it exclusively is not required.
*
* This method should only be invoked by LoggerDB.
*/
/**
* Pointers to children and sibling loggers.
- * These pointers should only ever be accessed while holding the main
- * LoggerDB lock. (These are only modified when creating new loggers,
- * which occurs with the main LoggerDB lock held.)
+ * These pointers should only ever be accessed while holding the
+ * LoggerDB::loggersByName_ lock. (These are only modified when creating new
+ * loggers, which occurs with the main LoggerDB lock held.)
*/
LogCategory* firstChild_{nullptr};
LogCategory* nextSibling_{nullptr};
#include <folly/String.h>
#include <folly/experimental/logging/LogCategory.h>
#include <folly/experimental/logging/LogHandler.h>
+#include <folly/experimental/logging/LogHandlerFactory.h>
#include <folly/experimental/logging/LogLevel.h>
#include <folly/experimental/logging/Logger.h>
#include <folly/experimental/logging/RateLimiter.h>
LoggerDB::LoggerDB(TestConstructorArg) : LoggerDB() {}
+LoggerDB::~LoggerDB() {}
+
LogCategory* LoggerDB::getCategory(StringPiece name) {
return getOrCreateCategoryLocked(*loggersByName_.wlock(), name);
}
}
}
+ // Also extract our HandlerFactoryMap and HandlerMap, so we can clear them
+ // later without holding the handlerInfo_ lock.
+ HandlerFactoryMap factories;
+ HandlerMap handlers;
+ {
+ auto handlerInfo = handlerInfo_.wlock();
+ factories.swap(handlerInfo->factories);
+ handlers.swap(handlerInfo->handlers);
+ }
+
+ // Remove all of the LogHandlers from all log categories,
+ // to drop any shared_ptr references to the LogHandlers
for (auto* category : categories) {
category->clearHandlers();
}
return handlers.size();
}
+void LoggerDB::registerHandlerFactory(
+ std::unique_ptr<LogHandlerFactory> factory,
+ bool replaceExisting) {
+ auto type = factory->getType();
+ auto handlerInfo = handlerInfo_.wlock();
+ if (replaceExisting) {
+ handlerInfo->factories[type.str()] = std::move(factory);
+ } else {
+ auto ret = handlerInfo->factories.emplace(type.str(), std::move(factory));
+ if (!ret.second) {
+ throw std::range_error(to<std::string>(
+ "a LogHandlerFactory for the type \"", type, "\" already exists"));
+ }
+ }
+}
+
+void LoggerDB::unregisterHandlerFactory(StringPiece type) {
+ auto handlerInfo = handlerInfo_.wlock();
+ auto numRemoved = handlerInfo->factories.erase(type.str());
+ if (numRemoved != 1) {
+ throw std::range_error(
+ to<std::string>("no LogHandlerFactory for type \"", type, "\" found"));
+ }
+}
+
LogLevel LoggerDB::xlogInit(
StringPiece categoryName,
std::atomic<LogLevel>* xlogCategoryLevel,
namespace folly {
class LogCategory;
+class LogHandler;
+class LogHandlerFactory;
enum class LogLevel : uint32_t;
/**
*/
static LoggerDB* get();
+ ~LoggerDB();
+
/**
* Get the LogCategory for the specified name.
*
*/
size_t flushAllHandlers();
+ /**
+ * Register a LogHandlerFactory.
+ *
+ * The LogHandlerFactory will be used to create LogHandler objects from a
+ * LogConfig object during updateConfig() and resetConfig() calls.
+ *
+ * Only one factory can be registered for a given handler type name.
+ * LogHandlerFactory::getType() returns the handler type supported by this
+ * LogHandlerFactory.
+ *
+ * If an existing LogHandlerFactory is already registered with this type name
+ * and replaceExisting is false a std::range_error will be thrown.
+ * Otherwise, if replaceExisting is true, the new factory will replace the
+ * existing factory.
+ */
+ void registerHandlerFactory(
+ std::unique_ptr<LogHandlerFactory> factory,
+ bool replaceExisting = false);
+
+ /**
+ * Remove a registered LogHandlerFactory.
+ *
+ * The type parameter should be the name of the handler type, as returned by
+ * LogHandlerFactory::getType().
+ *
+ * Throws std::range_error if no handler factory with this type name exists.
+ */
+ void unregisterHandlerFactory(folly::StringPiece type);
+
/**
* Initialize the LogCategory* and std::atomic<LogLevel> used by an XLOG()
* statement.
LogName::Hash,
LogName::Equals>;
+ using HandlerFactoryMap =
+ std::unordered_map<std::string, std::unique_ptr<LogHandlerFactory>>;
+ using HandlerMap = std::unordered_map<std::string, std::weak_ptr<LogHandler>>;
+ struct HandlerInfo {
+ HandlerFactoryMap factories;
+ HandlerMap handlers;
+ };
+
// Forbidden copy constructor and assignment operator
LoggerDB(LoggerDB const&) = delete;
LoggerDB& operator=(LoggerDB const&) = delete;
*/
folly::Synchronized<LoggerNameMap> loggersByName_;
+ /**
+ * The LogHandlers and LogHandlerFactories.
+ */
+ folly::Synchronized<HandlerInfo> handlerInfo_;
+
static std::atomic<InternalWarningHandler> warningHandler_;
};
} // namespace folly