59 auto defaultHandlerConfig =
61 auto rootCategoryConfig =
64 {{
"default", defaultHandlerConfig}},
65 {{
"", rootCategoryConfig}});
72 class LoggerDBSingleton {
79 ~LoggerDBSingleton() {
92 db_->cleanupHandlers();
108 std::unique_ptr<LoggerDB>
db_;
120 auto rootUptr = std::make_unique<LogCategory>(
this);
123 loggersByName_.wlock()->emplace(root->getName(),
std::move(rootUptr));
140 auto it = loggersByName->find(name);
141 if (it == loggersByName->end()) {
144 return it->second.get();
170 std::unordered_map<std::shared_ptr<LogHandler>,
string> handlersToName;
171 for (
const auto& entry : handlerInfo->handlers) {
172 auto handler = entry.second.lock();
176 handlersToName.emplace(
handler, entry.first);
177 handlerConfigs.emplace(entry.first,
handler->getConfig());
180 size_t anonymousNameIndex = 1;
181 auto generateAnonymousHandlerName = [&]() {
185 auto name = to<string>(
"anonymousHandler", anonymousNameIndex);
186 ++anonymousNameIndex;
187 if (handlerInfo->handlers.find(
name) == handlerInfo->handlers.end()) {
196 for (
const auto& entry : *loggersByName) {
197 auto* category = entry.second.get();
198 auto levelInfo = category->getLevelInfo();
199 auto handlers = category->getHandlers();
203 if (!includeAllCategories && handlers.empty() &&
209 std::vector<string> handlerNames;
210 for (
const auto&
handler : handlers) {
211 auto iter = handlersToName.find(
handler);
212 if (iter == handlersToName.end()) {
216 auto name = generateAnonymousHandlerName();
218 handlerConfigs.emplace(
name,
handler->getConfig());
219 handlerNames.emplace_back(
name);
221 handlerNames.emplace_back(iter->second);
226 levelInfo.first, levelInfo.second, handlerNames);
227 categoryConfigs.emplace(category->getName(),
std::move(categoryConfig));
246 for (
const auto& entry : handlerInfo->handlers) {
247 auto handler = entry.second.lock();
256 std::shared_ptr<LogHandler> oldHandler;
257 auto iter = handlers->find(entry.first);
258 if (iter != handlers->end()) {
259 oldHandler = iter->second;
264 if (entry.second.type.hasValue()) {
265 handlerConfig = &entry.second;
269 throw std::invalid_argument(to<std::string>(
270 "cannot update unknown log handler \"", entry.first,
"\""));
273 updatedConfig = oldHandler->getConfig();
278 throw std::invalid_argument(to<std::string>(
279 "existing log handler \"",
281 "\" is missing type information"));
283 updatedConfig.
update(entry.second);
284 handlerConfig = &updatedConfig;
288 auto factoryIter = handlerInfo->factories.find(handlerConfig->
type.
value());
289 if (factoryIter == handlerInfo->factories.end()) {
290 throw std::invalid_argument(to<std::string>(
291 "unknown log handler type \"", handlerConfig->
type.
value(),
"\""));
295 const auto& factory = factoryIter->second;
296 std::shared_ptr<LogHandler>
handler;
299 handler = factory->updateHandler(oldHandler, handlerConfig->
options);
300 if (handler != oldHandler) {
301 oldToNewHandlerMap->emplace(oldHandler, handler);
304 handler = factory->createHandler(handlerConfig->
options);
306 }
catch (
const std::exception& ex) {
311 throw std::invalid_argument(to<string>(
313 oldHandler ?
"updating" :
"creating",
319 handlerInfo->handlers[entry.first] =
handler;
320 (*handlers)[entry.first] =
handler;
326 if (!entry.second.handlers.hasValue()) {
329 for (
const auto& handlerName : entry.second.handlers.value()) {
330 auto iter = handlers->find(handlerName);
331 if (iter == handlers->end()) {
332 throw std::invalid_argument(to<std::string>(
333 "unknown log handler \"",
335 "\" configured for log category \"",
353 std::unordered_map<std::string, std::weak_ptr<LogHandler>> newHandlerMap;
354 for (
const auto& entry : *handlers) {
355 newHandlerMap.emplace(entry.first, entry.second);
360 oldToNewHandlerMap->clear();
361 handlerInfo->handlers.clear();
362 for (
auto iter = newHandlerMap.begin(); iter != newHandlerMap.end(); ) {
363 if (iter->second.expired()) {
364 iter = newHandlerMap.erase(iter);
369 handlerInfo->handlers.
swap(newHandlerMap);
375 const std::vector<std::string>& categoryHandlerNames) {
376 std::vector<std::shared_ptr<LogHandler>> catHandlers;
377 for (
const auto& handlerName : categoryHandlerNames) {
378 auto iter = handlerMap.find(handlerName);
379 if (iter == handlerMap.end()) {
382 throw std::invalid_argument(to<std::string>(
383 "bug: unknown log handler \"",
385 "\" configured for log category \"",
389 catHandlers.push_back(iter->second);
407 if (!oldToNewHandlerMap.empty()) {
409 for (
const auto& entry : *loggerMap) {
410 entry.second->updateHandlers(oldToNewHandlerMap);
421 if (entry.second.handlers.hasValue()) {
423 handlers, entry.first, entry.second.handlers.value());
429 entry.second.level, entry.second.inheritParentLevel);
459 for (
const auto& entry : *loggersByName) {
460 auto* category = entry.second.get();
466 category->clearHandlers();
468 if (category == rootCategory) {
476 const auto& catConfig = configIter->second;
479 category->setLevelLocked(catConfig.level, catConfig.inheritParentLevel);
484 std::vector<std::shared_ptr<LogHandler>> catHandlers;
485 if (catConfig.handlers.hasValue()) {
487 handlers, entry.first, catConfig.handlers.value());
489 category->replaceHandlers(
std::move(catHandlers));
499 auto it = loggersByName.find(name);
500 if (it != loggersByName.end()) {
501 return it->second.get();
513 auto uptr = std::make_unique<LogCategory>(
name,
parent);
515 auto ret = loggersByName.emplace(logger->getName(),
std::move(uptr));
525 std::vector<LogCategory*> categories;
528 categories.reserve(loggersByName->size());
529 for (
const auto& entry : *loggersByName) {
530 categories.push_back(entry.second.get());
540 factories.swap(handlerInfo->factories);
541 handlers.swap(handlerInfo->handlers);
546 for (
auto* category : categories) {
547 category->clearHandlers();
555 std::set<std::shared_ptr<LogHandler>> handlers;
558 for (
const auto& entry : *loggersByName) {
559 for (
const auto&
handler : entry.second->getHandlers()) {
566 for (
const auto&
handler : handlers) {
569 return handlers.size();
573 std::unique_ptr<LogHandlerFactory> factory,
574 bool replaceExisting) {
575 auto type = factory->getType();
577 if (replaceExisting) {
580 auto ret = handlerInfo->factories.emplace(
type.str(),
std::move(factory));
582 throw std::range_error(to<std::string>(
583 "a LogHandlerFactory for the type \"",
type,
"\" already exists"));
590 auto numRemoved = handlerInfo->factories.erase(type.
str());
591 if (numRemoved != 1) {
592 throw std::range_error(
593 to<std::string>(
"no LogHandlerFactory for type \"", type,
"\" found"));
599 std::atomic<LogLevel>* xlogCategoryLevel,
605 if (xlogCategory !=
nullptr && *xlogCategory !=
nullptr) {
607 return (*xlogCategory)->getEffectiveLevel();
615 *xlogCategory = category;
618 xlogCategoryLevel->store(level, std::memory_order_release);
619 category->registerXlogLevel(xlogCategoryLevel);
626 std::atomic<bool>* isInitialized) {
631 if (isInitialized->load(std::memory_order_acquire)) {
633 return *xlogCategory;
637 *xlogCategory = category;
638 isInitialized->store(
true, std::memory_order_release);
688 static auto* rateLimiter =
690 if (!rateLimiter->check()) {
709 auto fullMsg = folly::to<std::string>(
710 "logging warning:", filename,
":", lineNumber,
": ", msg,
"\n");
folly::Synchronized< HandlerInfo > handlerInfo_
FOLLY_ATTR_WEAK void initializeLoggerDB(LoggerDB &db)
void unregisterHandlerFactory(folly::StringPiece type)
static folly::StringPiece getParent(folly::StringPiece name)
LogCategory * getCategory(folly::StringPiece name)
static Singleton< ShutdownSocketSet, PrivateTag > singleton
void swap(Synchronized &rhs)
std::unordered_map< std::shared_ptr< LogHandler >, std::shared_ptr< LogHandler >> OldToNewHandlerMap
void setLevelLocked(LogLevel level, bool inherit)
const CategoryConfigMap & getCategoryConfigs() const
static void internalWarningImpl(folly::StringPiece filename, int lineNumber, std::string &&msg) noexcept
fbstring exceptionStr(const std::exception &e)
constexpr detail::Map< Move > move
std::unordered_map< std::string, std::unique_ptr< LogHandlerFactory >> HandlerFactoryMap
std::vector< std::shared_ptr< LogHandler > > buildCategoryHandlerList(const NewHandlerMap &handlerMap, StringPiece categoryName, const std::vector< std::string > &categoryHandlerNames)
LogCategory * getOrCreateCategoryLocked(LoggerNameMap &loggersByName, folly::StringPiece name)
LogConfig getConfig() const
LogCategory * xlogInitCategory(folly::StringPiece categoryName, LogCategory **xlogCategory, std::atomic< bool > *isInitialized)
—— Concurrent Priority Queue Implementation ——
requires E e noexcept(noexcept(s.error(std::move(e))))
void resetConfig(const LogConfig &config)
Optional< std::string > type
void handler(int, siginfo_t *, void *)
typename Base::LockedPtr LockedPtr
LogCategory * createCategoryLocked(LoggerNameMap &loggersByName, folly::StringPiece name, LogCategory *parent)
std::unordered_map< std::string, std::weak_ptr< LogHandler >> HandlerMap
std::unordered_map< std::string, LogCategoryConfig > CategoryConfigMap
std::unique_ptr< LoggerDB > db_
void updateConfig(const LogConfig &config)
LogLevel xlogInit(folly::StringPiece categoryName, std::atomic< LogLevel > *xlogCategoryLevel, LogCategory **xlogCategory)
folly::Synchronized< LoggerNameMap > loggersByName_
constexpr LogLevel kDefaultLogLevel
void startConfigUpdate(const Synchronized< HandlerInfo >::LockedPtr &handlerInfo, const LogConfig &config, NewHandlerMap *handlers, OldToNewHandlerMap *oldToNewHandlerMap)
FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept
ssize_t writeFull(int fd, const void *buf, size_t count)
void finishConfigUpdate(const Synchronized< HandlerInfo >::LockedPtr &handlerInfo, NewHandlerMap *handlers, OldToNewHandlerMap *oldToNewHandlerMap)
static void defaultInternalWarningImpl(folly::StringPiece filename, int lineNumber, std::string &&msg) noexcept
LogCategory *FOLLY_NULLABLE getCategoryOrNull(folly::StringPiece name)
std::unordered_map< std::string, LogHandlerConfig > HandlerConfigMap
static void setInternalWarningHandler(InternalWarningHandler handler)
void setLevel(folly::StringPiece name, LogLevel level, bool inherit=true)
static std::atomic< InternalWarningHandler > warningHandler_
LogLevel getEffectiveLevel() const
const HandlerConfigMap & getHandlerConfigs() const
void replaceHandlers(std::vector< std::shared_ptr< LogHandler >> handlers)
void registerHandlerFactory(std::unique_ptr< LogHandlerFactory > factory, bool replaceExisting=false)
FOLLY_CPP14_CONSTEXPR const Value & value() const &
size_t flushAllHandlers()
void(*)(folly::StringPiece file, int lineNumber, std::string &&) InternalWarningHandler
LogConfig getConfigImpl(bool includeAllCategories) const
void update(const LogHandlerConfig &other)
LogConfig getFullConfig() const
folly::Function< void()> parent
std::unordered_map< folly::StringPiece, std::unique_ptr< LogCategory >, LogName::Hash, LogName::Equals > LoggerNameMap
std::unordered_map< std::string, std::shared_ptr< LogHandler >> NewHandlerMap