00001
00002
00009
00010 #include "icl_core_logging/LoggingManager.h"
00011
00012 #include <assert.h>
00013 #include <iostream>
00014 #include <sstream>
00015 #include <cstdlib>
00016
00017 #include <boost/lexical_cast.hpp>
00018 #include <boost/tuple/tuple.hpp>
00019
00020 #include <icl_core/os_lxrt.h>
00021 #include <icl_core_config/Config.h>
00022 #include "icl_core_logging/FileLogOutput.h"
00023 #include "icl_core_logging/LogStream.h"
00024 #include "icl_core_logging/StdLogOutput.h"
00025 #include "icl_core_config/GetoptParser.h"
00026 #include "icl_core_config/GetoptParameter.h"
00027
00028 namespace icl_core {
00029 namespace logging {
00030
00031 void LoggingManager::initialize()
00032 {
00033 if (!m_initialized)
00034 {
00035 m_initialized = true;
00036
00037
00038 ::icl_core::config::ConfigIterator output_stream_it =
00039 ::icl_core::config::find("\\/IclCore\\/Logging\\/(OutputStream.*)\\/(.*)");
00040 while (output_stream_it.next())
00041 {
00042 ::icl_core::String entry_name = output_stream_it.matchGroup(1);
00043 ::icl_core::String value_name = output_stream_it.matchGroup(2);
00044 if (value_name == "OutputStreamName")
00045 {
00046 m_output_stream_config[entry_name].output_stream_name = output_stream_it.value();
00047 }
00048 else if (value_name == "Name")
00049 {
00050 m_output_stream_config[entry_name].name = output_stream_it.value();
00051 }
00052 else if (value_name == "LogLevel")
00053 {
00054 if (!stringToLogLevel(output_stream_it.value(), m_output_stream_config[entry_name].log_level))
00055 {
00056 std::cerr << "LOGGING CONFIG ERROR: Illegal log level in " << output_stream_it.key() << std::endl;
00057 }
00058 }
00059 else if (value_name.substr(0, 9) == "LogStream")
00060 {
00061 m_output_stream_config[entry_name].log_streams.push_back(output_stream_it.value());
00062 }
00063 }
00064
00065
00066 ::icl_core::config::ConfigIterator log_stream_it =
00067 ::icl_core::config::find("\\/IclCore\\/Logging\\/(LogStream.*)\\/(.*)");
00068 while (log_stream_it.next())
00069 {
00070 ::icl_core::String entry_name = log_stream_it.matchGroup(1);
00071 ::icl_core::String value_name = log_stream_it.matchGroup(2);
00072 if (value_name == "Name")
00073 {
00074 m_log_stream_config[entry_name].name = log_stream_it.value();
00075 }
00076 else if (value_name == "LogLevel")
00077 {
00078 if (!stringToLogLevel(log_stream_it.value(), m_log_stream_config[entry_name].log_level))
00079 {
00080 std::cerr << "LOGGING CONFIG ERROR: Illegal log level in " << log_stream_it.key() << std::endl;
00081 }
00082 }
00083 }
00084 }
00085
00086 configure();
00087
00088
00089 icl_core::String quick_debug_filename;
00090 if (icl_core::config::paramOpt<icl_core::String>("quick-debug", quick_debug_filename))
00091 {
00092
00093 icl_core::String output_stream_name = "QuickDebug";
00094 LogOutputStreamMap::const_iterator find_it = m_log_output_streams.find(output_stream_name);
00095 if (find_it != m_log_output_streams.end())
00096 {
00097 size_t count = 0;
00098 do
00099 {
00100 ++count;
00101 find_it = m_log_output_streams.find(output_stream_name
00102 + boost::lexical_cast<icl_core::String>(count));
00103 }
00104 while (find_it != m_log_output_streams.end());
00105 output_stream_name = output_stream_name + boost::lexical_cast<icl_core::String>(count);
00106 }
00107
00108
00109 LogOutputStream *output_stream = new FileLogOutput(output_stream_name, quick_debug_filename,
00110 eLL_TRACE, true);
00111 m_log_output_streams[output_stream_name] = output_stream;
00112 QuickDebug::instance().addOutputStream(output_stream);
00113 QuickDebug::instance().m_initial_level = eLL_TRACE;
00114 }
00115
00116
00117 if (m_default_log_output != 0)
00118 {
00119 m_default_log_output->start();
00120 }
00121 for (LogOutputStreamMap::iterator output_stream_it = m_log_output_streams.begin();
00122 output_stream_it != m_log_output_streams.end();
00123 ++output_stream_it)
00124 {
00125 output_stream_it->second->start();
00126 }
00127 }
00128
00129 void LoggingManager::configure()
00130 {
00131
00132 if (m_output_stream_config.empty() && m_default_log_output == NULL)
00133 {
00134 m_default_log_output = StdLogOutput::create("Default", "/IclCore/Logging/Default");
00135 }
00136
00137
00138 for (LogStreamFactoryMap::iterator log_stream_it = m_log_stream_factories.begin();
00139 log_stream_it != m_log_stream_factories.end(); ++log_stream_it)
00140 {
00141 if (m_log_streams.find(log_stream_it->first) == m_log_streams.end())
00142 {
00143 registerLogStream((*log_stream_it->second)());
00144 }
00145 }
00146
00147
00148 if (!m_output_stream_config.empty() && m_default_log_output != NULL)
00149 {
00150 for (LogStreamMap::iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
00151 {
00152 it->second->removeOutputStream(m_default_log_output);
00153 }
00154
00155 m_default_log_output->shutdown();
00156 delete m_default_log_output;
00157 m_default_log_output = 0;
00158 }
00159
00160
00161 for (LogOutputStreamConfigMap::iterator loc_it = m_output_stream_config.begin();
00162 loc_it != m_output_stream_config.end(); ++loc_it)
00163 {
00164
00165
00166 if (loc_it->second.name == ::icl_core::String())
00167 {
00168 loc_it->second.name = loc_it->second.output_stream_name;
00169 }
00170
00171
00172 LogOutputStreamMap::const_iterator find_log_output_stream =
00173 m_log_output_streams.find(loc_it->second.name);
00174 if (find_log_output_stream == m_log_output_streams.end())
00175 {
00176 LogOutputStreamFactoryMap::const_iterator find_log_output_stream_factory =
00177 m_log_output_stream_factories.find(loc_it->second.output_stream_name);
00178 if (find_log_output_stream_factory == m_log_output_stream_factories.end())
00179 {
00180
00181
00182 continue;
00183 }
00184 LogOutputStream *log_output_stream =
00185 (*find_log_output_stream_factory->second)(loc_it->second.name,
00186 "/IclCore/Logging/" + loc_it->first,
00187 loc_it->second.log_level);
00188 boost::tuples::tie(find_log_output_stream, boost::tuples::ignore) =
00189 m_log_output_streams.insert(std::make_pair(loc_it->second.name, log_output_stream));
00190 }
00191
00192
00193 if (find_log_output_stream != m_log_output_streams.end())
00194 {
00195
00196
00197 if (loc_it->second.log_streams.empty())
00198 {
00199 for (LogStreamMap::iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
00200 {
00201 it->second->addOutputStream(find_log_output_stream->second);
00202 }
00203 }
00204 else
00205 {
00206 for (StringList::const_iterator it = loc_it->second.log_streams.begin();
00207 it != loc_it->second.log_streams.end(); ++it)
00208 {
00209 LogStreamMap::iterator find_it = m_log_streams.find(*it);
00210 if (find_it == m_log_streams.end())
00211 {
00212
00213
00214
00215 continue;
00216 }
00217 else
00218 {
00219 find_it->second->addOutputStream(find_log_output_stream->second);
00220 }
00221 }
00222 }
00223 }
00224 }
00225
00226
00227
00228 for (LogStreamConfigMap::const_iterator lsc_it = m_log_stream_config.begin();
00229 lsc_it != m_log_stream_config.end(); ++lsc_it)
00230 {
00231 LogStreamMap::iterator find_it = m_log_streams.find(lsc_it->second.name);
00232 if (find_it == m_log_streams.end())
00233 {
00234
00235
00236
00237 continue;
00238 }
00239 else
00240 {
00241 find_it->second->m_initial_level = lsc_it->second.log_level;
00242 }
00243 }
00244
00245
00246 if (icl_core::config::Getopt::instance().paramOptPresent("log-level"))
00247 {
00248 LogLevel initial_level = cDEFAULT_LOG_LEVEL;
00249 icl_core::String log_level = icl_core::config::Getopt::instance().paramOpt("log-level");
00250 if (!stringToLogLevel(log_level, initial_level))
00251 {
00252 std::cerr << "Illegal log level " << log_level << std::endl;
00253 std::cerr << "Valid levels are 'Trace', 'Debug', 'Info', 'Warning', 'Error' and 'Mute'." << std::endl;
00254 }
00255 else
00256 {
00257 if (m_default_log_output == NULL)
00258 {
00259 m_default_log_output = StdLogOutput::create("Default", "/IclCore/Logging/Default");
00260 }
00261 m_default_log_output->setLogLevel(initial_level);
00262
00263 for (LogStreamMap::iterator lsm_it = m_log_streams.begin(); lsm_it != m_log_streams.end(); ++lsm_it)
00264 {
00265 lsm_it->second->m_initial_level = initial_level;
00266 lsm_it->second->addOutputStream(m_default_log_output);
00267 }
00268
00269 for (LogOutputStreamMap::iterator los_it = m_log_output_streams.begin(); los_it
00270 != m_log_output_streams.end(); ++los_it)
00271 {
00272 los_it->second->setLogLevel(initial_level);
00273 }
00274 }
00275 }
00276 }
00277
00278 void LoggingManager::assertInitialized() const
00279 {
00280 if (!initialized())
00281 {
00282 assert(0);
00283 }
00284 }
00285
00286 void LoggingManager::registerLogOutputStream(const ::icl_core::String& name, LogOutputStreamFactory factory)
00287 {
00288 m_log_output_stream_factories[name] = factory;
00289 }
00290
00291 void LoggingManager::removeLogOutputStream(LogOutputStream *log_output_stream, bool remove_from_list)
00292 {
00293 for (LogStreamMap::iterator log_stream_it = m_log_streams.begin();
00294 log_stream_it != m_log_streams.end();
00295 ++log_stream_it)
00296 {
00297 log_stream_it->second->removeOutputStream(log_output_stream);
00298 }
00299
00300 if (remove_from_list)
00301 {
00302 m_log_output_streams.erase(log_output_stream->name());
00303 }
00304 }
00305
00306 void LoggingManager::registerLogStream(const icl_core::String& name, LogStreamFactory factory)
00307 {
00308 m_log_stream_factories[name] = factory;
00309 }
00310
00311 void LoggingManager::registerLogStream(LogStream *log_stream)
00312 {
00313 m_log_streams[log_stream->name()] = log_stream;
00314
00315 if (m_default_log_output != 0)
00316 {
00317 log_stream->addOutputStream(m_default_log_output);
00318 }
00319 }
00320
00321 void LoggingManager::removeLogStream(const icl_core::String& log_stream_name)
00322 {
00323 if (!m_shutdown_running)
00324 {
00325 m_log_streams.erase(log_stream_name);
00326 }
00327 }
00328
00329 LoggingManager::LoggingManager()
00330 {
00331 m_initialized = false;
00332 m_shutdown_running = false;
00333 m_default_log_output = NULL;
00334
00335 icl_core::String help_text =
00336 "Override the log level of all streams and connect them to stdout. "
00337 "Possible values are 'Trace', 'Debug', 'Info', 'Warning', 'Error' and 'Mute'.";
00338 icl_core::config::addParameter(icl_core::config::GetoptParameter("log-level:", "l", help_text));
00339 icl_core::config::addParameter(icl_core::config::GetoptParameter(
00340 "quick-debug:", "qd",
00341 "Activate the QuickDebug log stream and write it "
00342 "to the specified file."));
00343 }
00344
00345 LoggingManager::~LoggingManager()
00346 {
00347 shutdown();
00348 }
00349
00350 void LoggingManager::printConfiguration() const
00351 {
00352 std::cerr << "LoggingManager configuration:" << std::endl;
00353
00354 std::cerr << " Log output stream factories:" << std::endl;
00355 for (LogOutputStreamFactoryMap::const_iterator it = m_log_output_stream_factories.begin();
00356 it != m_log_output_stream_factories.end(); ++it)
00357 {
00358 std::cerr << " " << it->first << std::endl;
00359 }
00360
00361 std::cerr << " Log output streams:" << std::endl;
00362 if (m_default_log_output)
00363 {
00364 m_default_log_output->printConfiguration();
00365 }
00366 for (LogOutputStreamMap::const_iterator it = m_log_output_streams.begin();
00367 it != m_log_output_streams.end(); ++it)
00368 {
00369 it->second->printConfiguration();
00370 }
00371
00372 std::cerr << " Log streams:" << std::endl;
00373 for (LogStreamMap::const_iterator it = m_log_streams.begin(); it != m_log_streams.end(); ++it)
00374 {
00375 std::cerr << " " << it->first << " -> ";
00376 it->second->printConfiguration();
00377 std::cerr << std::endl;
00378 }
00379 }
00380
00381 void LoggingManager::changeLogFormat(const ::icl_core::String& name, const char *format)
00382 {
00383 for (LogOutputStreamMap::const_iterator it = m_log_output_streams.begin();
00384 it != m_log_output_streams.end(); ++it)
00385 {
00386 if (it->first == name)
00387 {
00388 it->second->changeLogFormat(format);
00389 }
00390 }
00391 }
00392
00393 void LoggingManager::shutdown()
00394 {
00395 m_initialized = false;
00396 m_shutdown_running = true;
00397
00398
00399
00400 if (m_default_log_output != 0)
00401 {
00402 removeLogOutputStream(m_default_log_output, false);
00403 m_default_log_output->shutdown();
00404 delete m_default_log_output;
00405 m_default_log_output = 0;
00406 }
00407
00408
00409
00410 for (LogOutputStreamMap::iterator output_stream_it = m_log_output_streams.begin();
00411 output_stream_it != m_log_output_streams.end();
00412 ++output_stream_it)
00413 {
00414 removeLogOutputStream(output_stream_it->second, false);
00415 output_stream_it->second->shutdown();
00416 delete output_stream_it->second;
00417 }
00418
00419
00420 m_log_output_streams.clear();
00421
00422
00423 for (LogStreamMap::iterator log_stream_it = m_log_streams.begin();
00424 log_stream_it != m_log_streams.end();
00425 ++log_stream_it)
00426 {
00427 delete log_stream_it->second;
00428 }
00429
00430
00431 m_log_streams.clear();
00432
00433 m_shutdown_running = false;
00434 }
00435
00437 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00438
00439 LoggingManager& LoggingManager::Instance()
00440 {
00441 return instance();
00442 }
00443
00447 void LoggingManager::Configure()
00448 {
00449 configure();
00450 }
00451
00455 void LoggingManager::Initialize()
00456 {
00457 initialize();
00458 }
00459
00463 bool LoggingManager::Initialized() const
00464 {
00465 return initialized();
00466 }
00467
00471 void LoggingManager::AssertInitialized() const
00472 {
00473 assertInitialized();
00474 }
00475
00479 void LoggingManager::RegisterLogOutputStream(const icl_core::String& name,
00480 LogOutputStreamFactory factory)
00481 {
00482 registerLogOutputStream(name, factory);
00483 }
00484
00488 void LoggingManager::RemoveLogOutputStream(LogOutputStream *log_output_stream,
00489 bool remove_from_list)
00490 {
00491 removeLogOutputStream(log_output_stream, remove_from_list);
00492 }
00493
00497 void LoggingManager::RegisterLogStream(const icl_core::String& name,
00498 LogStreamFactory factory)
00499 {
00500 registerLogStream(name, factory);
00501 }
00502
00506 void LoggingManager::RegisterLogStream(LogStream *log_stream)
00507 {
00508 registerLogStream(log_stream);
00509 }
00510
00514 void LoggingManager::RemoveLogStream(const icl_core::String& log_stream_name)
00515 {
00516 removeLogStream(log_stream_name);
00517 }
00518
00522 void LoggingManager::PrintConfiguration() const
00523 {
00524 printConfiguration();
00525 }
00526
00530 void LoggingManager::ChangeLogFormat(const icl_core::String& name,
00531 const char *format)
00532 {
00533 changeLogFormat(name, format);
00534 }
00535
00539 void LoggingManager::Shutdown()
00540 {
00541 shutdown();
00542 }
00543
00544 #endif
00545
00546
00547 namespace hidden {
00548
00549 LogOutputStreamRegistrar::LogOutputStreamRegistrar(const ::icl_core::String& name,
00550 LogOutputStreamFactory factory)
00551 {
00552 LoggingManager::instance().registerLogOutputStream(name, factory);
00553 }
00554
00555 LogStreamRegistrar::LogStreamRegistrar(const ::icl_core::String& name, LogStreamFactory factory)
00556 {
00557 LoggingManager::instance().registerLogStream(name, factory);
00558 }
00559
00560 }
00561
00562 LifeCycle::LifeCycle(int &argc, char *argv[])
00563 {
00564 icl_core::config::initialize(argc, argv, icl_core::config::Getopt::eCLC_Cleanup, icl_core::config::Getopt::ePRC_Relaxed);
00565 LoggingManager::instance().initialize();
00566 }
00567
00568 LifeCycle::~LifeCycle()
00569 {
00570 LoggingManager::instance().shutdown();
00571 }
00572
00573 }
00574 }