logging: add numbered INFO* log level values
authorAdam Simpkins <simpkins@fb.com>
Wed, 10 Jan 2018 04:08:37 +0000 (20:08 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 10 Jan 2018 04:26:36 +0000 (20:26 -0800)
Summary:
Define INFO0 through INFO9 levels for users that want to have finer-grained
control over info log messages.

This also renumbers the DBG log levels slightly so that there are exactly 1000
levels between each major log level step.  This renumbering change should not
affect any code behavior, since these level values are primarily used in memory
and aren't saved persistently anywhere.

Reviewed By: yfeldblum

Differential Revision: D6690466

fbshipit-source-id: acd499cff6830a1d1b579f295bd4b2bac93b5ada

folly/experimental/logging/LogLevel.cpp
folly/experimental/logging/LogLevel.h
folly/experimental/logging/test/LogLevelTest.cpp

index 2858957..fc09b00 100644 (file)
@@ -15,6 +15,7 @@
  */
 #include <folly/experimental/logging/LogLevel.h>
 
+#include <array>
 #include <cctype>
 #include <ostream>
 
@@ -24,6 +25,20 @@ using std::string;
 
 namespace folly {
 
+namespace {
+struct NumberedLevelInfo {
+  LogLevel min;
+  LogLevel max;
+  StringPiece lowerPrefix;
+  StringPiece upperPrefix;
+};
+
+constexpr std::array<NumberedLevelInfo, 2> numberedLogLevels = {
+    NumberedLevelInfo{LogLevel::DBG, LogLevel::DBG0, "dbg", "DBG"},
+    NumberedLevelInfo{LogLevel::INFO, LogLevel::INFO0, "info", "INFO"},
+};
+} // namespace
+
 LogLevel stringToLogLevel(StringPiece name) {
   string lowerNameStr;
   lowerNameStr.reserve(name.size());
@@ -67,13 +82,19 @@ LogLevel stringToLogLevel(StringPiece name) {
     return LogLevel::MAX_LEVEL;
   }
 
-  if (lowerName.startsWith("dbg")) {
-    auto remainder = lowerName.subpiece(3);
+  for (const auto& info : numberedLogLevels) {
+    if (!lowerName.startsWith(info.lowerPrefix)) {
+      continue;
+    }
+    auto remainder = lowerName.subpiece(info.lowerPrefix.size());
     auto level = folly::tryTo<int>(remainder).value_or(-1);
-    if (level < 0 || level > 100) {
-      throw std::range_error("invalid dbg logger level: " + name.str());
+    if (level < 0 ||
+        static_cast<unsigned int>(level) > (static_cast<uint32_t>(info.max) -
+                                            static_cast<uint32_t>(info.min))) {
+      throw std::range_error(to<string>(
+          "invalid ", info.lowerPrefix, " logger level: ", name.str()));
     }
-    return LogLevel::DBG0 - level;
+    return info.max - level;
   }
 
   // Try as an plain integer if all else fails
@@ -106,12 +127,14 @@ string logLevelToString(LogLevel level) {
     return "FATAL";
   }
 
-  if (static_cast<uint32_t>(level) <= static_cast<uint32_t>(LogLevel::DBG0) &&
-      static_cast<uint32_t>(level) > static_cast<uint32_t>(LogLevel::DBG)) {
-    auto num =
-        static_cast<uint32_t>(LogLevel::DBG0) - static_cast<uint32_t>(level);
-    return folly::to<string>("DBG", num);
+  for (const auto& info : numberedLogLevels) {
+    if (static_cast<uint32_t>(level) <= static_cast<uint32_t>(info.max) &&
+        static_cast<uint32_t>(level) > static_cast<uint32_t>(info.min)) {
+      auto num = static_cast<uint32_t>(info.max) - static_cast<uint32_t>(level);
+      return folly::to<string>(info.upperPrefix, num);
+    }
   }
+
   return folly::to<string>("LogLevel(", static_cast<uint32_t>(level), ")");
 }
 
index f066fb5..6177710 100644 (file)
@@ -30,10 +30,10 @@ namespace folly {
  *
  * Higher levels are more important than lower ones.
  *
- * However, the numbers in the DBG* level names are reversed, and can be
- * thought of as debug verbosity levels.  Increasing DBG* numbers mean
- * increasing level of verbosity.  DBG0 is the least verbose debug level,
- * DBG1 is one level higher of verbosity, etc.
+ * However, the numbers in the DBG* and INFO* level names are reversed, and can
+ * be thought of as debug verbosity levels.  Increasing DBG* numbers mean
+ * increasing level of verbosity.  DBG0 is the least verbose debug level, DBG1
+ * is one level higher of verbosity, etc.
  */
 enum class LogLevel : uint32_t {
   UNINITIALIZED = 0,
@@ -49,20 +49,33 @@ enum class LogLevel : uint32_t {
   //
   // This is named "DBG" rather than "DEBUG" since some open source projects
   // define "DEBUG" as a preprocessor macro.
-  DBG = 900,
-
-  DBG0 = 1000,
-  DBG1 = 999,
-  DBG2 = 998,
-  DBG3 = 997,
-  DBG4 = 996,
-  DBG5 = 995,
-  DBG6 = 994,
-  DBG7 = 993,
-  DBG8 = 992,
-  DBG9 = 991,
+  DBG = 1000,
+
+  // Fine-grained debug log levels.
+  DBG0 = 1999,
+  DBG1 = 1998,
+  DBG2 = 1997,
+  DBG3 = 1996,
+  DBG4 = 1995,
+  DBG5 = 1994,
+  DBG6 = 1993,
+  DBG7 = 1992,
+  DBG8 = 1991,
+  DBG9 = 1990,
 
   INFO = 2000,
+  // Fine-grained info log levels.
+  INFO0 = 2999,
+  INFO1 = 2998,
+  INFO2 = 2997,
+  INFO3 = 2996,
+  INFO4 = 2995,
+  INFO5 = 2994,
+  INFO6 = 2993,
+  INFO7 = 2992,
+  INFO8 = 2991,
+  INFO9 = 2990,
+
   WARN = 3000,
   WARNING = 3000,
 
index 8a65266..cc3a0a3 100644 (file)
@@ -71,9 +71,19 @@ TEST(LogLevel, fromString) {
   EXPECT_EQ(LogLevel::DBG5, stringToLogLevel("dbg5"));
   EXPECT_EQ(LogLevel::DBG5, stringToLogLevel("DBG5"));
   EXPECT_EQ(LogLevel::DBG9, stringToLogLevel("DBG9"));
-  EXPECT_EQ(LogLevel::DBG + 1, stringToLogLevel("DBG99"));
-  EXPECT_EQ(LogLevel::DBG, stringToLogLevel("900"));
-  EXPECT_EQ(LogLevel::DBG, stringToLogLevel("LogLevel(900)"));
+  EXPECT_EQ(LogLevel::DBG + 1, stringToLogLevel("DBG998"));
+  EXPECT_EQ(LogLevel::DBG, stringToLogLevel("DBG999"));
+  EXPECT_EQ(LogLevel::DBG, stringToLogLevel("1000"));
+  EXPECT_EQ(LogLevel::DBG, stringToLogLevel("LogLevel(1000)"));
+
+  EXPECT_EQ(LogLevel::INFO0, stringToLogLevel("info0"));
+  EXPECT_EQ(LogLevel::INFO5, stringToLogLevel("INFO5"));
+  EXPECT_EQ(LogLevel::INFO5, stringToLogLevel("INFO5"));
+  EXPECT_EQ(LogLevel::INFO9, stringToLogLevel("info9"));
+  EXPECT_EQ(LogLevel::INFO + 1, stringToLogLevel("Info998"));
+  EXPECT_EQ(LogLevel::INFO, stringToLogLevel("INFO999"));
+  EXPECT_EQ(LogLevel::INFO, stringToLogLevel("2000"));
+  EXPECT_EQ(LogLevel::INFO6, stringToLogLevel("LogLevel(2993)"));
 
   EXPECT_THROW(stringToLogLevel("foobar"), std::range_error);
   EXPECT_THROW(stringToLogLevel("dbgx"), std::range_error);
@@ -100,10 +110,17 @@ TEST(LogLevel, toString) {
   EXPECT_EQ("DBG2", logLevelToString(LogLevel::DBG2));
   EXPECT_EQ("DBG5", logLevelToString(LogLevel::DBG5));
   EXPECT_EQ("DBG9", logLevelToString(LogLevel::DBG9));
-  EXPECT_EQ("DBG97", logLevelToString(static_cast<LogLevel>(903)));
+  EXPECT_EQ("DBG96", logLevelToString(static_cast<LogLevel>(1903)));
   EXPECT_EQ("DBG64", logLevelToString(LogLevel::DBG4 - 60));
 
-  EXPECT_EQ("LogLevel(1234)", logLevelToString(static_cast<LogLevel>(1234)));
+  EXPECT_EQ("INFO0", logLevelToString(LogLevel::INFO0));
+  EXPECT_EQ("INFO2", logLevelToString(LogLevel::INFO2));
+  EXPECT_EQ("INFO5", logLevelToString(LogLevel::INFO5));
+  EXPECT_EQ("INFO9", logLevelToString(LogLevel::INFO9));
+  EXPECT_EQ("INFO86", logLevelToString(static_cast<LogLevel>(2913)));
+  EXPECT_EQ("INFO57", logLevelToString(LogLevel::INFO7 - 50));
+
+  EXPECT_EQ("LogLevel(123)", logLevelToString(static_cast<LogLevel>(123)));
 }
 
 TEST(LogLevel, toStringAndBack) {