Browse Source

Switch to using an enum class for log_level

Sam Jaffe 6 năm trước cách đây
mục cha
commit
57d456e63d

+ 18 - 38
include/logger/c_logger.h

@@ -25,6 +25,14 @@
 
 #define VA_LOG(level) VA_LOGN(level, c_logger::LOGF_MAX_SIZE)
 
+#define MAKE_LOGGER_FMT(lvl)                                        \
+  inline void lvl##f(char const * fmt, ...) { VA_LOG(level::lvl); } \
+  inline void lvl##nf(size_t n, char const * fmt, ...) {            \
+    VA_LOGN(level::lvl, n);                                         \
+  }                                                                 \
+  inline void lvl(char const * msg) { log(level::lvl, msg); }       \
+  inline void lvl(std::string const & msg) { log(level::lvl, msg); }
+
 namespace logging {
   class logger_impl;
   
@@ -32,43 +40,16 @@ namespace logging {
   public:
     static const size_t LOGF_MAX_SIZE = 2048;
   public:
-    inline void tracef(char const* fmt, ...) { VA_LOG(LTRACE); }
-    inline void tracenf(size_t n, char const* fmt, ...) { VA_LOGN(LTRACE, n); }
-    inline void trace(char const* msg) { log(LTRACE, msg); }
-    inline void trace(std::string const& msg) { log(LTRACE, msg); }
-    
-    inline void debugf(char const* fmt, ...) { VA_LOG(LDEBUG); }
-    inline void debugnf(size_t n, char const* fmt, ...) { VA_LOGN(LDEBUG, n); }
-    inline void debug(char const* msg) { log(LDEBUG, msg); }
-    inline void debug(std::string const& msg) { log(LDEBUG, msg); }
-    
-    inline void infof(char const* fmt, ...) { VA_LOG(LINFO); }
-    inline void infonf(size_t n, char const* fmt, ...) { VA_LOGN(LINFO, n); }
-    inline void info(char const* msg) { log(LINFO, msg); }
-    inline void info(std::string const& msg) { log(LINFO, msg); }
-    
-    inline void warnf(char const* fmt, ...) { VA_LOG(LWARNING); }
-    inline void warnnf(size_t n, char const* fmt, ...) { VA_LOGN(LWARNING, n); }
-    inline void warn(char const* msg) { log(LWARNING, msg); }
-    inline void warn(std::string const& msg) { log(LWARNING, msg); }
-    
-    inline void errorf(char const* fmt, ...) { VA_LOG(LERROR); }
-    inline void errornf(size_t n, char const* fmt, ...) { VA_LOGN(LERROR, n); }
-    inline void error(char const* msg) { log(LERROR, msg); }
-    inline void error(std::string const& msg) { log(LERROR, msg); }
-    
-    inline void criticalf(char const* fmt, ...) { VA_LOG(LCRITICAL); }
-    inline void criticalnf(size_t n, char const* fmt, ...) { VA_LOGN(LCRITICAL, n); }
-    inline void critical(char const* msg) { log(LCRITICAL, msg); }
-    inline void critical(std::string const& msg) { log(LCRITICAL, msg); }
-    
-    inline void fatalf(char const* fmt, ...) { VA_LOG(LFATAL); }
-    inline void fatalnf(size_t n, char const* fmt, ...) { VA_LOGN(LFATAL, n); }
-    inline void fatal(char const* msg) { log(LFATAL, msg); }
-    inline void fatal(std::string const& msg) { log(LFATAL, msg); }
+    MAKE_LOGGER_FMT(trace)
+    MAKE_LOGGER_FMT(debug)
+    MAKE_LOGGER_FMT(info)
+    MAKE_LOGGER_FMT(warn)
+    MAKE_LOGGER_FMT(error)
+    MAKE_LOGGER_FMT(critical)
+    MAKE_LOGGER_FMT(fatal)
     
     template <typename... Args>
-    inline void log(log_level ll, std::string const & interp, Args && ...args);
+    inline void log(level ll, std::string const & interp, Args && ...args);
     
     void flush();
     
@@ -79,11 +60,10 @@ namespace logging {
     c_logger(std::string const & name, std::shared_ptr<logger_impl> impl);
 
   private:
-    void vlognf(log_level, size_t, char const*, va_list);
-    void log(log_level, std::string const&);
+    void vlognf(level, size_t, char const*, va_list);
+    void log(level, std::string const&);
     
   private:
-    log_level min_level_;
     std::string logger_name_;
     std::shared_ptr<logger_impl> impl_;
   };

+ 2 - 2
include/logger/detail/appender.h

@@ -9,11 +9,11 @@ namespace logging {
     virtual void write(std::string const & msg) = 0;
     virtual void flush() = 0;
     
-    bool should_log(log_level ll) const {
+    bool should_log(level ll) const {
       return ll >= min_log_level;
     }
     
   protected:
-    log_level min_log_level;
+    level min_log_level;
   };
 }

+ 2 - 2
include/logger/detail/logger_impl.h

@@ -14,11 +14,11 @@ namespace logging {
     using p_appender = std::shared_ptr<appender>;
     using p_layout = std::shared_ptr<layout>;
 
-    bool should_log(log_level ll) const;
+    bool should_log(level ll) const;
     void write(logpacket const & pkt);
     void flush();
 
     std::vector<std::pair<p_appender, p_layout>> impls_;
-    log_level min_log_level_;
+    level min_log_level_;
   };
 }

+ 3 - 0
include/logger/detail/to_json.h

@@ -24,6 +24,9 @@ namespace logging { namespace detail {
   json to_json(T const & obj);
 } }
 #else
+namespace logging {
+  typedef void json;
+}
 namespace logging { namespace detail {
   template <typename T> void to_json(T const &) {}
 } }

+ 6 - 8
include/logger/logger.h

@@ -27,8 +27,8 @@
 #include "format.h"
 
 #define log_here { __FILE__, __LINE__, STRING( FUNCTION ) }
-#define log_message( logger, level, ... )   \
-  logger.log( level, log_here, __VA_ARGS__ )
+#define log_message( logger, lvl, ... )   \
+logger.log( level::lvl, log_here, __VA_ARGS__ )
 
 namespace logging {
   class logger_impl;
@@ -39,13 +39,12 @@ namespace logging {
     ~logger();
 
     template <typename... Args>
-    inline void log(log_level ll, std::string const & interp,
-                    Args && ...args) {
+    inline void log(level ll, std::string const & interp, Args && ...args) {
       log( ll, location_info{}, interp, std::forward<Args>(args)... );
     }
     
     template <typename... Args>
-    inline void log(log_level ll, location_info info,
+    inline void log(level ll, location_info info,
                     std::string const & interp, Args && ...args) {
       if ( should_log( ll ) ) {
         log( ll, info, format_msg( interp, std::forward<Args>(args)... ) );
@@ -59,11 +58,10 @@ namespace logging {
     
   private:
     friend class manager;
-    bool should_log( log_level ) const;
-    void log( log_level ll, location_info info, std::string const& );
+    bool should_log( level ) const;
+    void log( level ll, location_info info, std::string const& );
 
   private:
-    log_level min_level_;
     std::string const logger_name_;
     std::shared_ptr<logger_impl> impl_;
   };

+ 9 - 11
include/logger/logger_fwd.h

@@ -10,17 +10,15 @@
 #include <string>
 
 namespace logging {
-  enum log_level {
-    LTRACE,
-    LDEBUG,
-    LINFO,
-    LWARNING,
-    LERROR,
-    LCRITICAL,
-    LFATAL,
-    LNONE
+#define LIST_OF_LOGGING_LEVELS \
+  X(trace) X(debug) X(info) X(warning) X(error) X(critical) X(fatal)
+#define X(token) token,
+  enum class level : int {
+    LIST_OF_LOGGING_LEVELS none, warn = warning
   };
-    
+#undef X
+  std::ostream & operator<<(std::ostream & os, level l);
+
   struct location_info {
     char const * filename = "???";
     int line = 0;
@@ -30,7 +28,7 @@ namespace logging {
   struct logpacket {
     struct timeval time;
     //    int thread_id;
-    log_level level;
+    level level;
     location_info info;
     std::string logger;
     std::string message;

+ 11 - 2
include/logger/wrapper_object.h

@@ -23,10 +23,12 @@ namespace logging { namespace detail {
       return os << obj.to_string_(obj.ptr_);
     }
     template <typename> static std::string to_string_impl(void * ptr);
-    
+    template <typename> static json to_json_impl(void * ptr);
+
   private:
     void * ptr_;
     std::string (*to_string_)(void*);
+    json (*to_json_)(void*);
   };
   
   
@@ -35,9 +37,16 @@ namespace logging { namespace detail {
     return to_string(*static_cast<T*>(ptr));
   }
   
+  template <typename T>
+  json object::to_json_impl(void * ptr) {
+    return to_json(*static_cast<T*>(ptr));
+  }
+  
   template <typename T>
   object::object(T & object)
-  : ptr_(&object), to_string_(&object::to_string_impl<T>) {
+  : ptr_(&object),
+  to_string_(&object::to_string_impl<T>),
+  to_json_(&object::to_json_impl<T>) {
     
   }
 } }

+ 5 - 5
src/c_logger.cxx

@@ -14,7 +14,7 @@ using namespace logging;
 
 c_logger::c_logger(std::string const & name,
                    std::shared_ptr<logger_impl> impl)
-: min_level_(LDEBUG), logger_name_(name), impl_(impl)
+: logger_name_(name), impl_(impl)
 {
 }
 
@@ -22,9 +22,9 @@ c_logger::~c_logger() {
   if (impl_) impl_->flush();
 }
 
-void c_logger::vlognf(log_level level, size_t num_bytes, char const* fmt,
+void c_logger::vlognf(level level, size_t num_bytes, char const* fmt,
                       va_list args) {
-  if (level < min_level_ || !impl_->should_log(level)) return;
+  if (!impl_->should_log(level)) return;
   const std::unique_ptr<char[]> data(new char[num_bytes]);
   int n = vsnprintf(data.get(), num_bytes, fmt, args);
   if (n >= 0) {
@@ -33,8 +33,8 @@ void c_logger::vlognf(log_level level, size_t num_bytes, char const* fmt,
   }
 }
 
-void c_logger::log(log_level level, std::string const& msg) {
-  if (level < min_level_ || !impl_->should_log(level)) return;
+void c_logger::log(level level, std::string const& msg) {
+  if (!impl_->should_log(level)) return;
   impl_->write({ now(), level, {}, logger_name_, msg });
 }
 

+ 31 - 25
src/common.cxx

@@ -10,32 +10,38 @@
 #include <cassert>
 #include <ctime>
 
-#define X(l)          \
-  case logging::L##l: \
-    return #l;
-const char* logging::level_header(log_level l) {
-  assert(l != logging::LNONE);
-  switch (l) {
-    X(FATAL)
-    X(CRITICAL)
-    X(ERROR)
-    X(WARNING)
-    X(INFO)
-    X(DEBUG)
-    X(TRACE)
-    X(NONE)
+namespace logging {
+  timeval now() {
+    struct timeval tv;
+    gettimeofday( &tv, nullptr );
+    return tv;
+  }
+  
+#define X(token) if (lower_case == #token) return level::token; else
+  level level_from_string(std::string const & str) {
+    std::string lower_case;
+    std::transform(str.begin(), str.end(), lower_case.begin(), &tolower);
+    LIST_OF_LOGGING_LEVELS
+    return level::none;
   }
-}
 #undef X
-
-timeval logging::now() {
-  struct timeval tv;
-  gettimeofday( &tv, nullptr );
-  return tv;
-}
-
-namespace logging {
-  std::ostream & operator<<(std::ostream & os, log_level l) {
-    return os << std::string(level_header(l));
+  
+#define X(token) if (lvl == level::token) return #token; else
+  char const * level_to_string(level lvl) {
+    LIST_OF_LOGGING_LEVELS
+    return "";
+  }
+#undef X
+  
+  std::string to_string(level lvl, bool uppercase) {
+    std::string str = level_to_string(lvl);
+    if (uppercase) {
+      std::transform(str.begin(), str.end(), str.begin(), &toupper);
+    }
+    return str;
+  }
+  
+  std::ostream & operator<<(std::ostream & os, level l) {
+    return os << std::string(level_to_string(l));
   }
 }

+ 3 - 3
src/common.h

@@ -12,9 +12,9 @@
 #include "logger/logger_fwd.h"
 
 namespace logging {
-  const char* level_header(log_level l);
   timeval now();
-  std::string timestamp();
 
-  std::ostream & operator<<(std::ostream & os, log_level l);
+  level level_from_string(std::string const & value);
+  char const * level_to_string(level lvl);
+  std::string to_string(level lvl, bool uppercase);
 }

+ 1 - 1
src/format.cxx

@@ -61,7 +61,7 @@ namespace logging {
       };
     } else if (is('p')) {
       return [](logpacket const & lp){
-        return level_header(lp.level);
+        return to_string(lp.level, true);
       };
     } else if (is('m')) {
       return [](logpacket const & lp){

+ 4 - 4
src/logger.cxx

@@ -20,7 +20,7 @@
 
 namespace logging {
   logger::logger(std::string const & name, std::shared_ptr<logger_impl> impl)
-  : min_level_(LDEBUG), logger_name_(name), impl_(impl)
+  : logger_name_(name), impl_(impl)
   {
   }
   
@@ -28,13 +28,13 @@ namespace logging {
     if (impl_) impl_->flush();
   }
   
-  void logger::log(log_level ll, location_info info,
+  void logger::log(level ll, location_info info,
                    std::string const & msg) {
     impl_->write({ now(), ll, info, logger_name_, msg });
   }
   
-  bool logger::should_log(log_level ll) const {
-    return ll >= min_level_ && impl_->should_log( ll );
+  bool logger::should_log(level ll) const {
+    return impl_->should_log( ll );
   }
   
   void logger::flush() {

+ 1 - 1
src/logger_impl.cxx

@@ -12,7 +12,7 @@
 
 using namespace logging;
 
-bool logger_impl::should_log(log_level ll) const {
+bool logger_impl::should_log(level ll) const {
   return ll >= min_log_level_;
 }
 

+ 3 - 3
test/c_logger_test.cxx

@@ -50,7 +50,7 @@ TEST_F(CLoggerTest, FmtLogHasNameInHeader) {
 TEST_F(CLoggerTest, FmtLogHasLevelInHeader) {
   using testing::_;
   using testing::Field;
-  EXPECT_CALL(*layout, format(Field(&logpacket::level, LERROR))).Times(1);
+  EXPECT_CALL(*layout, format(Field(&logpacket::level, level::error))).Times(1);
   t_logger("TEST", pimpl).errorf("%d", 5);
 }
 
@@ -63,14 +63,14 @@ TEST_F(CLoggerTest, LogsRawData) {
 
 TEST_F(CLoggerTest, DoesNotLogAboveLevel) {
   using testing::_;
-  pimpl->min_log_level_ = LFATAL;
+  pimpl->min_log_level_ = level::fatal;
   EXPECT_CALL(*appender, write(_)).Times(0);
   t_logger("", pimpl).errorf("%d", 5);
 }
 
 TEST_F(CLoggerTest, DoesNotRawLogAboveLevel) {
   using testing::_;
-  pimpl->min_log_level_ = LFATAL;
+  pimpl->min_log_level_ = level::fatal;
   EXPECT_CALL(*appender, write(_)).Times(0);
   t_logger("", pimpl).error("5");
 }

+ 8 - 8
test/format_test.cxx

@@ -105,21 +105,21 @@ TEST(FormatTest, SupportsHumanDateFormat) {
 TEST(FormatTest, LoggerIdIsCToken) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%c");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq("UNIT_TEST"));
 }
 
 TEST(FormatTest, LogLevelIsPToken) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%p");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq("ERROR"));
 }
 
 TEST(FormatTest, LogMessageIsMToken) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%m");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq("HELLO"));
 }
 
@@ -132,29 +132,29 @@ TEST(FormatTest, ThrowsOnUnknownToken) {
 TEST(FormatTest, TokenCanBeTruncatedInFormat) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%.3m");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq("HEL"));
 }
 
 TEST(FormatTest, TokenCanBeLeftPadded) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%6m");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq(" HELLO"));
 }
 
 TEST(FormatTest, TokenCanBeRightPadded) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%-6m");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq("HELLO "));
 }
 
 TEST(FormatTest, TokenCanBeSizeBound) {
   using testing::Eq;
   auto fmt = format::parse_format_string("%6.8m");
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO"}),
               Eq(" HELLO"));
-  EXPECT_THAT(fmt.process({{}, LERROR, {}, "UNIT_TEST", "HELLO FRIEND"}),
+  EXPECT_THAT(fmt.process({{}, level::error, {}, "UNIT_TEST", "HELLO FRIEND"}),
               Eq("HELLO FR"));
 }

+ 4 - 4
test/logger_test.cxx

@@ -31,18 +31,18 @@ TEST_F(LoggerTest, FlushesOnFlushCall) {
 TEST_F(LoggerTest, LogsWithBraceFmtCode) {
   using testing::Field;
   EXPECT_CALL(*layout, format(Field(&logpacket::message, "5"))).Times(1);
-  t_logger("", pimpl).log(LERROR, "{}", 5);
+  t_logger("", pimpl).log(level::error, "{}", 5);
 }
 
 TEST_F(LoggerTest, DoesNotLogAboveLevel) {
   using testing::_;
-  pimpl->min_log_level_ = LFATAL;
+  pimpl->min_log_level_ = level::fatal;
   EXPECT_CALL(*appender, write(_)).Times(0);
-  t_logger("", pimpl).log(LERROR, "{}", 5);
+  t_logger("", pimpl).log(level::error, "{}", 5);
 }
 
 TEST_F(LoggerTest, LogCurlyBraceLiteralByDoubling) {
   using testing::Field;
   EXPECT_CALL(*layout, format(Field(&logpacket::message, "{}"))).Times(1);
-  t_logger("", pimpl).log(LERROR, "{{}}", 5);
+  t_logger("", pimpl).log(level::error, "{{}}", 5);
 }

+ 2 - 2
test/mock_logger.h

@@ -32,8 +32,8 @@ namespace logging {
 }
 
 struct MockAppender : public logging::appender {
-  MockAppender() { SetLogLevel(logging::LTRACE); }
-  void SetLogLevel(logging::log_level ll) { min_log_level = ll; }
+  MockAppender() { SetLogLevel(logging::level::trace); }
+  void SetLogLevel(logging::level ll) { min_log_level = ll; }
   MOCK_METHOD0(flush, void());
   MOCK_METHOD1(write, void(std::string const &));
 };