浏览代码

Read from config to create loggers

Sam Jaffe 6 年之前
父节点
当前提交
bc8443eb8d
共有 5 个文件被更改,包括 81 次插入18 次删除
  1. 3 3
      include/logger/log_manager.h
  2. 4 0
      include/logger/properties.h
  3. 58 13
      src/log_manager.cxx
  4. 1 1
      src/loggers/file_logger.cxx
  5. 15 1
      src/loggers/properties.cxx

+ 3 - 3
include/logger/log_manager.h

@@ -29,13 +29,13 @@ namespace logging {
     c_logger c_get();
     c_logger c_get(std::string const & name);
 
-    void configure();
-    
+    void configure(properties const & props);
+
   private:
     manager();
     
   private:
-    std::unique_ptr<struct manager_impl> pimpl;
+    std::unique_ptr<struct manager_impl> pimpl_;
   };
   
   using impl_factory = objects::prototype::factory<

+ 4 - 0
include/logger/properties.h

@@ -14,6 +14,10 @@
 
 namespace logging {
   struct properties {
+    operator std::string const &() const;
+    properties const & operator[](std::size_t idx) const;
+    properties const & operator[](std::string const & key) const;
+
     const enum { STRING, OBJECT, ARRAY } type;
     const std::map<std::string, properties> obj;
     const std::vector<properties> array;

+ 58 - 13
src/log_manager.cxx

@@ -10,10 +10,12 @@
 #include <memory>
 #include <unordered_map>
 
+#include "../../../paradigm/declarative/expect/include/expect/expect.hpp"
 #include "../../../types/resource_factory/include/resource_factory/prototype_factory.hpp"
 
 #include "logger/c_logger.h"
 #include "logger/logger.h"
+#include "logger/logger_impl.h"
 #include "logger/properties.h"
 
 INSTANTIATE_PROTOTYPE_FACTORY_2(logging::impl_factory);
@@ -21,33 +23,76 @@ INSTANTIATE_PROTOTYPE_FACTORY_2(logging::impl_factory);
 using namespace logging;
 
 struct logging::manager_impl {
-  std::shared_ptr<logger_impl> get(std::string const & name) {
-    auto it = loggers.find(name);
-    if (it == loggers.end()) {
-      auto & factory = impl_factory::instance();
-      it = loggers.emplace(name, factory.get(name, {})).first;
-    }
-    return it->second;
-  }
+  std::shared_ptr<logger_impl> get_logger(properties const & props);
   
   std::shared_ptr<logger_impl> default_logger;
+  std::unordered_map<std::string, std::shared_ptr<logger_impl>> appenders;
   std::unordered_map<std::string, std::shared_ptr<logger_impl>> loggers;
 };
 
-manager::manager() : pimpl(new manager_impl) {}
+manager::manager() : pimpl_(new manager_impl) {}
 
 logger manager::get() {
-  return logger("", pimpl->default_logger);
+  return logger("", pimpl_->default_logger);
 }
 
 logger manager::get(std::string const & name) {
-  return logger(name, pimpl->get(name));
+  return logger(name, pimpl_->loggers.at(name));
 }
 
 c_logger manager::c_get() {
-  return c_logger("", pimpl->default_logger);
+  return c_logger("", pimpl_->default_logger);
 }
 
 c_logger manager::c_get(std::string const & name) {
-  return c_logger(name, pimpl->get(name));
+  return c_logger(name, pimpl_->loggers.at(name));
+}
+
+struct compound_logger : public logger_impl {
+  void write(logpacket const & pkt) override {
+    for (auto & log : values) { log->write(pkt); }
+  }
+  void write(log_level l, std::string const & msg) override {
+    for (auto & log : values) { log->write(l, msg); }
+  }
+  void flush() override {
+    for (auto & log : values) { log->flush(); }
+  }
+  std::vector<std::shared_ptr<logger_impl>> values;
+};
+
+std::shared_ptr<logger_impl>
+manager_impl::get_logger(properties const & props) {
+  auto & appends = props["appenders"];
+  if (appends.type == properties::OBJECT) {
+    // TODO include settings on the parent
+    return appenders.at(appends["ref"].value);
+  } else if (appends.type == properties::ARRAY) {
+    auto out = std::make_shared<compound_logger>();
+    for (auto & part : appends.array) {
+      out->values.push_back(get_logger(part));
+    }
+    return out;
+  } else {
+    throw;
+  }
+}
+
+
+void manager::configure(properties const & props) {
+  auto & factory = impl_factory::instance();
+  // TODO: Load logger_impl here
+  auto & impls = props["configuration"]["appenders"];
+  // TODO: Support multiple File loggers, etc.
+  expects(impls.type == properties::OBJECT);
+  for (auto & app : impls.obj) {
+    pimpl_->appenders.emplace(app.first, factory.get(app.first, app.second));
+  }
+  // TODO: root
+  auto & configs = props["configuration"]["loggers"];
+  expects(configs.type == properties::OBJECT);
+  for (auto & log : configs.obj) {
+    pimpl_->loggers.emplace(log.first, pimpl_->get_logger(log.second));
+  }
+  pimpl_->default_logger = pimpl_->get_logger(configs["root"]);
 }

+ 1 - 1
src/loggers/file_logger.cxx

@@ -29,7 +29,7 @@ private:
 };
 
 std::shared_ptr<logger_impl> file_logger::create(properties const&) {
-  return std::unique_ptr<logger_impl>(); // TODO
+  return std::shared_ptr<logger_impl>(); // TODO
 }
 
 file_logger::file_logger(const std::string& fname)

+ 15 - 1
src/loggers/properties.cxx

@@ -7,6 +7,8 @@
 
 #include "logger/properties.h"
 
+#include "../../../../paradigm/declarative/expect/include/expect/expect.hpp"
+
 /*
  {
  {"pattern",{{},"%d{%h:%M:%s.%_ms} [%t] %-5.5p %.36c - %m%n"}}
@@ -15,7 +17,6 @@
  }
  */
 namespace logging {
-  
   namespace {
     properties _property(std::map<std::string, properties> const& m) {
       return properties{properties::OBJECT, m, {}, {}};
@@ -77,4 +78,17 @@ namespace logging {
       {"Loggers",_list({LOGGER_DEFAULT_SCHEMA})}
     })
   };
+  
+  properties::operator std::string const &() const {
+    expects(type == STRING);
+    return value;
+  }
+  properties const & properties::operator[](std::size_t idx) const {
+    expects(type == ARRAY);
+    return array.at(idx);
+  }
+  properties const & properties::operator[](std::string const & key) const {
+    expects(type == OBJECT);
+    return obj.at(key);
+  }
 }