LoggingManager.cpp
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00022 //----------------------------------------------------------------------
00023 #include "icl_core_logging/LoggingManager.h"
00024 
00025 #include <assert.h>
00026 #include <iostream>
00027 #include <sstream>
00028 #include <cstdlib>
00029 
00030 #include <boost/lexical_cast.hpp>
00031 #include <boost/tuple/tuple.hpp>
00032 
00033 #include <icl_core/os_lxrt.h>
00034 #include <icl_core_config/Config.h>
00035 #include "icl_core_logging/FileLogOutput.h"
00036 #include "icl_core_logging/LogStream.h"
00037 #include "icl_core_logging/StdLogOutput.h"
00038 #include "icl_core_config/GetoptParser.h"
00039 #include "icl_core_config/GetoptParameter.h"
00040 
00041 namespace icl_core {
00042 namespace logging {
00043 
00044 void LoggingManager::initialize()
00045 {
00046   if (!m_initialized)
00047   {
00048     m_initialized = true;
00049 
00050     // Read the log output stream configuration.
00051     ::icl_core::config::ConfigIterator output_stream_it =
00052         ::icl_core::config::find("\\/IclCore\\/Logging\\/(OutputStream.*)\\/(.*)");
00053     while (output_stream_it.next())
00054     {
00055       ::icl_core::String entry_name = output_stream_it.matchGroup(1);
00056       ::icl_core::String value_name = output_stream_it.matchGroup(2);
00057       if (value_name == "OutputStreamName")
00058       {
00059         m_output_stream_config[entry_name].output_stream_name = output_stream_it.value();
00060       }
00061       else if (value_name == "Name")
00062       {
00063         m_output_stream_config[entry_name].name = output_stream_it.value();
00064       }
00065       else if (value_name == "LogLevel")
00066       {
00067         if (!stringToLogLevel(output_stream_it.value(), m_output_stream_config[entry_name].log_level))
00068         {
00069           std::cerr << "LOGGING CONFIG ERROR: Illegal log level in " << output_stream_it.key() << std::endl;
00070         }
00071       }
00072       else if (value_name.substr(0, 9) == "LogStream")
00073       {
00074         m_output_stream_config[entry_name].log_streams.push_back(output_stream_it.value());
00075       }
00076     }
00077 
00078     // Read the log stream configuration.
00079     ::icl_core::config::ConfigIterator log_stream_it =
00080         ::icl_core::config::find("\\/IclCore\\/Logging\\/(LogStream.*)\\/(.*)");
00081     while (log_stream_it.next())
00082     {
00083       ::icl_core::String entry_name = log_stream_it.matchGroup(1);
00084       ::icl_core::String value_name = log_stream_it.matchGroup(2);
00085       if (value_name == "Name")
00086       {
00087         m_log_stream_config[entry_name].name = log_stream_it.value();
00088       }
00089       else if (value_name == "LogLevel")
00090       {
00091         if (!stringToLogLevel(log_stream_it.value(), m_log_stream_config[entry_name].log_level))
00092         {
00093           std::cerr << "LOGGING CONFIG ERROR: Illegal log level in " << log_stream_it.key() << std::endl;
00094         }
00095       }
00096     }
00097   }
00098 
00099   configure();
00100 
00101   // Configure the "QuickDebug" log stream and log output stream.
00102   icl_core::String quick_debug_filename;
00103   if (icl_core::config::paramOpt<icl_core::String>("quick-debug", quick_debug_filename))
00104   {
00105     // Find an unused name for the QuickDebug[0-9]* log output stream.
00106     icl_core::String output_stream_name = "QuickDebug";
00107     LogOutputStreamMap::const_iterator find_it = m_log_output_streams.find(output_stream_name);
00108     if (find_it != m_log_output_streams.end())
00109     {
00110       size_t count = 0;
00111       do
00112       {
00113         ++count;
00114         find_it = m_log_output_streams.find(output_stream_name
00115                                             + boost::lexical_cast<icl_core::String>(count));
00116       }
00117       while (find_it != m_log_output_streams.end());
00118       output_stream_name = output_stream_name + boost::lexical_cast<icl_core::String>(count);
00119     }
00120 
00121     // Create the log output stream and connect the log stream.
00122     LogOutputStream *output_stream = new FileLogOutput(output_stream_name, quick_debug_filename,
00123                                                        eLL_TRACE, true);
00124     m_log_output_streams[output_stream_name] = output_stream;
00125     QuickDebug::instance().addOutputStream(output_stream);
00126     QuickDebug::instance().m_initial_level = eLL_TRACE;
00127   }
00128 
00129   // Run the log output stream threads.
00130   if (m_default_log_output != 0)
00131   {
00132     m_default_log_output->start();
00133   }
00134   for (LogOutputStreamMap::iterator output_stream_it = m_log_output_streams.begin();
00135        output_stream_it != m_log_output_streams.end();
00136        ++output_stream_it)
00137   {
00138     output_stream_it->second->start();
00139   }
00140 }
00141 
00142 void LoggingManager::configure()
00143 {
00144   // Create the default log output stream, if necessary.
00145   if (m_output_stream_config.empty() && m_default_log_output == NULL)
00146   {
00147     m_default_log_output = StdLogOutput::create("Default", "/IclCore/Logging/Default");
00148   }
00149 
00150   // Create log stream instances, if necessary.
00151   for (LogStreamFactoryMap::iterator log_stream_it = m_log_stream_factories.begin();
00152        log_stream_it != m_log_stream_factories.end(); ++log_stream_it)
00153   {
00154     if (m_log_streams.find(log_stream_it->first) == m_log_streams.end())
00155     {
00156       registerLogStream((*log_stream_it->second)());
00157     }
00158   }
00159 
00160   // Delete the default log output stream, if necessary.
00161   if (!m_output_stream_config.empty() && m_default_log_output != NULL)
00162   {
00163     for (LogStreamMap::iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
00164     {
00165       it->second->removeOutputStream(m_default_log_output);
00166     }
00167 
00168     m_default_log_output->shutdown();
00169     delete m_default_log_output;
00170     m_default_log_output = 0;
00171   }
00172 
00173   // Run through the log output stream configuration
00174   for (LogOutputStreamConfigMap::iterator loc_it = m_output_stream_config.begin();
00175        loc_it != m_output_stream_config.end(); ++loc_it)
00176   {
00177     // Auto-generate a suitable name for the log output stream, if it
00178     // has not been set in the configuration.
00179     if (loc_it->second.name == ::icl_core::String())
00180     {
00181       loc_it->second.name = loc_it->second.output_stream_name;
00182     }
00183 
00184     // Create the configured log output stream, if necessary.
00185     LogOutputStreamMap::const_iterator find_log_output_stream =
00186       m_log_output_streams.find(loc_it->second.name);
00187     if (find_log_output_stream == m_log_output_streams.end())
00188     {
00189       LogOutputStreamFactoryMap::const_iterator find_log_output_stream_factory =
00190         m_log_output_stream_factories.find(loc_it->second.output_stream_name);
00191       if (find_log_output_stream_factory == m_log_output_stream_factories.end())
00192       {
00193         // If the log output stream cannot be created then skip to the
00194         // next configuration entry.
00195         continue;
00196       }
00197       LogOutputStream *log_output_stream =
00198         (*find_log_output_stream_factory->second)(loc_it->second.name,
00199                                                   "/IclCore/Logging/" + loc_it->first,
00200                                                   loc_it->second.log_level);
00201       boost::tuples::tie(find_log_output_stream, boost::tuples::ignore) =
00202         m_log_output_streams.insert(std::make_pair(loc_it->second.name, log_output_stream));
00203     }
00204 
00205     // Check again, just to be sure!
00206     if (find_log_output_stream != m_log_output_streams.end())
00207     {
00208       // Connect the configured log streams (either the list from the
00209       // commandline or all available log streams).
00210       if (loc_it->second.log_streams.empty())
00211       {
00212         for (LogStreamMap::iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
00213         {
00214           it->second->addOutputStream(find_log_output_stream->second);
00215         }
00216       }
00217       else
00218       {
00219         for (StringList::const_iterator it = loc_it->second.log_streams.begin();
00220              it != loc_it->second.log_streams.end(); ++it)
00221         {
00222           LogStreamMap::iterator find_it = m_log_streams.find(*it);
00223           if (find_it == m_log_streams.end())
00224           {
00225             // If the log stream cannot be found then skip to the next
00226             // entry.  Maybe there will be a second call to configure()
00227             // in the future and the log stream is available then.
00228             continue;
00229           }
00230           else
00231           {
00232             find_it->second->addOutputStream(find_log_output_stream->second);
00233           }
00234         }
00235       }
00236     }
00237   }
00238 
00239   // Set the log level of the configured log streams (either the list
00240   // from the commandline or all available log streams).
00241   for (LogStreamConfigMap::const_iterator lsc_it = m_log_stream_config.begin();
00242        lsc_it != m_log_stream_config.end(); ++lsc_it)
00243   {
00244     LogStreamMap::iterator find_it = m_log_streams.find(lsc_it->second.name);
00245     if (find_it == m_log_streams.end())
00246     {
00247       // If the log stream cannot be found then skip to the next
00248       // entry.  Maybe there will be a second call to configure() in
00249       // the future and the log stream is available then.
00250       continue;
00251     }
00252     else
00253     {
00254       find_it->second->m_initial_level = lsc_it->second.log_level;
00255     }
00256   }
00257 
00258 
00259   if (icl_core::config::Getopt::instance().paramOptPresent("log-level"))
00260   {
00261     LogLevel initial_level = cDEFAULT_LOG_LEVEL;
00262     icl_core::String log_level = icl_core::config::Getopt::instance().paramOpt("log-level");
00263     if (!stringToLogLevel(log_level, initial_level))
00264     {
00265       std::cerr << "Illegal log level " << log_level << std::endl;
00266       std::cerr << "Valid levels are 'Trace', 'Debug', 'Info', 'Warning', 'Error' and 'Mute'." << std::endl;
00267     }
00268     else
00269     {
00270       if (m_default_log_output == NULL)
00271       {
00272         m_default_log_output = StdLogOutput::create("Default", "/IclCore/Logging/Default");
00273       }
00274       m_default_log_output->setLogLevel(initial_level);
00275 
00276       for (LogStreamMap::iterator lsm_it = m_log_streams.begin(); lsm_it != m_log_streams.end(); ++lsm_it)
00277       {
00278         lsm_it->second->m_initial_level = initial_level;
00279         lsm_it->second->addOutputStream(m_default_log_output);
00280       }
00281 
00282       for (LogOutputStreamMap::iterator los_it = m_log_output_streams.begin(); los_it
00283              != m_log_output_streams.end(); ++los_it)
00284       {
00285         los_it->second->setLogLevel(initial_level);
00286       }
00287     }
00288   }
00289 }
00290 
00291 void LoggingManager::setLogLevel(icl_core::logging::LogLevel log_level)
00292 {
00293   for (LogStreamMap::iterator lsm_it = m_log_streams.begin(); lsm_it != m_log_streams.end(); ++lsm_it)
00294   {
00295     lsm_it->second->m_initial_level = log_level;
00296   }
00297 
00298   for (LogOutputStreamMap::iterator los_it = m_log_output_streams.begin();
00299        los_it != m_log_output_streams.end(); ++los_it)
00300   {
00301     los_it->second->setLogLevel(log_level);
00302   }
00303 }
00304 
00305 void LoggingManager::assertInitialized() const
00306 {
00307   if (!initialized())
00308   {
00309     assert(0);
00310   }
00311 }
00312 
00313 void LoggingManager::registerLogOutputStream(const ::icl_core::String& name, LogOutputStreamFactory factory)
00314 {
00315   m_log_output_stream_factories[name] = factory;
00316 }
00317 
00318 void LoggingManager::removeLogOutputStream(LogOutputStream *log_output_stream, bool remove_from_list)
00319 {
00320   for (LogStreamMap::iterator log_stream_it = m_log_streams.begin();
00321        log_stream_it != m_log_streams.end();
00322        ++log_stream_it)
00323   {
00324     log_stream_it->second->removeOutputStream(log_output_stream);
00325   }
00326 
00327   if (remove_from_list)
00328   {
00329     m_log_output_streams.erase(log_output_stream->name());
00330   }
00331 }
00332 
00333 void LoggingManager::registerLogStream(const icl_core::String& name, LogStreamFactory factory)
00334 {
00335   m_log_stream_factories[name] = factory;
00336 }
00337 
00338 void LoggingManager::registerLogStream(LogStream *log_stream)
00339 {
00340   m_log_streams[log_stream->name()] = log_stream;
00341 
00342   if (m_default_log_output != 0)
00343   {
00344     log_stream->addOutputStream(m_default_log_output);
00345   }
00346 }
00347 
00348 void LoggingManager::removeLogStream(const icl_core::String& log_stream_name)
00349 {
00350   if (!m_shutdown_running)
00351   {
00352     m_log_streams.erase(log_stream_name);
00353   }
00354 }
00355 
00356 LoggingManager::LoggingManager()
00357 {
00358   m_initialized = false;
00359   m_shutdown_running = false;
00360   m_default_log_output = NULL;
00361 
00362   icl_core::String help_text =
00363     "Override the log level of all streams and connect them to stdout. "
00364     "Possible values are 'Trace', 'Debug', 'Info', 'Warning', 'Error' and 'Mute'.";
00365   icl_core::config::addParameter(icl_core::config::GetoptParameter("log-level:", "l", help_text));
00366   icl_core::config::addParameter(icl_core::config::GetoptParameter(
00367                                    "quick-debug:", "qd",
00368                                    "Activate the QuickDebug log stream and write it "
00369                                    "to the specified file."));
00370 }
00371 
00372 LoggingManager::~LoggingManager()
00373 {
00374   shutdown();
00375 }
00376 
00377 void LoggingManager::printConfiguration() const
00378 {
00379   std::cerr << "LoggingManager configuration:" << std::endl;
00380 
00381   std::cerr << "  Log output stream factories:" << std::endl;
00382   for (LogOutputStreamFactoryMap::const_iterator it = m_log_output_stream_factories.begin();
00383        it != m_log_output_stream_factories.end(); ++it)
00384   {
00385     std::cerr << "    " << it->first << std::endl;
00386   }
00387 
00388   std::cerr << "  Log output streams:" << std::endl;
00389   if (m_default_log_output)
00390   {
00391     m_default_log_output->printConfiguration();
00392   }
00393   for (LogOutputStreamMap::const_iterator it = m_log_output_streams.begin();
00394        it != m_log_output_streams.end(); ++it)
00395   {
00396     it->second->printConfiguration();
00397   }
00398 
00399   std::cerr << "  Log streams:" << std::endl;
00400   for (LogStreamMap::const_iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
00401   {
00402     std::cerr << "    " << it->first << " -> ";
00403     it->second->printConfiguration();
00404     std::cerr << std::endl;
00405   }
00406 }
00407 
00408 void LoggingManager::changeLogFormat(const ::icl_core::String& name, const char *format)
00409 {
00410   for (LogOutputStreamMap::const_iterator it = m_log_output_streams.begin();
00411        it != m_log_output_streams.end(); ++it)
00412   {
00413     if (it->first == name)
00414     {
00415       it->second->changeLogFormat(format);
00416     }
00417   }
00418 }
00419 
00420 void LoggingManager::shutdown()
00421 {
00422   m_initialized = false;
00423   m_shutdown_running = true;
00424 
00425   // If the default log output stream exists then remove it from all connected
00426   // log streams and delete it afterwards.
00427   if (m_default_log_output != 0)
00428   {
00429     removeLogOutputStream(m_default_log_output, false);
00430     m_default_log_output->shutdown();
00431     delete m_default_log_output;
00432     m_default_log_output = 0;
00433   }
00434 
00435   // Remove all log output streams from all connected log streams and delete
00436   // the output streams afterwards.
00437   for (LogOutputStreamMap::iterator output_stream_it = m_log_output_streams.begin();
00438        output_stream_it != m_log_output_streams.end();
00439        ++output_stream_it)
00440   {
00441     removeLogOutputStream(output_stream_it->second, false);
00442     output_stream_it->second->shutdown();
00443     delete output_stream_it->second;
00444   }
00445 
00446   // Clear the log output stream map.
00447   m_log_output_streams.clear();
00448 
00449   // Delete all log streams.
00450   for (LogStreamMap::iterator log_stream_it = m_log_streams.begin();
00451        log_stream_it != m_log_streams.end();
00452        ++log_stream_it)
00453   {
00454     delete log_stream_it->second;
00455   }
00456 
00457   // Clear the log stream map.
00458   m_log_streams.clear();
00459 
00460   m_shutdown_running = false;
00461 }
00462 
00464 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00465 
00466   LoggingManager& LoggingManager::Instance()
00467   {
00468     return instance();
00469   }
00470 
00474   void LoggingManager::Configure()
00475   {
00476     configure();
00477   }
00478 
00482   void LoggingManager::Initialize()
00483   {
00484     initialize();
00485   }
00486 
00490   bool LoggingManager::Initialized() const
00491   {
00492     return initialized();
00493   }
00494 
00498   void LoggingManager::AssertInitialized() const
00499   {
00500     assertInitialized();
00501   }
00502 
00506   void LoggingManager::RegisterLogOutputStream(const icl_core::String& name,
00507                                                LogOutputStreamFactory factory)
00508   {
00509     registerLogOutputStream(name, factory);
00510   }
00511 
00515   void LoggingManager::RemoveLogOutputStream(LogOutputStream *log_output_stream,
00516                                              bool remove_from_list)
00517   {
00518     removeLogOutputStream(log_output_stream, remove_from_list);
00519   }
00520 
00524   void LoggingManager::RegisterLogStream(const icl_core::String& name,
00525                                          LogStreamFactory factory)
00526   {
00527     registerLogStream(name, factory);
00528   }
00529 
00533   void LoggingManager::RegisterLogStream(LogStream *log_stream)
00534   {
00535     registerLogStream(log_stream);
00536   }
00537 
00541   void LoggingManager::RemoveLogStream(const icl_core::String& log_stream_name)
00542   {
00543     removeLogStream(log_stream_name);
00544   }
00545 
00549   void LoggingManager::PrintConfiguration() const
00550   {
00551     printConfiguration();
00552   }
00553 
00557   void LoggingManager::ChangeLogFormat(const icl_core::String& name,
00558                                        const char *format)
00559   {
00560     changeLogFormat(name, format);
00561   }
00562 
00566   void LoggingManager::Shutdown()
00567   {
00568     shutdown();
00569   }
00570 
00571 #endif
00572 
00573 
00574 namespace hidden {
00575 
00576   LogOutputStreamRegistrar::LogOutputStreamRegistrar(const ::icl_core::String& name,
00577                                                      LogOutputStreamFactory factory)
00578   {
00579     LoggingManager::instance().registerLogOutputStream(name, factory);
00580   }
00581 
00582   LogStreamRegistrar::LogStreamRegistrar(const ::icl_core::String& name, LogStreamFactory factory)
00583   {
00584     LoggingManager::instance().registerLogStream(name, factory);
00585   }
00586 
00587 }
00588 
00589 LifeCycle::LifeCycle(int &argc, char *argv[])
00590 {
00591   icl_core::config::initialize(argc, argv, icl_core::config::Getopt::eCLC_Cleanup, icl_core::config::Getopt::ePRC_Relaxed);
00592   LoggingManager::instance().initialize();
00593 }
00594 
00595 LifeCycle::~LifeCycle()
00596 {
00597   LoggingManager::instance().shutdown();
00598 }
00599 
00600 }
00601 }


fzi_icl_core
Author(s):
autogenerated on Tue Aug 8 2017 02:28:03