Browse Source

Collate objects into a message struct that can be lazily handled.

Sam Jaffe 6 years ago
parent
commit
e63a496c17

+ 16 - 6
include/logger/format.h

@@ -33,14 +33,24 @@ namespace logging {
     
   using string_generator = std::function<std::string(logpacket const &)>;
   string_generator get_date_formatter(std::string fmt);
+  
+  class message {
+  public:
+    message() = default;
+    message(char const * fmt) : format_code(fmt) {}
+    template <typename... Args>
+    message(std::string const & fmt, Args && ...args);
+    
+    std::string str() const;
     
-  void format_msg(std::ostream & os, std::string const & interp, size_t pos,
-                  std::vector<detail::object> const & objs, size_t idx);
+  private:
+    std::string format_code;
+    std::vector<detail::object> objects;
+  };
   
   template <typename... Args>
-  std::string format_msg(std::string const & interp, Args && ...args) {
-    std::stringstream msg;
-    format_msg(msg, interp, 0, {detail::object(args)...}, 0);
-    return msg.str();
+  message::message(std::string const & fmt, Args && ...args)
+  : format_code(fmt), objects({detail::object(args)...}) {
+    
   }
 }

+ 2 - 2
include/logger/logger.h

@@ -47,7 +47,7 @@ namespace logging {
     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)... ) );
+        log( ll, info, message( interp, std::forward<Args>(args)... ) );
       }
     }
     
@@ -59,7 +59,7 @@ namespace logging {
   private:
     friend class manager;
     bool should_log( level ) const;
-    void log( level ll, location_info info, std::string const& );
+    void log( level ll, location_info info, message const& );
 
   private:
     std::string const logger_name_;

+ 12 - 15
include/logger/logger_fwd.h

@@ -10,27 +10,24 @@
 #include <string>
 
 namespace logging {
-#define LIST_OF_LOGGING_LEVELS \
-  X(trace) X(debug) X(info) X(warning) X(error) X(critical) X(fatal) X(none)
-#define X(token) token,
-  enum class level : int {
-    LIST_OF_LOGGING_LEVELS warn = warning
-  };
-#undef X
+  enum class level : int;
+  struct logpacket;
+  
   std::ostream & operator<<(std::ostream & os, level l);
-
+  
   struct location_info {
     char const * filename = "???";
     int line = 0;
     char const * function = "";
   };
+}
 
-  struct logpacket {
-    struct timeval time;
-    //    int thread_id;
-    level level;
-    location_info info;
-    std::string logger;
-    std::string message;
+#define LIST_OF_LOGGING_LEVELS \
+  X(trace) X(debug) X(info) X(warning) X(error) X(critical) X(fatal) X(none)
+#define X(token) token,
+namespace logging {
+  enum class level : int {
+    LIST_OF_LOGGING_LEVELS warn = warning
   };
 }
+#undef X

+ 16 - 0
include/logger/logpacket.h

@@ -0,0 +1,16 @@
+
+#pragma once
+
+#include "logger_fwd.h"
+#include "format.h"
+
+namespace logging {
+  struct logpacket {
+    struct timeval time;
+    //    int thread_id;
+    level level;
+    location_info info;
+    std::string logger;
+    message message;
+  };
+}

+ 2 - 1
src/c_logger.cxx

@@ -9,6 +9,7 @@
 
 #include "common.h"
 #include "logger/detail/logger_impl.h"
+#include "logger/logpacket.h"
 
 using namespace logging;
 
@@ -29,7 +30,7 @@ void c_logger::vlognf(level level, size_t num_bytes, char const* fmt,
   int n = vsnprintf(data.get(), num_bytes, fmt, args);
   if (n >= 0) {
     data[num_bytes-1] = '\0';
-    impl_->write({ now(), level, {}, logger_name_, data.get() });
+    impl_->write({ now(), level, {}, logger_name_, {data.get()} });
   }
 }
 

+ 1 - 0
src/date_format.cxx

@@ -12,6 +12,7 @@
 #include "logger/exception.h"
 #include "logger/format.h"
 #include "logger/logger_fwd.h"
+#include "logger/logpacket.h"
 
 namespace logging {
   std::string fmt_time(struct timeval round, char const * const fmt) {

+ 8 - 1
src/format.cxx

@@ -19,6 +19,7 @@
 #include "common.h"
 #include "logger/exception.h"
 #include "logger/logger.h"
+#include "logger/logpacket.h"
 
 #if defined( _WIN32 )
 # define NEWLINE "\r\n"
@@ -65,7 +66,7 @@ namespace logging {
       };
     } else if (is('m')) {
       return [](logpacket const & lp){
-        return lp.message;
+        return lp.message.str();
       };
     } else {
       std::string error_msg{"unknown format character: '"};
@@ -168,4 +169,10 @@ namespace logging {
       format_msg(os << objs[idx], interp, next+2, objs, idx+1);
     }
   }
+  
+  std::string message::str() const {
+    std::stringstream ss;
+    format_msg(ss, format_code, 0, objects, 0);
+    return ss.str();
+  }
 }

+ 2 - 1
src/logger.cxx

@@ -17,6 +17,7 @@
 
 #include "common.h"
 #include "logger/detail/logger_impl.h"
+#include "logger/logpacket.h"
 
 namespace logging {
   logger::logger(std::string const & name, std::shared_ptr<logger_impl> impl)
@@ -29,7 +30,7 @@ namespace logging {
   }
   
   void logger::log(level ll, location_info info,
-                   std::string const & msg) {
+                   message const & msg) {
     impl_->write({ now(), ll, info, logger_name_, msg });
   }
   

+ 1 - 0
src/logger_impl.cxx

@@ -9,6 +9,7 @@
 
 #include "logger/detail/appender.h"
 #include "logger/detail/layout.h"
+#include "logger/logpacket.h"
 
 using namespace logging;
 

+ 2 - 1
src/loggers/default_layout.cxx

@@ -9,6 +9,7 @@
 
 #include "logger/detail/layout.h"
 #include "logger/log_manager.h"
+#include "logger/logpacket.h"
 
 using namespace logging;
 
@@ -22,7 +23,7 @@ std::shared_ptr<layout> default_layout::create(properties const &) {
 }
 
 std::string default_layout::format(logpacket const & pkt) const {
-  return pkt.message;
+  return pkt.message.str();
 }
 
 namespace {

+ 2 - 5
test/c_logger_test.cxx

@@ -32,9 +32,7 @@ TEST_F(CLoggerTest, FlushesOnFlushCall) {
 
 TEST_F(CLoggerTest, LogsWithFmtCode) {
   using testing::_;
-  using testing::Field;
-  // TODO: Eq
-  EXPECT_CALL(*layout, format(Field(&logpacket::message, "5"))).Times(1);
+  EXPECT_CALL(*layout, format(MessageEq("5"))).Times(1);
   t_logger("", pimpl).errorf("%d", 5);
 }
 
@@ -56,8 +54,7 @@ TEST_F(CLoggerTest, FmtLogHasLevelInHeader) {
 
 TEST_F(CLoggerTest, LogsRawData) {
   using testing::_;
-  using testing::Field;
-  EXPECT_CALL(*layout, format(Field(&logpacket::message, "5"))).Times(1);
+  EXPECT_CALL(*layout, format(MessageEq("5"))).Times(1);
   t_logger("", pimpl).error("5");
 }
 

+ 1 - 0
test/format_test.cxx

@@ -9,6 +9,7 @@
 
 #include "logger/exception.h"
 #include "logger/format.h"
+#include "logger/logpacket.h"
 
 using namespace logging;
 

+ 2 - 4
test/logger_test.cxx

@@ -29,8 +29,7 @@ TEST_F(LoggerTest, FlushesOnFlushCall) {
 }
 
 TEST_F(LoggerTest, LogsWithBraceFmtCode) {
-  using testing::Field;
-  EXPECT_CALL(*layout, format(Field(&logpacket::message, "5"))).Times(1);
+  EXPECT_CALL(*layout, format(MessageEq("5"))).Times(1);
   t_logger("", pimpl).log(level::error, "{}", 5);
 }
 
@@ -42,7 +41,6 @@ TEST_F(LoggerTest, DoesNotLogAboveLevel) {
 }
 
 TEST_F(LoggerTest, LogCurlyBraceLiteralByDoubling) {
-  using testing::Field;
-  EXPECT_CALL(*layout, format(Field(&logpacket::message, "{}"))).Times(1);
+  EXPECT_CALL(*layout, format(MessageEq("{}"))).Times(1);
   t_logger("", pimpl).log(level::error, "{{}}", 5);
 }

+ 7 - 2
test/mock_logger.h

@@ -13,6 +13,7 @@
 #include "logger/detail/appender.h"
 #include "logger/detail/layout.h"
 #include "logger/detail/logger_impl.h"
+#include "logger/logpacket.h"
 
 namespace logging {
   inline void PrintTo(location_info const & info, std::ostream * os) {
@@ -27,7 +28,7 @@ namespace logging {
   inline void PrintTo(logpacket const & pkt, std::ostream * os) {
     (*os) << "{ " << pkt.level << ", ";
     PrintTo(pkt.info, os);
-    (*os) << ", \"" << pkt.logger << "\", \"" << pkt.message << "\" }";
+    (*os) << ", \"" << pkt.logger << "\", \"" << pkt.message.str() << "\" }";
   }
 }
 
@@ -43,7 +44,11 @@ struct MockLayout : public logging::layout {
 };
 
 ACTION(ReturnMessage) {
-  return arg0.message;
+  return arg0.message.str();
+}
+
+MATCHER_P(MessageEq, value, "") {
+  return arg.message.str() == value;
 }
 
 struct LoggerTest : public testing::Test {