Quellcode durchsuchen

Fixing test cases, biting the bullet and including jsoncpp on a permanent basis.

Sam Jaffe vor 6 Jahren
Ursprung
Commit
3a8d12c57d

+ 4 - 31
include/logger/detail/to_json.h

@@ -7,42 +7,15 @@
 
 #pragma once
 
-#include <iostream>
+#include <string>
 
-#if defined(LOGGING_JSON_SJAFFE)
-#  include "json/json.hpp"
-#endif
-#if defined(LOGGING_JSON_VALUE)
-#  include <memory>
-#  include "json/json.h"
-#endif
+#include <json/json.h>
 
 namespace logging { namespace detail {
   template <typename T> std::string to_string(T const & obj);
-
-// TODO: Establish bindings
-#if defined(LOGGING_JSON_SJAFFE)
-  template <typename T, typename S>
-  void to_stream(json::binder::visitor<T, S> const & visitor,
-                 std::ostream & out) {
-    json::parser::write(visitor, out);
-  }
-  
-  void to_stream(json::value const & obj, std::ostream & os) {
-    json::parser::write(obj, os);
-  }
-#endif
-
-#if defined(LOGGING_JSON_VALUE)
-  void to_stream(Json::Value const & obj, std::ostream & os) {
-    Json::StreamWriterBuilder build;
-    std::unique_ptr<Json::StreamWriter> ptr(build.newStreamWriter());
-    return ptr->write(obj, &os);
-  }
-#endif
   
   template <typename T>
-  std::string to_json(T const & obj, bool compact = false) {
-    return "\"" + to_string(obj) + "\"";
+  Json::Value to_json(T const & obj) {
+    return to_string(obj);
   }
 } }

+ 1 - 1
include/logger/format.h

@@ -42,7 +42,7 @@ namespace logging {
     message(std::string const & fmt, Args && ...args);
     
     std::string str() const;
-    std::string json() const;
+    Json::Value json() const;
   private:
     std::string format_code;
     std::vector<detail::object> objects;

+ 4 - 4
include/logger/wrapper_object.h

@@ -18,19 +18,19 @@ namespace logging { namespace detail {
   public:
     template <typename T> explicit object(T & object);
     
-    std::string json() const { return to_json_(ptr_); }
+    Json::Value json() const { return to_json_(ptr_); }
     
   private:
     friend std::ostream & operator<<(std::ostream & os, object const & obj) {
       return os << obj.to_string_(obj.ptr_);
     }
     template <typename> static std::string to_string_impl(void * ptr);
-    template <typename> static std::string to_json_impl(void * ptr);
+    template <typename> static Json::Value to_json_impl(void * ptr);
 
   private:
     void * ptr_;
     std::string (*to_string_)(void*);
-    std::string (*to_json_)(void*);
+    Json::Value (*to_json_)(void*);
   };
   
   
@@ -40,7 +40,7 @@ namespace logging { namespace detail {
   }
 
   template <typename T>
-  std::string object::to_json_impl(void * ptr) {
+  Json::Value object::to_json_impl(void * ptr) {
     return to_json(*static_cast<T*>(ptr));
   }
 

+ 24 - 0
logger.xcodeproj/project.pbxproj

@@ -27,6 +27,8 @@
 		CD760CBF226221F6008A62DE /* console_appender_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD760CBE226221F6008A62DE /* console_appender_test.cxx */; };
 		CD760CC1226226CC008A62DE /* file_appender_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD760CC0226226CC008A62DE /* file_appender_test.cxx */; };
 		CD760CC922627202008A62DE /* json_layout_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD760CC822627202008A62DE /* json_layout_test.cxx */; };
+		CD760CD122628A63008A62DE /* libjsoncpp.1.8.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD760CCE226288AB008A62DE /* libjsoncpp.1.8.4.dylib */; };
+		CD760CD222628A73008A62DE /* libjsoncpp.1.8.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD760CCE226288AB008A62DE /* libjsoncpp.1.8.4.dylib */; };
 		CD88E9572252BDFC00927F40 /* log_manager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD88E9552252BDFC00927F40 /* log_manager.cxx */; };
 		CD88E95F2252D3EF00927F40 /* c_logger.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD88E95D2252D3EF00927F40 /* c_logger.cxx */; };
 		CD88E9632252D67A00927F40 /* common.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD88E9612252D67A00927F40 /* common.cxx */; };
@@ -99,6 +101,7 @@
 		CD760CBE226221F6008A62DE /* console_appender_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = console_appender_test.cxx; sourceTree = "<group>"; };
 		CD760CC0226226CC008A62DE /* file_appender_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = file_appender_test.cxx; sourceTree = "<group>"; };
 		CD760CC822627202008A62DE /* json_layout_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = json_layout_test.cxx; sourceTree = "<group>"; };
+		CD760CCE226288AB008A62DE /* libjsoncpp.1.8.4.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libjsoncpp.1.8.4.dylib; path = ../../../../../../../../opt/local/lib/libjsoncpp.1.8.4.dylib; sourceTree = "<group>"; };
 		CD88E9552252BDFC00927F40 /* log_manager.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = log_manager.cxx; sourceTree = "<group>"; };
 		CD88E95D2252D3EF00927F40 /* c_logger.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = c_logger.cxx; sourceTree = "<group>"; };
 		CD88E9612252D67A00927F40 /* common.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = common.cxx; sourceTree = "<group>"; };
@@ -112,6 +115,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CD760CD122628A63008A62DE /* libjsoncpp.1.8.4.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -119,6 +123,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CD760CD222628A73008A62DE /* libjsoncpp.1.8.4.dylib in Frameworks */,
 				CD6F7406225187F40081ED74 /* liblogging.dylib in Frameworks */,
 				CD6F746C22518A2C0081ED74 /* GoogleMock.framework in Frameworks */,
 			);
@@ -206,6 +211,7 @@
 		CD6F742B225188600081ED74 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				CD760CCE226288AB008A62DE /* libjsoncpp.1.8.4.dylib */,
 				CD6F746B22518A2C0081ED74 /* GoogleMock.framework */,
 				CD6F742F225189470081ED74 /* GoogleMock.xcodeproj */,
 				CD6F742D225189290081ED74 /* libcfmt_logger.dylib */,
@@ -434,6 +440,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = /opt/local/include/;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
 				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include/ $(PROJECT_DIR)/extern/expect/include/ $(PROJECT_DIR)/extern/resource_factory/include/ $(PROJECT_DIR)/extern/scoped_buffer_capture/include/ $(PROJECT_DIR)/extern/";
@@ -469,6 +476,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = /opt/local/include/;
 				SDKROOT = macosx;
 				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include/ $(PROJECT_DIR)/extern/expect/include/ $(PROJECT_DIR)/extern/resource_factory/include/ $(PROJECT_DIR)/extern/scoped_buffer_capture/include/ $(PROJECT_DIR)/extern/";
 			};
@@ -515,6 +523,10 @@
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					/opt/local/lib,
+				);
 				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -559,6 +571,10 @@
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					/opt/local/lib,
+				);
 				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -596,6 +612,10 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				INFOPLIST_FILE = logger_test/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					/opt/local/lib,
+				);
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
@@ -633,6 +653,10 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				INFOPLIST_FILE = logger_test/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					/opt/local/lib,
+				);
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;

+ 1 - 1
src/format.cxx

@@ -165,7 +165,7 @@ namespace logging {
     return ss.str();
   }
   
-  std::string message::json() const {
+  Json::Value message::json() const {
     return objects[0].json();
   }
 }

+ 24 - 62
src/loggers/json_layout.cxx

@@ -5,8 +5,13 @@
 //  Created by Sam Jaffe on 4/7/19.
 //
 
+#include <iterator>
+#include <regex>
+
+#include <json/json.h>
 #include "resource_factory/prototype_factory.hpp"
 
+#include "common.h"
 #include "logger/detail/layout.h"
 #include "logger/log_manager.h"
 #include "logger/logpacket.h"
@@ -22,19 +27,8 @@ public:
   void format(std::ostream & os, logpacket const & pkt) const override;
   
 private:
-  bool compact_, eol_, log_as_json_;
-};
-
-struct json_writer {
-  json_writer(std::ostream & os, bool compact);
-  void write_indent();
-  void write_key(std::string const & key);
-  void write_timestamp(struct timeval time);
-  
-  std::ostream & os;
-  bool write_whitespace;
-  int indent;
-  std::string div;
+  Json::StreamWriterBuilder build;
+  bool eol_, log_as_json_;
 };
 
 using namespace logging::property;
@@ -54,61 +48,29 @@ std::shared_ptr<layout> json_layout::create(properties const & props) {
 }
 
 json_layout::json_layout(properties const & props)
-: compact_(props["compact"]),
-  eol_(props["eventEol"]),
-  log_as_json_(props["objectMessageAsJsonObject"]) {
-  
-}
-
-json_writer::json_writer(std::ostream & os, bool compact)
-: os(os), write_whitespace(!compact), indent(1),
-  div(compact ? "" : " ") {
-}
-
-void json_writer::write_indent() {
-  if (!write_whitespace) return;
-  os << NEWLINE_TOKEN;
-  for (int i = 0; i < indent; ++i) {
-    os << "  ";
-  }
-}
-
-void json_writer::write_key(std::string const & key) {
-  write_indent();
-  os << '"' << key << '"' << ':' << div;
-}
-
-void json_writer::write_timestamp(struct timeval time) {
-  write_key("instant");
-  os << '{';
-  ++indent;
-  write_key("epochSecond");
-  os << time.tv_sec << ",";
-  write_key("nanoOfSecond");
-  os << (time.tv_usec * 1000);
-  --indent;
-  write_indent();
-  os << '}';
+: eol_(props["eventEol"]),
+  log_as_json_(props["objectMessageAsJsonObject"])
+{
+  build["indentation"] = props["compact"] ? "" : "  ";
 }
 
 void json_layout::format(std::ostream & os, logpacket const & pkt) const {
-  json_writer writer(os, compact_);
-  os << '{';
-  writer.write_timestamp(pkt.time);
-  os << ',';
-  writer.write_key("level");
-  os << "\"" << pkt.level << "\",";
-  writer.write_key("loggerName");
-  os << "\"" << pkt.logger << "\",";
-  writer.write_key("message");
+  Json::Value root;
+  root["instant"]["epochSecond"] = (Json::UInt64) pkt.time.tv_sec;
+  root["instant"]["nanoOfSecond"] = pkt.time.tv_usec * 1000;
+  root["level"] = level_to_string(pkt.level);
+  root["loggerName"] = pkt.logger;
   if (log_as_json_) {
-    os << pkt.message.json();
+    root["message"] = pkt.message.json();
   } else {
-    os << "\"" << pkt.message.str() << "\"";
+    root["message"] = pkt.message.str();
   }
-  --writer.indent;
-  writer.write_indent();
-  os << '}';
+  std::string data = Json::writeString(build, root);
+  // jsoncpp is dumb and writes a newline after each ':' token if
+  // the child is an object or array.
+  std::regex_replace(std::ostreambuf_iterator<char>(os),
+                     data.begin(), data.end(),
+                     std::regex(": \n(  )*(\\{|\\[)"), ": $2");
   if (eol_) {
     os << NEWLINE_TOKEN;
   }

+ 24 - 21
test/json_layout_test.cxx

@@ -7,6 +7,7 @@
 
 #include <gmock/gmock.h>
 
+#include <json/json.h>
 #include "resource_factory/prototype_factory.hpp"
 
 #include "logger/detail/layout.h"
@@ -24,13 +25,13 @@ namespace {
 }
 
 std::string const formatted_output = R"({
-  "instant": {
-    "epochSecond": 1554401840,
-    "nanoOfSecond": 123456000
+  "instant" : {
+    "epochSecond" : 1554401840,
+    "nanoOfSecond" : 123456000
   },
-  "level": "warning",
-  "loggerName": "UnitTest",
-  "message": "This is a test message"
+  "level" : "warning",
+  "loggerName" : "UnitTest",
+  "message" : "This is a test message"
 })";
 
 std::string const compact_output = "{\"instant\":{\"epochSecond\":"
@@ -84,13 +85,13 @@ TEST(JsonLayoutTest, EOLPropertyAppendsNewline) {
 }
 
 std::string const struct_output = R"({
-  "instant": {
-    "epochSecond": 1554401840,
-    "nanoOfSecond": 123456000
+  "instant" : {
+    "epochSecond" : 1554401840,
+    "nanoOfSecond" : 123456000
   },
-  "level": "warning",
-  "loggerName": "UnitTest",
-  "message": "{225}"
+  "level" : "warning",
+  "loggerName" : "UnitTest",
+  "message" : "{225}"
 })";
 
 struct example {
@@ -101,14 +102,14 @@ std::ostream & operator<<(std::ostream & os, example const & ex) {
 }
 
 std::string const struct_json_output = R"({
-  "instant": {
-    "epochSecond": 1554401840,
-    "nanoOfSecond": 123456000
+  "instant" : {
+    "epochSecond" : 1554401840,
+    "nanoOfSecond" : 123456000
   },
-  "level": "warning",
-  "loggerName": "UnitTest",
-  "message": {
-    "content":225
+  "level" : "warning",
+  "loggerName" : "UnitTest",
+  "message" : {
+    "content" : 225
   }
 })";
 
@@ -118,8 +119,10 @@ struct json_example {
 std::ostream & operator<<(std::ostream & os, json_example const & ex) {
   return os << '{' << ex.content << '}';
 }
-std::string to_json(json_example const & ex) {
-  return "{\"content\":" + std::to_string(ex.content) + "}";
+Json::Value to_json(json_example const & ex) {
+  Json::Value json;
+  json["content"] = ex.content;
+  return json;
 }
 
 TEST(JsonLayoutTest, MessageCanBeLoggedAsJSON) {