Go to the documentation of this file.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 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
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
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
00172 if (_options & LOG_DATETIME)
00173 {
00174
00175 time_t ltime;
00176 ltime=time(NULL);
00177 std::string timestamp(asctime( localtime(<ime) ));
00178 timestamp.erase(std::remove(timestamp.begin(), timestamp.end(), '\n'), timestamp.end());
00179 prefixes.push_back(timestamp);
00180 }
00181
00182
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
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
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
00293 _logwriter.stop();
00294 }
00295
00296 Logger::LogWriter::LogWriter()
00297 {
00298 }
00299
00300 Logger::LogWriter::~LogWriter()
00301 {
00302
00303 if (!_use_queue) return;
00304
00305
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
00322
00323
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
00337 Logger::_queue.abort();
00338
00339
00340 return true;
00341 }
00342 }