|
|
@@ -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"]);
|
|
|
}
|