فهرست منبع

Import file_logger prototype and console_logger.

Sam Jaffe 6 سال پیش
والد
کامیت
844d2dc685

+ 2 - 1
include/logger/log_manager.h

@@ -18,6 +18,7 @@ namespace logging {
   class c_logger;
   class logger;
   class logger_impl;
+  class properties;
   
   class manager {
   public:
@@ -38,5 +39,5 @@ namespace logging {
   };
   
   using impl_factory = objects::prototype::factory<
-      std::shared_ptr<logger_impl>>;
+      std::shared_ptr<logger_impl>, properties const &>;
 }

+ 1 - 0
include/logger/logger_impl.h

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

+ 22 - 0
include/logger/properties.h

@@ -0,0 +1,22 @@
+//
+//  properties.hpp
+//  logger
+//
+//  Created by Sam Jaffe on 10/3/15.
+//
+//
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace logging {
+  struct properties {
+    const enum { STRING, OBJECT, ARRAY } type;
+    const std::map<std::string, properties> obj;
+    const std::vector<properties> array;
+    const std::string value;
+  };
+}

+ 20 - 0
logger.xcodeproj/project.pbxproj

@@ -7,6 +7,9 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		CD1CDE872252E5B900E5B6B2 /* properties.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1CDE862252E5B900E5B6B2 /* properties.cxx */; };
+		CD1CDE892252E60900E5B6B2 /* file_logger.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1CDE882252E60900E5B6B2 /* file_logger.cxx */; };
+		CD1CDE8B2252E61800E5B6B2 /* console_logger.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1CDE8A2252E61800E5B6B2 /* console_logger.cxx */; };
 		CD29739B1D7B401F00E37217 /* logger.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD2973991D7B401F00E37217 /* logger.cxx */; };
 		CD3C80C01D6A2CA300ACC795 /* format.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD3C80BE1D6A2CA300ACC795 /* format.cxx */; };
 		CD6F73EC225187BE0081ED74 /* logger in Headers */ = {isa = PBXBuildFile; fileRef = CD6F73EA225187A10081ED74 /* logger */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -59,6 +62,9 @@
 /* Begin PBXFileReference section */
 		0EB833481BBF45E600DDC844 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
 		0ECAC4AF1BC00AC500FDAE14 /* liblogging.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = liblogging.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD1CDE862252E5B900E5B6B2 /* properties.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = properties.cxx; sourceTree = "<group>"; };
+		CD1CDE882252E60900E5B6B2 /* file_logger.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = file_logger.cxx; sourceTree = "<group>"; };
+		CD1CDE8A2252E61800E5B6B2 /* console_logger.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = console_logger.cxx; sourceTree = "<group>"; };
 		CD2973991D7B401F00E37217 /* logger.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logger.cxx; sourceTree = "<group>"; };
 		CD3C80BE1D6A2CA300ACC795 /* format.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = format.cxx; sourceTree = "<group>"; };
 		CD6F73EA225187A10081ED74 /* logger */ = {isa = PBXFileReference; lastKnownFileType = folder; name = logger; path = include/logger; sourceTree = "<group>"; };
@@ -116,9 +122,20 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
+		CD1CDE812252E54100E5B6B2 /* loggers */ = {
+			isa = PBXGroup;
+			children = (
+				CD1CDE862252E5B900E5B6B2 /* properties.cxx */,
+				CD1CDE882252E60900E5B6B2 /* file_logger.cxx */,
+				CD1CDE8A2252E61800E5B6B2 /* console_logger.cxx */,
+			);
+			path = loggers;
+			sourceTree = "<group>";
+		};
 		CD2973971D7B3FC600E37217 /* src */ = {
 			isa = PBXGroup;
 			children = (
+				CD1CDE812252E54100E5B6B2 /* loggers */,
 				CD2973991D7B401F00E37217 /* logger.cxx */,
 				CD88E9642252D6C700927F40 /* common.h */,
 				CD88E9612252D67A00927F40 /* common.cxx */,
@@ -307,6 +324,9 @@
 				CD88E9572252BDFC00927F40 /* log_manager.cxx in Sources */,
 				CD3C80C01D6A2CA300ACC795 /* format.cxx in Sources */,
 				CD88E95F2252D3EF00927F40 /* c_logger.cxx in Sources */,
+				CD1CDE872252E5B900E5B6B2 /* properties.cxx in Sources */,
+				CD1CDE8B2252E61800E5B6B2 /* console_logger.cxx in Sources */,
+				CD1CDE892252E60900E5B6B2 /* file_logger.cxx in Sources */,
 				CD88E9632252D67A00927F40 /* common.cxx in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 4 - 2
src/log_manager.cxx

@@ -10,9 +10,11 @@
 #include <memory>
 #include <unordered_map>
 
+#include "../../../types/resource_factory/include/resource_factory/prototype_factory.hpp"
+
 #include "logger/c_logger.h"
 #include "logger/logger.h"
-#include "../../../types/resource_factory/include/resource_factory/prototype_factory.hpp"
+#include "logger/properties.h"
 
 INSTANTIATE_PROTOTYPE_FACTORY_2(logging::impl_factory);
 
@@ -23,7 +25,7 @@ struct logging::manager_impl {
     auto it = loggers.find(name);
     if (it == loggers.end()) {
       auto & factory = impl_factory::instance();
-      it = loggers.emplace(name, factory.get(name)).first;
+      it = loggers.emplace(name, factory.get(name, {})).first;
     }
     return it->second;
   }

+ 69 - 0
src/loggers/console_logger.cxx

@@ -0,0 +1,69 @@
+//
+//  console_logger.cxx
+//  logging
+//
+//  Created by Sam Jaffe on 4/1/19.
+//
+
+#include <iostream>
+
+#include "../../../../paradigm/declarative/expect/include/expect/expect.hpp"
+#include "../../../../types/resource_factory/include/resource_factory/prototype_factory.hpp"
+
+#include "logger/log_manager.h"
+#include "logger/logger_impl.h"
+#include "logger/properties.h"
+
+using namespace logging;
+
+static std::string validate_or_throw(logging::properties const& props) {
+  expects(props.type == properties::OBJECT, "expected properties to be a map");
+  auto it = props.obj.find("target");
+  expects(it != props.obj.end(), "expected a console target entry");
+  expects(it->second.type == properties::STRING,
+          "expected properties[\"target\"] to be a string");
+  return it->second.value;
+}
+
+class console_logger : public logger_impl {
+public:
+  static std::shared_ptr<logger_impl> create(properties const& props);
+  
+  explicit console_logger(std::ostream& os);
+  
+  void write(logpacket const & pkt) override;
+  void write(log_level level, std::string const& msg) override;
+  
+  void flush() override;
+private:
+  std::ostream& out_;
+};
+
+std::shared_ptr<logger_impl> console_logger::create(properties const& props) {
+  const std::string target = validate_or_throw(props);
+  if (target == "SYSTEM_OUT") {
+    return std::make_shared<console_logger>(std::cout);
+  } else if (target == "SYSTEM_ERR") {
+    return std::make_shared<console_logger>(std::cerr);
+  } else {
+    throw std::logic_error{target + " is not a valid console"};
+  }
+}
+
+console_logger::console_logger(std::ostream& os) : out_(os) {}
+
+void console_logger::write(logpacket const & pkt) {
+  out_ << pkt.message;
+}
+
+void console_logger::write(log_level level, std::string const& msg) {
+  out_ << msg;
+}
+
+void console_logger::flush() {
+  out_.flush();
+}
+
+namespace {
+  bool _ = impl_factory::instance().bind("Console", console_logger::create);
+}

+ 48 - 0
src/loggers/file_logger.cxx

@@ -0,0 +1,48 @@
+//
+//  file_logger.cxx
+//  logging
+//
+//  Created by Sam Jaffe on 4/1/19.
+//
+
+#include <fstream>
+
+#include "../../../../paradigm/declarative/expect/include/expect/expect.hpp"
+#include "../../../../types/resource_factory/include/resource_factory/prototype_factory.hpp"
+
+#include "logger/log_manager.h"
+#include "logger/logger_impl.h"
+#include "logger/properties.h"
+
+using namespace logging;
+
+class file_logger : public logger_impl {
+public:
+  static std::shared_ptr<logger_impl> create(properties const&);
+  
+  explicit file_logger(const std::string& fname);
+  
+  void write(log_level level, std::string const& msg) override;
+  void flush() override;
+private:
+  std::ofstream out_;
+};
+
+std::shared_ptr<logger_impl> file_logger::create(properties const&) {
+  return std::unique_ptr<logger_impl>(); // TODO
+}
+
+file_logger::file_logger(const std::string& fname)
+: out_(fname) {}
+
+void file_logger::write(log_level level, std::string const& msg) {
+  out_ << msg;
+}
+
+void file_logger::flush() {
+  out_.flush();
+}
+
+namespace {
+  bool _ = impl_factory::instance().bind("File", file_logger::create);
+}

+ 80 - 0
src/loggers/properties.cxx

@@ -0,0 +1,80 @@
+//
+//  properties.cxx
+//  logging
+//
+//  Created by Sam Jaffe on 4/1/19.
+//
+
+#include "logger/properties.h"
+
+/*
+ {
+ {"pattern",{{},"%d{%h:%M:%s.%_ms} [%t] %-5.5p %.36c - %m%n"}}
+ },
+ "PatternLayout"
+ }
+ */
+namespace logging {
+  
+  namespace {
+    properties _property(std::map<std::string, properties> const& m) {
+      return properties{properties::OBJECT, m, {}, {}};
+    }
+    properties _list(std::vector<properties> const& l) {
+      return properties{properties::ARRAY, {}, l, {}};
+    }
+    properties _value(std::string const& s) {
+      return properties{properties::STRING, {}, {}, s};
+    }
+  }
+  
+  /*
+   * %d{%h:%M:%s.%_ms} [%t] %-5.5p %.36c - %m%n
+   *
+   * %d{fmt} := date(format)
+   * %t      := thread
+   * %-5.5p  := level (max 5char, align left)
+   * %.36c   := logsource (max 36char)
+   * %m      := log message
+   * %n      := platform-specific line separator
+   *
+   */
+  
+  properties const STDOUT_DEFAULT_SCHEMA{
+    _property({
+      {"type", _value("Console")},
+      {"name", _value("Console")},
+      {"target", _value("SYSTEM_OUT")},
+      {
+        "data", _list({
+          _property({
+            {"type", _value("PatternLayout")},
+            {"pattern", _value("%d{%h:%M:%s.%_ms} [%t] %-5.5p %.36c - %m%n")}
+          })
+        })
+      }
+    })
+  };
+  
+  properties const LOGGER_DEFAULT_SCHEMA {
+    _property({
+      {"type", _value("Root")},
+      {"level", _value("Error")},
+      {
+        "data", _list({
+          _property({
+            {"type", _value("AppenderRef")},
+            {"ref", _value("Console")}
+          })
+        })
+      }
+    })
+  };
+  
+  properties const DEFAULT_SCHEMA{
+    _property({
+      {"Appenders",_list({STDOUT_DEFAULT_SCHEMA})},
+      {"Loggers",_list({LOGGER_DEFAULT_SCHEMA})}
+    })
+  };
+}