LoggingManager.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
24 
25 #include <assert.h>
26 #include <iostream>
27 #include <sstream>
28 #include <cstdlib>
29 
30 #include <boost/lexical_cast.hpp>
31 #include <boost/tuple/tuple.hpp>
32 
33 #include <icl_core/os_lxrt.h>
34 #include <icl_core_config/Config.h>
40 
41 namespace icl_core {
42 namespace logging {
43 
45 {
46  if (!m_initialized)
47  {
48  m_initialized = true;
49 
50  // Read the log output stream configuration.
51  ::icl_core::config::ConfigIterator output_stream_it =
52  ::icl_core::config::find("\\/IclCore\\/Logging\\/(OutputStream.*)\\/(.*)");
53  while (output_stream_it.next())
54  {
55  ::icl_core::String entry_name = output_stream_it.matchGroup(1);
56  ::icl_core::String value_name = output_stream_it.matchGroup(2);
57  if (value_name == "OutputStreamName")
58  {
59  m_output_stream_config[entry_name].output_stream_name = output_stream_it.value();
60  }
61  else if (value_name == "Name")
62  {
63  m_output_stream_config[entry_name].name = output_stream_it.value();
64  }
65  else if (value_name == "LogLevel")
66  {
67  if (!stringToLogLevel(output_stream_it.value(), m_output_stream_config[entry_name].log_level))
68  {
69  std::cerr << "LOGGING CONFIG ERROR: Illegal log level in " << output_stream_it.key() << std::endl;
70  }
71  }
72  else if (value_name.substr(0, 9) == "LogStream")
73  {
74  m_output_stream_config[entry_name].log_streams.push_back(output_stream_it.value());
75  }
76  }
77 
78  // Read the log stream configuration.
80  ::icl_core::config::find("\\/IclCore\\/Logging\\/(LogStream.*)\\/(.*)");
81  while (log_stream_it.next())
82  {
83  ::icl_core::String entry_name = log_stream_it.matchGroup(1);
84  ::icl_core::String value_name = log_stream_it.matchGroup(2);
85  if (value_name == "Name")
86  {
87  m_log_stream_config[entry_name].name = log_stream_it.value();
88  }
89  else if (value_name == "LogLevel")
90  {
91  if (!stringToLogLevel(log_stream_it.value(), m_log_stream_config[entry_name].log_level))
92  {
93  std::cerr << "LOGGING CONFIG ERROR: Illegal log level in " << log_stream_it.key() << std::endl;
94  }
95  }
96  }
97  }
98 
99  configure();
100 
101  // Configure the "QuickDebug" log stream and log output stream.
102  icl_core::String quick_debug_filename;
103  if (icl_core::config::paramOpt<icl_core::String>("quick-debug", quick_debug_filename))
104  {
105  // Find an unused name for the QuickDebug[0-9]* log output stream.
106  icl_core::String output_stream_name = "QuickDebug";
107  LogOutputStreamMap::const_iterator find_it = m_log_output_streams.find(output_stream_name);
108  if (find_it != m_log_output_streams.end())
109  {
110  size_t count = 0;
111  do
112  {
113  ++count;
114  find_it = m_log_output_streams.find(output_stream_name
115  + boost::lexical_cast<icl_core::String>(count));
116  }
117  while (find_it != m_log_output_streams.end());
118  output_stream_name = output_stream_name + boost::lexical_cast<icl_core::String>(count);
119  }
120 
121  // Create the log output stream and connect the log stream.
122  LogOutputStream *output_stream = new FileLogOutput(output_stream_name, quick_debug_filename,
123  eLL_TRACE, true);
124  m_log_output_streams[output_stream_name] = output_stream;
125  QuickDebug::instance().addOutputStream(output_stream);
126  QuickDebug::instance().m_initial_level = eLL_TRACE;
127  }
128 
129  // Run the log output stream threads.
130  if (m_default_log_output != 0)
131  {
133  }
134  for (LogOutputStreamMap::iterator output_stream_it = m_log_output_streams.begin();
135  output_stream_it != m_log_output_streams.end();
136  ++output_stream_it)
137  {
138  output_stream_it->second->start();
139  }
140 }
141 
143 {
144  // Create the default log output stream, if necessary.
145  if (m_output_stream_config.empty() && m_default_log_output == NULL)
146  {
147  m_default_log_output = StdLogOutput::create("Default", "/IclCore/Logging/Default");
148  }
149 
150  // Create log stream instances, if necessary.
151  for (LogStreamFactoryMap::iterator log_stream_it = m_log_stream_factories.begin();
152  log_stream_it != m_log_stream_factories.end(); ++log_stream_it)
153  {
154  if (m_log_streams.find(log_stream_it->first) == m_log_streams.end())
155  {
156  registerLogStream((*log_stream_it->second)());
157  }
158  }
159 
160  // Delete the default log output stream, if necessary.
161  if (!m_output_stream_config.empty() && m_default_log_output != NULL)
162  {
163  for (LogStreamMap::iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
164  {
165  it->second->removeOutputStream(m_default_log_output);
166  }
167 
169  delete m_default_log_output;
171  }
172 
173  // Run through the log output stream configuration
174  for (LogOutputStreamConfigMap::iterator loc_it = m_output_stream_config.begin();
175  loc_it != m_output_stream_config.end(); ++loc_it)
176  {
177  // Auto-generate a suitable name for the log output stream, if it
178  // has not been set in the configuration.
179  if (loc_it->second.name == ::icl_core::String())
180  {
181  loc_it->second.name = loc_it->second.output_stream_name;
182  }
183 
184  // Create the configured log output stream, if necessary.
185  LogOutputStreamMap::const_iterator find_log_output_stream =
186  m_log_output_streams.find(loc_it->second.name);
187  if (find_log_output_stream == m_log_output_streams.end())
188  {
189  LogOutputStreamFactoryMap::const_iterator find_log_output_stream_factory =
190  m_log_output_stream_factories.find(loc_it->second.output_stream_name);
191  if (find_log_output_stream_factory == m_log_output_stream_factories.end())
192  {
193  // If the log output stream cannot be created then skip to the
194  // next configuration entry.
195  continue;
196  }
197  LogOutputStream *log_output_stream =
198  (*find_log_output_stream_factory->second)(loc_it->second.name,
199  "/IclCore/Logging/" + loc_it->first,
200  loc_it->second.log_level);
201  boost::tuples::tie(find_log_output_stream, boost::tuples::ignore) =
202  m_log_output_streams.insert(std::make_pair(loc_it->second.name, log_output_stream));
203  }
204 
205  // Check again, just to be sure!
206  if (find_log_output_stream != m_log_output_streams.end())
207  {
208  // Connect the configured log streams (either the list from the
209  // commandline or all available log streams).
210  if (loc_it->second.log_streams.empty())
211  {
212  for (LogStreamMap::iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
213  {
214  it->second->addOutputStream(find_log_output_stream->second);
215  }
216  }
217  else
218  {
219  for (StringList::const_iterator it = loc_it->second.log_streams.begin();
220  it != loc_it->second.log_streams.end(); ++it)
221  {
222  LogStreamMap::iterator find_it = m_log_streams.find(*it);
223  if (find_it == m_log_streams.end())
224  {
225  // If the log stream cannot be found then skip to the next
226  // entry. Maybe there will be a second call to configure()
227  // in the future and the log stream is available then.
228  continue;
229  }
230  else
231  {
232  find_it->second->addOutputStream(find_log_output_stream->second);
233  }
234  }
235  }
236  }
237  }
238 
239  // Set the log level of the configured log streams (either the list
240  // from the commandline or all available log streams).
241  for (LogStreamConfigMap::const_iterator lsc_it = m_log_stream_config.begin();
242  lsc_it != m_log_stream_config.end(); ++lsc_it)
243  {
244  LogStreamMap::iterator find_it = m_log_streams.find(lsc_it->second.name);
245  if (find_it == m_log_streams.end())
246  {
247  // If the log stream cannot be found then skip to the next
248  // entry. Maybe there will be a second call to configure() in
249  // the future and the log stream is available then.
250  continue;
251  }
252  else
253  {
254  find_it->second->m_initial_level = lsc_it->second.log_level;
255  }
256  }
257 
258 
260  {
261  LogLevel initial_level = cDEFAULT_LOG_LEVEL;
263  if (!stringToLogLevel(log_level, initial_level))
264  {
265  std::cerr << "Illegal log level " << log_level << std::endl;
266  std::cerr << "Valid levels are 'Trace', 'Debug', 'Info', 'Warning', 'Error' and 'Mute'." << std::endl;
267  }
268  else
269  {
270  if (m_default_log_output == NULL)
271  {
272  m_default_log_output = StdLogOutput::create("Default", "/IclCore/Logging/Default");
273  }
274  m_default_log_output->setLogLevel(initial_level);
275 
276  for (LogStreamMap::iterator lsm_it = m_log_streams.begin(); lsm_it != m_log_streams.end(); ++lsm_it)
277  {
278  lsm_it->second->m_initial_level = initial_level;
279  lsm_it->second->addOutputStream(m_default_log_output);
280  }
281 
282  for (LogOutputStreamMap::iterator los_it = m_log_output_streams.begin(); los_it
283  != m_log_output_streams.end(); ++los_it)
284  {
285  los_it->second->setLogLevel(initial_level);
286  }
287  }
288  }
289 }
290 
292 {
293  for (LogStreamMap::iterator lsm_it = m_log_streams.begin(); lsm_it != m_log_streams.end(); ++lsm_it)
294  {
295  lsm_it->second->m_initial_level = log_level;
296  }
297 
298  for (LogOutputStreamMap::iterator los_it = m_log_output_streams.begin();
299  los_it != m_log_output_streams.end(); ++los_it)
300  {
301  los_it->second->setLogLevel(log_level);
302  }
303 }
304 
306 {
307  if (!initialized())
308  {
309  assert(0);
310  }
311 }
312 
314 {
315  m_log_output_stream_factories[name] = factory;
316 }
317 
318 void LoggingManager::removeLogOutputStream(LogOutputStream *log_output_stream, bool remove_from_list)
319 {
320  for (LogStreamMap::iterator log_stream_it = m_log_streams.begin();
321  log_stream_it != m_log_streams.end();
322  ++log_stream_it)
323  {
324  log_stream_it->second->removeOutputStream(log_output_stream);
325  }
326 
327  if (remove_from_list)
328  {
329  m_log_output_streams.erase(log_output_stream->name());
330  }
331 }
332 
334 {
335  m_log_stream_factories[name] = factory;
336 }
337 
339 {
340  m_log_streams[log_stream->name()] = log_stream;
341 
342  if (m_default_log_output != 0)
343  {
345  }
346 }
347 
349 {
350  if (!m_shutdown_running)
351  {
352  m_log_streams.erase(log_stream_name);
353  }
354 }
355 
357 {
358  m_initialized = false;
359  m_shutdown_running = false;
360  m_default_log_output = NULL;
361 
362  icl_core::String help_text =
363  "Override the log level of all streams and connect them to stdout. "
364  "Possible values are 'Trace', 'Debug', 'Info', 'Warning', 'Error' and 'Mute'.";
367  "quick-debug:", "qd",
368  "Activate the QuickDebug log stream and write it "
369  "to the specified file."));
370 }
371 
373 {
374  shutdown();
375 }
376 
378 {
379  std::cerr << "LoggingManager configuration:" << std::endl;
380 
381  std::cerr << " Log output stream factories:" << std::endl;
382  for (LogOutputStreamFactoryMap::const_iterator it = m_log_output_stream_factories.begin();
383  it != m_log_output_stream_factories.end(); ++it)
384  {
385  std::cerr << " " << it->first << std::endl;
386  }
387 
388  std::cerr << " Log output streams:" << std::endl;
390  {
392  }
393  for (LogOutputStreamMap::const_iterator it = m_log_output_streams.begin();
394  it != m_log_output_streams.end(); ++it)
395  {
396  it->second->printConfiguration();
397  }
398 
399  std::cerr << " Log streams:" << std::endl;
400  for (LogStreamMap::const_iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
401  {
402  std::cerr << " " << it->first << " -> ";
403  it->second->printConfiguration();
404  std::cerr << std::endl;
405  }
406 }
407 
409 {
410  for (LogOutputStreamMap::const_iterator it = m_log_output_streams.begin();
411  it != m_log_output_streams.end(); ++it)
412  {
413  if (it->first == name)
414  {
415  it->second->changeLogFormat(format);
416  }
417  }
418 }
419 
421 {
422  m_initialized = false;
423  m_shutdown_running = true;
424 
425  // If the default log output stream exists then remove it from all connected
426  // log streams and delete it afterwards.
427  if (m_default_log_output != 0)
428  {
431  delete m_default_log_output;
433  }
434 
435  // Remove all log output streams from all connected log streams and delete
436  // the output streams afterwards.
437  for (LogOutputStreamMap::iterator output_stream_it = m_log_output_streams.begin();
438  output_stream_it != m_log_output_streams.end();
439  ++output_stream_it)
440  {
441  removeLogOutputStream(output_stream_it->second, false);
442  output_stream_it->second->shutdown();
443  delete output_stream_it->second;
444  }
445 
446  // Clear the log output stream map.
447  m_log_output_streams.clear();
448 
449  // Delete all log streams.
450  for (LogStreamMap::iterator log_stream_it = m_log_streams.begin();
451  log_stream_it != m_log_streams.end();
452  ++log_stream_it)
453  {
454  delete log_stream_it->second;
455  }
456 
457  // Clear the log stream map.
458  m_log_streams.clear();
459 
460  m_shutdown_running = false;
461 }
462 
464 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
465 
466  LoggingManager& LoggingManager::Instance()
467  {
468  return instance();
469  }
470 
474  void LoggingManager::Configure()
475  {
476  configure();
477  }
478 
483  {
484  initialize();
485  }
486 
490  bool LoggingManager::Initialized() const
491  {
492  return initialized();
493  }
494 
498  void LoggingManager::AssertInitialized() const
499  {
501  }
502 
506  void LoggingManager::RegisterLogOutputStream(const icl_core::String& name,
507  LogOutputStreamFactory factory)
508  {
509  registerLogOutputStream(name, factory);
510  }
511 
515  void LoggingManager::RemoveLogOutputStream(LogOutputStream *log_output_stream,
516  bool remove_from_list)
517  {
518  removeLogOutputStream(log_output_stream, remove_from_list);
519  }
520 
524  void LoggingManager::RegisterLogStream(const icl_core::String& name,
525  LogStreamFactory factory)
526  {
527  registerLogStream(name, factory);
528  }
529 
533  void LoggingManager::RegisterLogStream(LogStream *log_stream)
534  {
535  registerLogStream(log_stream);
536  }
537 
541  void LoggingManager::RemoveLogStream(const icl_core::String& log_stream_name)
542  {
543  removeLogStream(log_stream_name);
544  }
545 
549  void LoggingManager::PrintConfiguration() const
550  {
552  }
553 
557  void LoggingManager::ChangeLogFormat(const icl_core::String& name,
558  const char *format)
559  {
560  changeLogFormat(name, format);
561  }
562 
566  void LoggingManager::Shutdown()
567  {
568  shutdown();
569  }
570 
571 #endif
572 
574 namespace hidden {
575 
576  LogOutputStreamRegistrar::LogOutputStreamRegistrar(const ::icl_core::String& name,
577  LogOutputStreamFactory factory)
578  {
580  }
581 
582  LogStreamRegistrar::LogStreamRegistrar(const ::icl_core::String& name, LogStreamFactory factory)
583  {
585  }
586 
587 }
588 
589 LifeCycle::LifeCycle(int &argc, char *argv[])
590 {
593 }
594 
596 {
598 }
599 
600 }
601 }
LogOutputStreamFactoryMap m_log_output_stream_factories
bool initialize(int &argc, char *argv[], bool remove_read_arguments)
Definition: Config.cpp:50
LifeCycle(int &argc, char *argv[])
Contains icl_logging::LoggingManager.
Contains GetoptParameter.
LogStreamFactoryMap m_log_stream_factories
void setLogLevel(icl_core::logging::LogLevel log_level)
const LogLevel cDEFAULT_LOG_LEVEL
The log level which is used initially.
Definition: LogLevel.h:60
known command line options are removed
Definition: GetoptParser.h:67
Contains Getopt.
static LoggingManager & instance()
icl_core::String paramOpt(const icl_core::String &name) const
bool paramOptPresent(const icl_core::String &name) const
void start()
Starts the worker thread of the log output stream.
Base header file for the configuration framework.
Contains icl_logging::StdLogOutput.
void addOutputStream(LogOutputStream *new_stream)
Definition: LogStream.cpp:72
ICL_CORE_VC_DEPRECATE_STYLE bool Initialize(int &argc, char *argv[], bool remove_read_arguments) ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Config.h:902
bool stringToLogLevel(const std::string &log_level_text, LogLevel &log_level)
Definition: LogLevel.cpp:53
Manages the logging framework.
LogStream *(* LogStreamFactory)()
void removeLogOutputStream(LogOutputStream *log_output_stream, bool remove_from_list=true)
LogOutputStream *(* LogOutputStreamFactory)(const icl_core::String &name, const icl_core::String &config_prefix, LogLevel log_level)
LogOutputStream * m_default_log_output
Implements a thread-safe logging framework.
Definition: LogStream.h:54
ThreadStream & endl(ThreadStream &stream)
Definition: ThreadStream.h:249
ConfigIterator find(const ::icl_core::String &query)
Definition: Config.cpp:45
LogOutputStreamConfigMap m_output_stream_config
void addParameter(const ConfigParameter &parameter)
Definition: Config.h:541
LogOutputStreamMap m_log_output_streams
Contains global LXRT functions.
void setLogLevel(icl_core::logging::LogLevel log_level)
Set the log level globally for all existing streams.
String matchGroup(size_t index) const
void removeLogStream(const icl_core::String &log_stream_name)
This is an output stream class for log messages.
options not registered are ignored
Definition: GetoptParser.h:60
static LogOutputStream * create(const icl_core::String &name, const icl_core::String &config_prefix, icl_core::logging::LogLevel log_level=cDEFAULT_LOG_LEVEL)
void changeLogFormat(const icl_core::String &name, const char *format="~T ~S(~L)~ C~(O~::D: ~E")
std::string String
Definition: BaseTypes.h:43
Contains icl_logging::FileLogOutput.
Contains icl_logging::LogStream.
icl_core::String name() const
Return the name of the log stream.
Definition: LogStream.h:68
static Getopt & instance()
void registerLogStream(const icl_core::String &name, LogStreamFactory factory)
LogStreamConfigMap m_log_stream_config
ConvertToRef< T >::ToConstRef value() const
void registerLogOutputStream(const icl_core::String &name, LogOutputStreamFactory factory)
icl_core::String name() const


fzi_icl_core
Author(s):
autogenerated on Mon Jun 10 2019 13:17:58