RSC  0.19.0
LoggerFactory.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of RSC project
4  *
5  * Copyright (C) 2010 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  * Copyright (C) 2018 Jan Moringen <jmoringe@techfak.uni-bielefeld.de>
7  *
8  * This file may be licensed under the terms of the
9  * GNU Lesser General Public License Version 3 (the ``LGPL''),
10  * or (at your option) any later version.
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the LGPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the LGPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * The development of this software was supported by:
23  * CoR-Lab, Research Institute for Cognition and Robotics
24  * Bielefeld University
25  *
26  * ============================================================ */
27 
28 #include "LoggerFactory.h"
29 
30 #include <boost/bind.hpp>
31 #include <boost/filesystem/fstream.hpp>
32 #include <boost/format.hpp>
33 #include <boost/algorithm/string.hpp>
34 
35 #include "../runtime/ContainerIO.h"
36 #include "../config/ConfigFileSource.h"
37 
38 #include "LoggerProxy.h"
40 #include "LoggingSystemFactory.h"
41 
42 using namespace std;
43 
44 namespace rsc {
45 namespace logging {
46 
47 const string LoggerFactory::DEFAULT_LOGGING_SYSTEM = "console";
48 const Logger::Level LoggerFactory::DEFAULT_LEVEL = Logger::LEVEL_WARN;
49 
54 public:
55 
63  public:
64 
65  LevelSetter(const Logger::Level& level) :
66  level(level) {
67  }
68 
69  virtual ~LevelSetter() {
70  }
71 
72  bool visit(const LoggerTreeNode::NamePath& /*path*/,
73  LoggerTreeNodePtr node, const Logger::Level& /*parentLevel*/) {
74 
75  if (node->getAssignedLevel()) {
76  return false;
77  }
78 
79  node->getLoggerProxy()->getLogger()->setLevel(level);
80 
81  return true;
82 
83  }
84 
85  private:
87  };
88 
90  boost::recursive_mutex& mutex) :
91  treeNode(treeNode), mutex(mutex) {
92  }
93 
94  virtual ~TreeLevelUpdater() {
95  }
96 
97  // TODO jwienke: maybe it would be better to make this signature contain the node instead of the proxy? Can this work?
98  void call(LoggerProxyPtr /*proxy*/, const Logger::Level& level) {
99  boost::recursive_mutex::scoped_lock lock(mutex);
100  LoggerTreeNodePtr node = treeNode.lock();
101  node->getLoggerProxy()->getLogger()->setLevel(level);
102  node->setAssignedLevel(level);
103  // TODO we ignore the path anyways... Can this be done by the tree itself?
104  node->visit(LoggerTreeNode::VisitorPtr(new LevelSetter(level)),
106  }
107 
108 private:
110  boost::recursive_mutex& mutex;
111 
112 };
113 
114 LoggerFactory::LoggerFactory() {
115  reselectLoggingSystem();
116  loggerTree.reset(new LoggerTreeNode("", LoggerTreeNodePtr()));
117  LoggerPtr logger(loggingSystem->createLogger(""));
118  LoggerProxyPtr proxy(
119  new LoggerProxy(
120  logger,
122  new TreeLevelUpdater(
123  LoggerTreeNodeWeakPtr(loggerTree),
124  mutex))));
125  loggerTree->setLoggerProxy(proxy);
126  // assign the initial level to the only logger available, which is the root logger
127  // by directly assigning the level to the proxied logger we prevent the
128  // callback mechanism from working uselessly
129  logger->setLevel(DEFAULT_LEVEL);
130  loggerTree->setAssignedLevel(DEFAULT_LEVEL);
131 }
132 
133 LoggerFactory::~LoggerFactory() {
134 }
135 
137 public:
138 
139  ReselectVisitor(boost::shared_ptr<LoggingSystem> newSystem) :
140  newSystem(newSystem) {
141  }
142 
144  const Logger::Level& /*parentLevel*/) {
145  const Logger::Level oldLevel =
146  node->getLoggerProxy()->getLogger()->getLevel();
147  node->getLoggerProxy()->setLogger(
148  newSystem->createLogger(LoggerTreeNode::pathToName(path)));
149  node->getLoggerProxy()->getLogger()->setLevel(oldLevel);
150  return true;
151  }
152 private:
153  boost::shared_ptr<LoggingSystem> newSystem;
154 };
155 
156 void LoggerFactory::reselectLoggingSystem(const std::string& nameHint) {
157  std::string systemName
158  (nameHint.empty() ? DEFAULT_LOGGING_SYSTEM : nameHint);
159  LoggingSystemPtr system
160  (LoggingSystemFactory::getInstance().createInst(systemName));
161 
162  {
163  boost::recursive_mutex::scoped_lock lock(mutex);
164 
165  this->loggingSystem = system;
166 
167  // update existing loggers to use the new logging system
168  if (loggerTree) {
169  const Logger::Level oldLevel = loggerTree->getLoggerProxy()->getLevel();
170  loggerTree->getLoggerProxy()->setLogger(
171  loggingSystem->createLogger(""));
172  loggerTree->getLoggerProxy()->getLogger()->setLevel(oldLevel);
173  loggerTree->visit(
174  LoggerTreeNode::VisitorPtr(new ReselectVisitor(loggingSystem)));
175  }
176  }
177 }
178 
179 LoggerProxyPtr LoggerFactory::createLogger(const LoggerTreeNode::NamePath& path,
180  LoggerTreeNodePtr node) {
181  LoggerPtr logger(
182  loggingSystem->createLogger(LoggerTreeNode::pathToName(path)));
183  LoggerProxyPtr proxy(
184  new LoggerProxy(
185  logger,
188  mutex))));
189  // new level can be derived from parent logger
190  logger->setLevel(
191  node->getParent()->getLoggerProxy()->getLogger()->getLevel());
192  return proxy;
193 }
194 
195 LoggerPtr LoggerFactory::getLogger(const string& name) {
196  boost::recursive_mutex::scoped_lock lock(mutex);
197  LoggerTreeNode::NamePath path = LoggerTreeNode::nameToPath(name);
198  if (path.empty()) {
199  return loggerTree->getLoggerProxy();
200  }
201  LoggerTreeNodePtr node = loggerTree->addChildren(path,
202  boost::bind(&LoggerFactory::createLogger, this, _1, _2));
203  return node->getLoggerProxy();
204 }
205 
207 public:
208 
210  newLevel(newLevel) {
211  }
212 
214  const Logger::Level& /*parentLevel*/) {
215  if (node->hasAssignedLevel()) {
216  node->setAssignedLevel(newLevel);
217  }
218  node->getLoggerProxy()->getLogger()->setLevel(newLevel);
219  return true;
220 
221  }
222 private:
224 };
225 
226 void LoggerFactory::reconfigure(const Logger::Level& level) {
227  boost::recursive_mutex::scoped_lock lock(mutex);
228  loggerTree->getLoggerProxy()->getLogger()->setLevel(level);
229  loggerTree->setAssignedLevel(level);
230  loggerTree->visit(
232 }
233 
234 string LoggerFactory::getLoggingSystemName() {
235  boost::recursive_mutex::scoped_lock lock(mutex);
236  return this->loggingSystem->getName();
237 }
238 
239 void LoggerFactory::clearKnownLoggers() {
240  boost::recursive_mutex::scoped_lock lock(mutex);
241  loggerTree->clearChildren();
242 }
243 
244 void LoggerFactory::reconfigureFromFile(const string& fileName) {
245  OptionBasedConfigurator configurator;
246  boost::filesystem::ifstream stream(fileName);
247  if (!stream) {
248  throw invalid_argument("Unable to open file " + fileName);
249  }
250  config::ConfigFileSource(stream).provideOptions(configurator);
251 }
252 
253 }
254 }
boost::recursive_mutex & mutex
boost::shared_ptr< LoggerProxy > LoggerProxyPtr
Definition: LoggerProxy.h:112
Objects of this class parse streams that contain configuration information in "ini-file" syntax...
bool visit(const LoggerTreeNode::NamePath &path, LoggerTreeNodePtr node, const Logger::Level &)
Called for each node in the tree.
Visitor interface to operate on the tree.
bool visit(const LoggerTreeNode::NamePath &, LoggerTreeNodePtr node, const Logger::Level &)
Called for each node in the tree.
A simple tree representation for loggers.
void provideOptions(OptionHandler &handler)
Implementations should pass all configuration options to handler.
ReconfigurationVisitor(const Logger::Level &newLevel)
STL namespace.
A Visitor that propagates a logging level down the logger tree but stops if a logger already as a lev...
std::vector< std::string > NamePath
A unique representation of a name.
Level
Possible logging levels.
Definition: Logger.h:63
void call(LoggerProxyPtr, const Logger::Level &level)
boost::shared_ptr< LoggingSystem > newSystem
A proxy to an instance of Logger, which provides the same interface but allows to exchange the underl...
Definition: LoggerProxy.h:43
ReselectVisitor(boost::shared_ptr< LoggingSystem > newSystem)
LoggerPtr getLogger()
boost::shared_ptr< LoggingSystem > LoggingSystemPtr
Definition: LoggingSystem.h:73
bool visit(const LoggerTreeNode::NamePath &, LoggerTreeNodePtr node, const Logger::Level &)
Called for each node in the tree.
boost::shared_ptr< SetLevelCallback > SetLevelCallbackPtr
Definition: LoggerProxy.h:63
LoggerTreeNodeWeakPtr treeNode
boost::shared_ptr< LoggerTreeNode > LoggerTreeNodePtr
LevelSetter(const Logger::Level &level)
boost::shared_ptr< Visitor > VisitorPtr
TreeLevelUpdater(LoggerTreeNodeWeakPtr treeNode, boost::recursive_mutex &mutex)
Interface for callbacks which are invoked when someone calls setLevel on this proxy.
Definition: LoggerProxy.h:57
A class which configures the logging tree using configuration subsystem of RSC.
boost::weak_ptr< LoggerTreeNode > LoggerTreeNodeWeakPtr
boost::shared_ptr< Logger > LoggerPtr
Definition: Logger.h:41