• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

ibrcommon/ibrcommon/Logger.cpp

Go to the documentation of this file.
00001 /*
00002  * Logger.cpp
00003  *
00004  *  Created on: 08.06.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/Logger.h"
00009 #include "ibrcommon/SyslogStream.h"
00010 #include <algorithm>
00011 #include <sys/time.h>
00012 #include <ibrcommon/thread/Mutex.h>
00013 #include <ibrcommon/thread/MutexLock.h>
00014 #include <iomanip>
00015 
00016 
00017 namespace ibrcommon
00018 {
00019         std::list<Logger::LoggerOutput> Logger::_logger;
00020         ibrcommon::Queue<Logger> Logger::_queue;
00021         bool Logger::_use_queue = false;
00022         int Logger::_verbosity = 0;
00023         bool Logger::_syslog = 0;
00024         unsigned char Logger::_syslog_mask = 0;
00025         Logger::endl_flag Logger::endl;
00026 
00027         Logger::LogWriter Logger::_logwriter;
00028 
00029         Logger::Logger(LogLevel level, int debug_verbosity)
00030          : _level(level), _debug_verbosity(debug_verbosity)
00031         {
00032                 ::gettimeofday(&_logtime, NULL);
00033         }
00034 
00035         Logger::Logger(const Logger &obj)
00036          : std::stringstream(obj.str()), _level(obj._level), _debug_verbosity(obj._debug_verbosity), _logtime(obj._logtime)
00037         {
00038         }
00039 
00040         Logger::~Logger()
00041         {
00042         }
00043 
00044         Logger Logger::emergency()
00045         {
00046                 return Logger(LOGGER_EMERG);
00047         }
00048 
00049         Logger Logger::alert()
00050         {
00051                 return Logger(LOGGER_ALERT);
00052         }
00053 
00054         Logger Logger::critical()
00055         {
00056                 return Logger(LOGGER_CRIT);
00057         }
00058 
00059         Logger Logger::error()
00060         {
00061                 return Logger(LOGGER_ERR);
00062         }
00063 
00064         Logger Logger::warning()
00065         {
00066                 return Logger(LOGGER_WARNING);
00067         }
00068 
00069         Logger Logger::notice()
00070         {
00071                 return Logger(LOGGER_NOTICE);
00072         }
00073 
00074         Logger Logger::info()
00075         {
00076                 return Logger(LOGGER_INFO);
00077         }
00078 
00079         Logger Logger::debug(int verbosity)
00080         {
00081                 return Logger(LOGGER_DEBUG, verbosity);
00082         }
00083 
00084         void Logger::setVerbosity(const int verbosity)
00085         {
00086                 Logger::_verbosity = verbosity;
00087         }
00088 
00089         int Logger::getVerbosity()
00090         {
00091                 return Logger::_verbosity;
00092         }
00093 
00094         void Logger::addStream(std::ostream &stream, const unsigned char logmask, const unsigned char options)
00095         {
00096                 _logger.push_back( LoggerOutput(stream, logmask, options) );
00097         }
00098 
00099         void Logger::enableSyslog(const char *name, int option, int facility, const unsigned char logmask)
00100         {
00101                 // init syslog
00102                 ::openlog(name, option, facility);
00103                 Logger::_syslog = true;
00104                 Logger::_syslog_mask = logmask;
00105         }
00106 
00107         void Logger::flush()
00108         {
00109                 if (Logger::_verbosity >= _debug_verbosity)
00110                 {
00111                         for (std::list<LoggerOutput>::iterator iter = _logger.begin(); iter != _logger.end(); iter++)
00112                         {
00113                                 LoggerOutput &output = (*iter);
00114                                 output.log(*this);
00115                         }
00116 
00117                         // additionally log to the syslog
00118                         if (Logger::_syslog)
00119                         {
00120                                 if (_level & Logger::_syslog_mask)
00121                                 {
00122                                         switch (_level)
00123                                         {
00124                                         case LOGGER_EMERG:
00125                                                 ::syslog( LOG_EMERG, "%s", str().c_str() );
00126                                                 break;
00127 
00128                                         case LOGGER_ALERT:
00129                                                 ::syslog( LOG_ALERT, "%s", str().c_str() );
00130                                                 break;
00131 
00132                                         case LOGGER_CRIT:
00133                                                 ::syslog( LOG_CRIT, "%s", str().c_str() );
00134                                                 break;
00135 
00136                                         case LOGGER_ERR:
00137                                                 ::syslog( LOG_ERR, "%s", str().c_str() );
00138                                                 break;
00139 
00140                                         case LOGGER_WARNING:
00141                                                 ::syslog( LOG_WARNING, "%s", str().c_str() );
00142                                                 break;
00143 
00144                                         case LOGGER_NOTICE:
00145                                                 ::syslog( LOG_NOTICE, "%s", str().c_str() );
00146                                                 break;
00147 
00148                                         case LOGGER_INFO:
00149                                                 ::syslog( LOG_INFO, "%s", str().c_str() );
00150                                                 break;
00151 
00152                                         case LOGGER_DEBUG:
00153                                                 ::syslog( LOG_DEBUG, "%s", str().c_str() );
00154                                                 break;
00155 
00156                                         default:
00157                                                 ::syslog( LOG_NOTICE, "%s", str().c_str() );
00158                                                 break;
00159                                         }
00160                                 }
00161                         }
00162                 }
00163         }
00164 
00165         void Logger::LoggerOutput::log(const Logger &log)
00166         {
00167                 if (_level & log._level)
00168                 {
00169                         std::list<std::string> prefixes;
00170 
00171                         // check for prefixes
00172                         if (_options & LOG_DATETIME)
00173                         {
00174                                 // get timestamp
00175                                 time_t ltime; /* calendar time */
00176                                 ltime=time(NULL); /* get current cal time */
00177                                 std::string timestamp(asctime( localtime(&ltime) ));
00178                                 timestamp.erase(std::remove(timestamp.begin(), timestamp.end(), '\n'), timestamp.end());
00179                                 prefixes.push_back(timestamp);
00180                         }
00181 
00182                         // check for prefixes
00183                         if (_options & LOG_TIMESTAMP)
00184                         {
00185                                 std::stringstream ss;
00186                                 ss.fill('0');
00187                                 ss << log._logtime.tv_sec << "." << std::setw(6) << log._logtime.tv_usec;
00188                                 prefixes.push_back(ss.str());
00189                         }
00190 
00191                         if (_options & LOG_LEVEL)
00192                         {
00193                                 // print log level
00194                                 switch (log._level)
00195                                 {
00196                                         case LOGGER_EMERG:
00197                                                 prefixes.push_back("EMERGENCY");
00198                                                 break;
00199 
00200                                         case LOGGER_ALERT:
00201                                                 prefixes.push_back("ALERT");
00202                                                 break;
00203 
00204                                         case LOGGER_CRIT:
00205                                                 prefixes.push_back("CRTITICAL");
00206                                                 break;
00207 
00208                                         case LOGGER_ERR:
00209                                                 prefixes.push_back("ERROR");
00210                                                 break;
00211 
00212                                         case LOGGER_WARNING:
00213                                                 prefixes.push_back("WARNING");
00214                                                 break;
00215 
00216                                         case LOGGER_NOTICE:
00217                                                 prefixes.push_back("NOTICE");
00218                                                 break;
00219 
00220                                         case LOGGER_INFO:
00221                                                 prefixes.push_back("INFO");
00222                                                 break;
00223 
00224                                         case LOGGER_DEBUG:
00225                                         {
00226                                                 std::stringstream ss;
00227                                                 ss << "DEBUG." << log._debug_verbosity;
00228                                                 prefixes.push_back(ss.str());
00229                                                 break;
00230                                         }
00231 
00232                                         default:
00233                                                 break;
00234                                 }
00235                         }
00236 
00237                         if (_options & LOG_HOSTNAME)
00238                         {
00239                                 char *hostname_array = new char[64];
00240                                 if ( gethostname(hostname_array, 64) == 0 )
00241                                 {
00242                                         std::string hostname(hostname_array);
00243                                         prefixes.push_back(hostname);
00244                                 }
00245 
00246                                 delete[] hostname_array;
00247                         }
00248 
00249                         // print prefixes
00250                         for (std::list<std::string>::const_iterator iter = prefixes.begin(); iter != prefixes.end(); iter++)
00251                         {
00252                                 if (iter == prefixes.begin())
00253                                 {
00254                                         _stream << (*iter);
00255                                 }
00256                                 else
00257                                 {
00258                                         _stream << " " << (*iter);
00259                                 }
00260                         }
00261 
00262                         if (!prefixes.empty())
00263                         {
00264                                 _stream << ": ";
00265                         }
00266 
00267                         _stream << log.rdbuf() << std::endl;
00268                 }
00269         }
00270 
00271         Logger::LoggerOutput::LoggerOutput(std::ostream &stream, const unsigned char logmask, const unsigned char options)
00272          : _stream(stream), _level(logmask), _options(options)
00273         {
00274         }
00275 
00276         Logger::LoggerOutput::~LoggerOutput()
00277         {
00278         }
00279 
00280         void Logger::enableAsync()
00281         {
00282                 try {
00283                         _use_queue = true;
00284                         _logwriter.start();
00285                 } catch (const ibrcommon::ThreadException &ex) {
00286                         IBRCOMMON_LOGGER(error) << "failed to start LogWriter\n" << ex.what() << IBRCOMMON_LOGGER_ENDL;
00287                 }
00288         }
00289         
00290         void Logger::stop()
00291         {
00292                 // stop the LogWriter::run() thread (this is needed with uclibc)
00293                 _logwriter.stop();
00294         }
00295 
00296         Logger::LogWriter::LogWriter()
00297         {
00298         }
00299 
00300         Logger::LogWriter::~LogWriter()
00301         {
00302                 // do cleanup only if the thread was running before
00303                 if (!_use_queue) return;
00304 
00305                 // join the LogWriter::run() thread
00306                 join();
00307         }
00308 
00309         void Logger::LogWriter::run()
00310         {
00311                 try {
00312                         while (true)
00313                         {
00314                                 Logger log = Logger::_queue.getnpop(true);
00315                                 log.flush();
00316                         }
00317                 } catch (std::exception) {
00318                         ibrcommon::Queue<Logger>::Locked q = Logger::_queue.exclusive();
00319 
00320                         try {
00321                                 // In this block we will write all remaining element in the queue
00322                                 // to the logging streams. While we do this, the queue should be locked
00323                                 // and finally we abort the queue to unblock all waiting threads.
00324                                 while (!q.empty())
00325                                 {
00326                                         Logger &log = q.front();
00327                                         log.flush();
00328                                         q.pop();
00329                                 }
00330                         } catch (std::exception) { }
00331                 }
00332         }
00333 
00334         bool Logger::LogWriter::__cancellation()
00335         {
00336                 // cancel the main thread in here
00337                 Logger::_queue.abort();
00338 
00339                 // return true, to signal that no further cancel (the hardway) is needed
00340                 return true;
00341         }
00342 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1