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 2858957f2fccd72144866dfac2bed7e3d0002835..fc09b006784f6476480730909a3fc8d38853d1aa 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 f066fb50942878bb3e56091314306ef92d6811c2..6177710cd9075a7b2095559aad732665237117cd 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 8a6526656bb1c1301bb2ec84867ce14aac4498e0..cc3a0a342f9610017cd33eb94c53db35346d7086 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) {