Commit b6e14b7b authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

logging: add a LoggerDB::getConfig() method

Summary: Add a method to get the current LogConfig state from the LoggerDB.

Reviewed By: bolinfest

Differential Revision: D6200596

fbshipit-source-id: 3bc57d498a5d25d19099d861376d71ea9f7e4039
parent 2fa201bf
...@@ -75,6 +75,15 @@ class LogCategory { ...@@ -75,6 +75,15 @@ class LogCategory {
level_.load(std::memory_order_acquire) & ~FLAG_INHERIT); level_.load(std::memory_order_acquire) & ~FLAG_INHERIT);
} }
/**
* Get the log level and inheritance flag.
*/
std::pair<LogLevel, bool> getLevelInfo() const {
auto value = level_.load(std::memory_order_acquire);
return {static_cast<LogLevel>(value & ~FLAG_INHERIT),
bool(value & FLAG_INHERIT)};
}
/** /**
* Get the effective level for this log category. * Get the effective level for this log category.
* *
......
...@@ -21,12 +21,15 @@ ...@@ -21,12 +21,15 @@
#include <folly/FileUtil.h> #include <folly/FileUtil.h>
#include <folly/String.h> #include <folly/String.h>
#include <folly/experimental/logging/LogCategory.h> #include <folly/experimental/logging/LogCategory.h>
#include <folly/experimental/logging/LogConfig.h>
#include <folly/experimental/logging/LogHandler.h> #include <folly/experimental/logging/LogHandler.h>
#include <folly/experimental/logging/LogHandlerFactory.h> #include <folly/experimental/logging/LogHandlerFactory.h>
#include <folly/experimental/logging/LogLevel.h> #include <folly/experimental/logging/LogLevel.h>
#include <folly/experimental/logging/Logger.h> #include <folly/experimental/logging/Logger.h>
#include <folly/experimental/logging/RateLimiter.h> #include <folly/experimental/logging/RateLimiter.h>
using std::string;
namespace folly { namespace folly {
namespace { namespace {
...@@ -138,6 +141,73 @@ std::vector<std::string> LoggerDB::processConfigString( ...@@ -138,6 +141,73 @@ std::vector<std::string> LoggerDB::processConfigString(
return errors; return errors;
} }
LogConfig LoggerDB::getConfig() const {
auto handlerInfo = handlerInfo_.rlock();
LogConfig::HandlerConfigMap handlerConfigs;
std::unordered_map<std::shared_ptr<LogHandler>, string> handlersToName;
for (const auto& entry : handlerInfo->handlers) {
auto handler = entry.second.lock();
if (!handler) {
continue;
}
handlersToName.emplace(handler, entry.first);
handlerConfigs.emplace(entry.first, handler->getConfig());
}
size_t anonymousNameIndex = 1;
auto generateAnonymousHandlerName = [&]() {
// Return a unique name of the form "anonymousHandlerN"
// Keep incrementing N until we find a name that isn't currently taken.
while (true) {
auto name = to<string>("anonymousHandler", anonymousNameIndex);
++anonymousNameIndex;
if (handlerInfo->handlers.find(name) == handlerInfo->handlers.end()) {
return name;
}
}
};
LogConfig::CategoryConfigMap categoryConfigs;
{
auto loggersByName = loggersByName_.rlock();
for (const auto& entry : *loggersByName) {
auto* category = entry.second.get();
auto levelInfo = category->getLevelInfo();
auto handlers = category->getHandlers();
// Don't report categories that have default settings.
if (handlers.empty() && levelInfo.first == LogLevel::MAX_LEVEL &&
levelInfo.second) {
continue;
}
// Translate the handler pointers to names
std::vector<string> handlerNames;
for (const auto& handler : handlers) {
auto iter = handlersToName.find(handler);
if (iter == handlersToName.end()) {
// This LogHandler must have been manually attached to the category,
// rather than defined with `updateConfig()` or `resetConfig()`.
// Generate a unique name to use for reporting it in the config.
auto name = generateAnonymousHandlerName();
handlersToName.emplace(handler, name);
handlerConfigs.emplace(name, handler->getConfig());
handlerNames.emplace_back(name);
} else {
handlerNames.emplace_back(iter->second);
}
}
LogCategoryConfig categoryConfig(
levelInfo.first, levelInfo.second, handlerNames);
categoryConfigs.emplace(category->getName(), std::move(categoryConfig));
}
}
return LogConfig{std::move(handlerConfigs), std::move(categoryConfigs)};
}
LogCategory* LoggerDB::getOrCreateCategoryLocked( LogCategory* LoggerDB::getOrCreateCategoryLocked(
LoggerNameMap& loggersByName, LoggerNameMap& loggersByName,
StringPiece name) { StringPiece name) {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
namespace folly { namespace folly {
class LogCategory; class LogCategory;
class LogConfig;
class LogHandler; class LogHandler;
class LogHandlerFactory; class LogHandlerFactory;
enum class LogLevel : uint32_t; enum class LogLevel : uint32_t;
...@@ -76,6 +77,17 @@ class LoggerDB { ...@@ -76,6 +77,17 @@ class LoggerDB {
void setLevel(folly::StringPiece name, LogLevel level, bool inherit = true); void setLevel(folly::StringPiece name, LogLevel level, bool inherit = true);
void setLevel(LogCategory* category, LogLevel level, bool inherit = true); void setLevel(LogCategory* category, LogLevel level, bool inherit = true);
/**
* Get a LogConfig object describing the current state of the LoggerDB.
*
* Note that this may not 100% accurately describe the current configuration
* if callers have manually added LogHandlers to some categories without
* using the updateConfig() or resetConfig() functions. In this case
* getConfig() will simply report these handlers as "unknown_handler" when
* returning handler names for the categories in question.
*/
LogConfig getConfig() const;
/** /**
* Apply a configuration string specifying a series a log levels. * Apply a configuration string specifying a series a log levels.
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment