00001
00002
00003
00004
00005
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 Logger::LogWriter Logger::_logwriter;
00020
00021 Logger::Logger(LogLevel level, int debug_verbosity)
00022 : _level(level), _debug_verbosity(debug_verbosity)
00023 {
00024 ::gettimeofday(&_logtime, NULL);
00025 }
00026
00027 Logger::Logger(const Logger &obj)
00028 : std::stringstream(obj.str()), _level(obj._level), _debug_verbosity(obj._debug_verbosity), _logtime(obj._logtime)
00029 {
00030 }
00031
00032 Logger::~Logger()
00033 {
00034 }
00035
00036 Logger Logger::emergency()
00037 {
00038 return Logger(LOGGER_EMERG);
00039 }
00040
00041 Logger Logger::alert()
00042 {
00043 return Logger(LOGGER_ALERT);
00044 }
00045
00046 Logger Logger::critical()
00047 {
00048 return Logger(LOGGER_CRIT);
00049 }
00050
00051 Logger Logger::error()
00052 {
00053 return Logger(LOGGER_ERR);
00054 }
00055
00056 Logger Logger::warning()
00057 {
00058 return Logger(LOGGER_WARNING);
00059 }
00060
00061 Logger Logger::notice()
00062 {
00063 return Logger(LOGGER_NOTICE);
00064 }
00065
00066 Logger Logger::info()
00067 {
00068 return Logger(LOGGER_INFO);
00069 }
00070
00071 Logger Logger::debug(int verbosity)
00072 {
00073 return Logger(LOGGER_DEBUG, verbosity);
00074 }
00075
00076 void Logger::setVerbosity(const int verbosity)
00077 {
00078 Logger::_logwriter.setVerbosity(verbosity);
00079 }
00080
00081 void Logger::LogWriter::setVerbosity(const int verbosity)
00082 {
00083 _verbosity = verbosity;
00084 }
00085
00086 int Logger::getVerbosity()
00087 {
00088 return Logger::_logwriter.getVerbosity();
00089 }
00090
00091 int Logger::LogWriter::getVerbosity()
00092 {
00093 return _verbosity;
00094 }
00095
00096 void Logger::addStream(std::ostream &stream, const unsigned char logmask, const unsigned char options)
00097 {
00098 Logger::_logwriter.addStream(stream, logmask, options);
00099 }
00100
00101 void Logger::LogWriter::addStream(std::ostream &stream, const unsigned char logmask, const unsigned char options)
00102 {
00103 _logger.push_back( Logger::LoggerOutput(stream, logmask, options) );
00104 }
00105
00106 void Logger::enableSyslog(const char *name, int option, int facility, const unsigned char logmask)
00107 {
00108 Logger::_logwriter.enableSyslog(name, option, facility, logmask);
00109 }
00110
00111 void Logger::print()
00112 {
00113 Logger::_logwriter.log(*this);
00114 }
00115
00116 void Logger::LogWriter::enableSyslog(const char *name, int option, int facility, const unsigned char logmask)
00117 {
00118
00119 ::openlog(name, option, facility);
00120 _syslog = true;
00121 _syslog_mask = logmask;
00122 }
00123
00124 void Logger::LogWriter::flush(const Logger &logger)
00125 {
00126 if (_verbosity >= logger._debug_verbosity)
00127 {
00128 for (std::list<LoggerOutput>::iterator iter = _logger.begin(); iter != _logger.end(); iter++)
00129 {
00130 LoggerOutput &output = (*iter);
00131 output.log(logger);
00132 }
00133
00134
00135 if (_syslog)
00136 {
00137 if (logger._level & _syslog_mask)
00138 {
00139 switch (logger._level)
00140 {
00141 case LOGGER_EMERG:
00142 ::syslog( LOG_EMERG, "%s", logger.str().c_str() );
00143 break;
00144
00145 case LOGGER_ALERT:
00146 ::syslog( LOG_ALERT, "%s", logger.str().c_str() );
00147 break;
00148
00149 case LOGGER_CRIT:
00150 ::syslog( LOG_CRIT, "%s", logger.str().c_str() );
00151 break;
00152
00153 case LOGGER_ERR:
00154 ::syslog( LOG_ERR, "%s", logger.str().c_str() );
00155 break;
00156
00157 case LOGGER_WARNING:
00158 ::syslog( LOG_WARNING, "%s", logger.str().c_str() );
00159 break;
00160
00161 case LOGGER_NOTICE:
00162 ::syslog( LOG_NOTICE, "%s", logger.str().c_str() );
00163 break;
00164
00165 case LOGGER_INFO:
00166 ::syslog( LOG_INFO, "%s", logger.str().c_str() );
00167 break;
00168
00169 case LOGGER_DEBUG:
00170 ::syslog( LOG_DEBUG, "%s", logger.str().c_str() );
00171 break;
00172
00173 default:
00174 ::syslog( LOG_NOTICE, "%s", logger.str().c_str() );
00175 break;
00176 }
00177 }
00178 }
00179 }
00180 }
00181
00182 void Logger::LoggerOutput::log(const Logger &log)
00183 {
00184 if (_level & log._level)
00185 {
00186 std::list<std::string> prefixes;
00187
00188
00189 if (_options & LOG_DATETIME)
00190 {
00191
00192 time_t ltime;
00193 ltime=time(NULL);
00194 std::string timestamp(asctime( localtime(<ime) ));
00195 timestamp.erase(std::remove(timestamp.begin(), timestamp.end(), '\n'), timestamp.end());
00196 prefixes.push_back(timestamp);
00197 }
00198
00199
00200 if (_options & LOG_TIMESTAMP)
00201 {
00202 std::stringstream ss;
00203 ss.fill('0');
00204 ss << log._logtime.tv_sec << "." << std::setw(6) << log._logtime.tv_usec;
00205 prefixes.push_back(ss.str());
00206 }
00207
00208 if (_options & LOG_LEVEL)
00209 {
00210
00211 switch (log._level)
00212 {
00213 case LOGGER_EMERG:
00214 prefixes.push_back("EMERGENCY");
00215 break;
00216
00217 case LOGGER_ALERT:
00218 prefixes.push_back("ALERT");
00219 break;
00220
00221 case LOGGER_CRIT:
00222 prefixes.push_back("CRTITICAL");
00223 break;
00224
00225 case LOGGER_ERR:
00226 prefixes.push_back("ERROR");
00227 break;
00228
00229 case LOGGER_WARNING:
00230 prefixes.push_back("WARNING");
00231 break;
00232
00233 case LOGGER_NOTICE:
00234 prefixes.push_back("NOTICE");
00235 break;
00236
00237 case LOGGER_INFO:
00238 prefixes.push_back("INFO");
00239 break;
00240
00241 case LOGGER_DEBUG:
00242 {
00243 std::stringstream ss;
00244 ss << "DEBUG." << log._debug_verbosity;
00245 prefixes.push_back(ss.str());
00246 break;
00247 }
00248
00249 default:
00250 break;
00251 }
00252 }
00253
00254 if (_options & LOG_HOSTNAME)
00255 {
00256 char *hostname_array = new char[64];
00257 if ( gethostname(hostname_array, 64) == 0 )
00258 {
00259 std::string hostname(hostname_array);
00260 prefixes.push_back(hostname);
00261 }
00262
00263 delete[] hostname_array;
00264 }
00265
00266
00267 for (std::list<std::string>::const_iterator iter = prefixes.begin(); iter != prefixes.end(); iter++)
00268 {
00269 if (iter == prefixes.begin())
00270 {
00271 _stream << (*iter);
00272 }
00273 else
00274 {
00275 _stream << " " << (*iter);
00276 }
00277 }
00278
00279 if (!prefixes.empty())
00280 {
00281 _stream << ": ";
00282 }
00283
00284 _stream << log.rdbuf() << std::endl;
00285 }
00286 }
00287
00288 Logger::LoggerOutput::LoggerOutput(std::ostream &stream, const unsigned char logmask, const unsigned char options)
00289 : _stream(stream), _level(logmask), _options(options)
00290 {
00291 }
00292
00293 Logger::LoggerOutput::~LoggerOutput()
00294 {
00295 }
00296
00297 void Logger::enableAsync()
00298 {
00299 Logger::_logwriter.enableAsync();
00300 }
00301
00302 void Logger::LogWriter::enableAsync()
00303 {
00304 try {
00305 _use_queue = true;
00306 start();
00307 } catch (const ibrcommon::ThreadException &ex) {
00308 IBRCOMMON_LOGGER(error) << "failed to start LogWriter\n" << ex.what() << IBRCOMMON_LOGGER_ENDL;
00309 }
00310 }
00311
00312 void Logger::stop()
00313 {
00314
00315 _logwriter.stop();
00316 }
00317
00318 Logger::LogWriter::LogWriter()
00319 : _verbosity(0), _syslog(0), _syslog_mask(0), _queue(50), _use_queue(false)
00320
00321 {
00322 }
00323
00324 Logger::LogWriter::~LogWriter()
00325 {
00326
00327 if (_use_queue) stop();
00328
00329
00330 join();
00331 }
00332
00333 void Logger::LogWriter::log(Logger &logger)
00334 {
00335 if (_use_queue)
00336 {
00337 _queue.push(logger);
00338 }
00339 else
00340 {
00341 flush(logger);
00342 }
00343 }
00344
00345 void Logger::LogWriter::run()
00346 {
00347 try {
00348 while (true)
00349 {
00350 Logger log = _queue.getnpop(true);
00351 flush(log);
00352 }
00353 } catch (const std::exception&) {
00354 ibrcommon::Queue<Logger>::Locked q = _queue.exclusive();
00355
00356 try {
00357
00358
00359
00360 while (!q.empty())
00361 {
00362 Logger &log = q.front();
00363 try { log.flush(); } catch (...) {};
00364 q.pop();
00365 }
00366 } catch (const std::exception&) {
00367
00368 }
00369 }
00370 }
00371
00372 bool Logger::LogWriter::__cancellation()
00373 {
00374
00375 _queue.abort();
00376
00377
00378 return true;
00379 }
00380 }