Fix SignalHandlerTest with ASAN
[folly.git] / folly / experimental / logging / LoggerDB.cpp
index 2611e23c98101dde2d9b9f9382a2e6bf2c81ac56..bd64d257b68c19c2db9dabdfda94238d788701f3 100644 (file)
@@ -107,40 +107,6 @@ void LoggerDB::setLevel(LogCategory* category, LogLevel level, bool inherit) {
   category->setLevelLocked(level, inherit);
 }
 
-std::vector<std::string> LoggerDB::processConfigString(
-    folly::StringPiece config) {
-  std::vector<std::string> errors;
-  if (config.empty()) {
-    return errors;
-  }
-
-  std::vector<StringPiece> pieces;
-  folly::split(",", config, pieces);
-  for (const auto& p : pieces) {
-    auto idx = p.rfind('=');
-    if (idx == folly::StringPiece::npos) {
-      errors.emplace_back(
-          folly::sformat("missing '=' in logger configuration: \"{}\"", p));
-      continue;
-    }
-
-    auto category = p.subpiece(0, idx);
-    auto level_str = p.subpiece(idx + 1);
-    LogLevel level;
-    try {
-      level = stringToLogLevel(level_str);
-    } catch (const std::exception&) {
-      errors.emplace_back(folly::sformat(
-          "invalid log level \"{}\" for category \"{}\"", level_str, category));
-      continue;
-    }
-
-    setLevel(category, level);
-  }
-
-  return errors;
-}
-
 LogConfig LoggerDB::getConfig() const {
   auto handlerInfo = handlerInfo_.rlock();
 
@@ -229,13 +195,6 @@ void LoggerDB::startConfigUpdate(
 
   // Create all of the new LogHandlers needed from this configuration
   for (const auto& entry : config.getHandlerConfigs()) {
-    // Look up the LogHandlerFactory
-    auto factoryIter = handlerInfo->factories.find(entry.second.type);
-    if (factoryIter == handlerInfo->factories.end()) {
-      throw std::invalid_argument(to<std::string>(
-          "unknown log handler type \"", entry.second.type, "\""));
-    }
-
     // Check to see if there is an existing LogHandler with this name
     std::shared_ptr<LogHandler> oldHandler;
     auto iter = handlers->find(entry.first);
@@ -243,16 +202,62 @@ void LoggerDB::startConfigUpdate(
       oldHandler = iter->second;
     }
 
+    LogHandlerConfig updatedConfig;
+    const LogHandlerConfig* handlerConfig;
+    if (entry.second.type.hasValue()) {
+      handlerConfig = &entry.second;
+    } else {
+      // This configuration is intended to update an existing LogHandler
+      if (!oldHandler) {
+        throw std::invalid_argument(to<std::string>(
+            "cannot update unknown log handler \"", entry.first, "\""));
+      }
+
+      updatedConfig = oldHandler->getConfig();
+      if (!updatedConfig.type.hasValue()) {
+        // This normally should not happen unless someone improperly manually
+        // constructed a LogHandler object.  All existing LogHandler objects
+        // should indicate their type.
+        throw std::invalid_argument(to<std::string>(
+            "existing log handler \"",
+            entry.first,
+            "\" is missing type information"));
+      }
+      updatedConfig.update(entry.second);
+      handlerConfig = &updatedConfig;
+    }
+
+    // Look up the LogHandlerFactory
+    auto factoryIter = handlerInfo->factories.find(handlerConfig->type.value());
+    if (factoryIter == handlerInfo->factories.end()) {
+      throw std::invalid_argument(to<std::string>(
+          "unknown log handler type \"", handlerConfig->type.value(), "\""));
+    }
+
     // Create the new log handler
     const auto& factory = factoryIter->second;
     std::shared_ptr<LogHandler> handler;
-    if (oldHandler) {
-      handler = factory->updateHandler(oldHandler, entry.second.options);
-      if (handler != oldHandler) {
-        oldToNewHandlerMap->emplace(oldHandler, handler);
+    try {
+      if (oldHandler) {
+        handler = factory->updateHandler(oldHandler, handlerConfig->options);
+        if (handler != oldHandler) {
+          oldToNewHandlerMap->emplace(oldHandler, handler);
+        }
+      } else {
+        handler = factory->createHandler(handlerConfig->options);
       }
-    } else {
-      handler = factory->createHandler(entry.second.options);
+    } catch (const std::exception& ex) {
+      // Errors creating or updating the the log handler are generally due to
+      // bad configuration options.  It is useful to update the exception
+      // message to include the name of the log handler we were trying to
+      // update or create.
+      throw std::invalid_argument(to<string>(
+          "error ",
+          oldHandler ? "updating" : "creating",
+          " log handler \"",
+          entry.first,
+          "\": ",
+          exceptionStr(ex)));
     }
     handlerInfo->handlers[entry.first] = handler;
     (*handlers)[entry.first] = handler;