libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_LOGGING_SCOPED_LOGGER_HPP 00029 #define MOOST_LOGGING_SCOPED_LOGGER_HPP 00030 00031 #include <string> 00032 #include <sstream> 00033 #include <map> 00034 #include <vector> 00035 00036 #include <boost/shared_ptr.hpp> 00037 00038 #if defined(_MSC_VER) 00039 #pragma warning (push) 00040 #pragma warning ( disable: 4231 4251 4275 4786 ) 00041 #endif 00042 00043 #include <log4cxx/logger.h> 00044 #include <log4cxx/helpers/pool.h> 00045 #include <log4cxx/spi/loggingevent.h> 00046 #include <log4cxx/helpers/synchronized.h> 00047 #include <log4cxx/helpers/mutex.h> 00048 00049 #include <log4cxx/helpers/resourcebundle.h> 00050 #include <log4cxx/helpers/transcoder.h> 00051 00052 #include <log4cxx/appenderskeleton.h> 00053 00054 #include "../logging.hpp" 00055 #include "../timer.h" 00056 00057 namespace moost { namespace logging { 00058 00067 class scoped_logger 00068 { 00069 private: 00070 00071 struct sLogEntry 00072 { 00073 sLogEntry() 00074 : pLocationInfo(NULL) {} 00075 00076 log4cxx::LevelPtr level; 00077 std::string message; 00078 log4cxx::spi::LocationInfo const* pLocationInfo; 00079 }; 00080 00081 public: 00082 00083 scoped_logger() 00084 : m_startTime(boost::posix_time::microsec_clock::local_time()) 00085 { 00086 init(std::string(), log4cxx::Level::getOff()); 00087 } 00088 00089 scoped_logger(const std::string& name) 00090 : m_startTime(boost::posix_time::microsec_clock::local_time()) 00091 { 00092 init(name); 00093 } 00094 00095 scoped_logger(const std::string& name, moost::timer::scoped_time& sc) 00096 : m_startTime(sc.get_time()) 00097 { 00098 init(name); 00099 } 00100 00101 scoped_logger(const std::string& name, moost::multi_timer::scoped_time& sc) 00102 : m_startTime(sc.get_time()) 00103 { 00104 init(name); 00105 } 00106 00107 scoped_logger(const std::string& name, const boost::posix_time::ptime& startTime) 00108 : m_startTime(startTime) 00109 { 00110 init(name); 00111 } 00112 00113 ~scoped_logger() 00114 { 00115 try 00116 { 00117 forcedLog(); 00118 } 00119 catch (...) 00120 {} 00121 } 00122 00124 // scoped_logger custom 00125 00129 void setTimingsHeader(const std::string& totTimingsHeader = " Overall time: ", const std::string& subTimingsIndentation = " -> ") 00130 { 00131 m_totTimingsHeader = totTimingsHeader; 00132 m_subTimingsIndentation = subTimingsIndentation; 00133 } 00134 00135 void addSubTime(const std::string& header, int ms) 00136 { 00137 m_subTimes[header] += ms; 00138 } 00139 00141 00142 void forcedLog(const log4cxx::LevelPtr& level, const std::string& message) 00143 { 00144 updateHighestLevel(level); 00145 00146 m_messages.push_back( sLogEntry() ); 00147 sLogEntry& b = m_messages.back(); 00148 b.level = level; 00149 b.message = message; 00150 } 00151 00152 void forcedLog(const log4cxx::LevelPtr& level, const std::string& message, const log4cxx::spi::LocationInfo& location) 00153 { 00154 updateHighestLevel(level); 00155 00156 m_messages.push_back( sLogEntry() ); 00157 sLogEntry& b = m_messages.back(); 00158 b.level = level; 00159 b.message = message; 00160 b.pLocationInfo = &location; 00161 } 00162 00163 log4cxx::LevelPtr getLevel() const 00164 { return m_loggerLevel; } 00165 00166 virtual void setLevel(const log4cxx::LevelPtr& level) 00167 { m_loggerLevel = level; } 00168 00170 00171 void debug(const std::string& msg, const log4cxx::spi::LocationInfo& location) 00172 { 00173 if (isDebugEnabled()) { 00174 forcedLog(log4cxx::Level::getDebug(), msg, location); 00175 } 00176 } 00177 void debug(const std::string& msg) 00178 { 00179 if (isDebugEnabled()) { 00180 forcedLog(log4cxx::Level::getDebug(), msg); 00181 } 00182 } 00183 00184 void error(const std::string& msg, const log4cxx::spi::LocationInfo& location) 00185 { 00186 if (isErrorEnabled()) { 00187 forcedLog(log4cxx::Level::getError(), msg, location); 00188 } 00189 } 00190 void error(const std::string& msg) 00191 { 00192 if (isErrorEnabled()) { 00193 forcedLog(log4cxx::Level::getError(), msg); 00194 } 00195 } 00196 00197 void fatal(const std::string& msg, const log4cxx::spi::LocationInfo& location) 00198 { 00199 if (isFatalEnabled()) { 00200 forcedLog(log4cxx::Level::getFatal(), msg, location); 00201 } 00202 } 00203 void fatal(const std::string& msg) 00204 { 00205 if (isFatalEnabled()) { 00206 forcedLog(log4cxx::Level::getFatal(), msg); 00207 } 00208 } 00209 00210 void info(const std::string& msg, const log4cxx::spi::LocationInfo& location) 00211 { 00212 if (isInfoEnabled()) { 00213 forcedLog(log4cxx::Level::getInfo(), msg, location); 00214 } 00215 } 00216 void info(const std::string& msg) 00217 { 00218 if (isInfoEnabled()) { 00219 forcedLog(log4cxx::Level::getInfo(), msg); 00220 } 00221 } 00222 00223 void log(const log4cxx::LevelPtr& level, const std::string& message, 00224 const log4cxx::spi::LocationInfo& location) 00225 { 00226 if (isEnabledFor(level)) { 00227 forcedLog(level, message, location); 00228 } 00229 } 00230 void log(const log4cxx::LevelPtr& level, const std::string& message) 00231 { 00232 if (isEnabledFor(level)) { 00233 forcedLog(level, message); 00234 } 00235 } 00236 00237 void warn(const std::string& msg, const log4cxx::spi::LocationInfo& location) 00238 { 00239 if (isWarnEnabled()) { 00240 forcedLog(log4cxx::Level::getWarn(), msg, location); 00241 } 00242 } 00243 void warn(const std::string& msg) 00244 { 00245 if (isWarnEnabled()) { 00246 forcedLog(log4cxx::Level::getWarn(), msg); 00247 } 00248 } 00249 00250 void trace(const std::string& msg, const log4cxx::spi::LocationInfo& location) 00251 { 00252 if (isTraceEnabled()) { 00253 forcedLog(log4cxx::Level::getTrace(), msg, location); 00254 } 00255 } 00256 void trace(const std::string& msg) 00257 { 00258 if (isTraceEnabled()) { 00259 forcedLog(log4cxx::Level::getTrace(), msg); 00260 } 00261 } 00262 00264 00265 void addRef() const 00266 { /*m_pLogger->addRef(); */} 00267 void releaseRef() const 00268 { /*m_pLogger->releaseRef(); */} 00269 virtual void addAppender(const log4cxx::AppenderPtr& /* newAppender */) 00270 { /*m_pLogger->addAppender(newAppender);*/ } 00271 void callAppenders(const log4cxx::spi::LoggingEventPtr& /* event */, log4cxx::helpers::Pool& /* pool */) const 00272 { /*m_pLogger->callAppenders(event, pool);*/ } 00273 void closeNestedAppenders() 00274 { /*m_pLogger->closeNestedAppenders();*/ } 00275 00276 bool getAdditivity() const 00277 { return true; /*m_pLogger->getAdditivity();*/ } 00278 //log4cxx::AppenderList getAllAppenders() const 00279 //{ return m_pLogger->getAllAppenders(); } 00280 virtual const log4cxx::LevelPtr& getEffectiveLevel() const 00281 { return m_loggerLevel; } 00282 log4cxx::spi::LoggerRepositoryPtr getLoggerRepository() const 00283 { return log4cxx::Logger::getRootLogger()->getLoggerRepository(); } 00284 void getName(std::string& name) const 00285 { log4cxx::helpers::Transcoder::encode(m_name, name); } 00286 log4cxx::LoggerPtr getParent() const 00287 { return log4cxx::Logger::getRootLogger(); } 00288 log4cxx::helpers::ResourceBundlePtr getResourceBundle() const 00289 { return log4cxx::Logger::getRootLogger()->getResourceBundle(); } 00290 00291 void removeAllAppenders() 00292 { log4cxx::Logger::getRootLogger()->removeAllAppenders(); } 00293 void removeAppender(const log4cxx::AppenderPtr& appender) 00294 { log4cxx::Logger::getRootLogger()->removeAppender(appender); } 00295 void setAdditivity(bool additive) 00296 { log4cxx::Logger::getRootLogger()->setAdditivity(additive); } 00297 inline void setResourceBundle(const log4cxx::helpers::ResourceBundlePtr& bundle) 00298 { log4cxx::Logger::getRootLogger()->setResourceBundle(bundle); } 00299 inline const log4cxx::helpers::Mutex& getMutex() const 00300 { return log4cxx::Logger::getRootLogger()->getMutex(); } 00301 00303 // forwarded methods 00304 00305 bool isAttached(const log4cxx::AppenderPtr& appender) const 00306 { return log4cxx::Logger::getRootLogger()->isAttached(appender); } 00307 bool isEnabledFor(const log4cxx::LevelPtr& level) const 00308 { return level->isGreaterOrEqual(m_loggerLevel); } 00309 00310 bool isDebugEnabled() const 00311 { return m_loggerLevel->toInt() <= log4cxx::Level::DEBUG_INT; } 00312 bool isInfoEnabled() const 00313 { return m_loggerLevel->toInt() <= log4cxx::Level::INFO_INT; } 00314 bool isWarnEnabled() const 00315 { return m_loggerLevel->toInt() <= log4cxx::Level::WARN_INT; } 00316 bool isErrorEnabled() const 00317 { return m_loggerLevel->toInt() <= log4cxx::Level::ERROR_INT; } 00318 bool isFatalEnabled() const 00319 { return m_loggerLevel->toInt() <= log4cxx::Level::FATAL_INT; } 00320 bool isTraceEnabled() const 00321 { return m_loggerLevel->toInt() <= log4cxx::Level::TRACE_INT; } 00322 00325 00326 //AppenderPtr getAppender(const LogString& name) const; 00327 00328 //void forcedLogLS( const LevelPtr& level, const log4cxx::LogString& message, 00329 // const log4cxx::spi::LocationInfo& location) const; 00330 // static LoggerPtr getLoggerLS(const LogString& name); 00331 //static LoggerPtr getLoggerLS(const LogString& name, 00332 // const log4cxx::spi::LoggerFactoryPtr& factory); 00333 //void removeAppender(const LogString& name) 00334 //void l7dlog(const LevelPtr& level, const LogString& key, 00335 // const log4cxx::spi::LocationInfo& locationInfo, 00336 // const std::vector<LogString>& values) const; 00337 //void logLS(const LevelPtr& level, const LogString& message, 00338 // const log4cxx::spi::LocationInfo& location) const; 00339 //const LogString getName() const { return name; } 00340 00341 private: 00342 00343 void forcedLog() 00344 { 00345 if ( !m_highestMessageLevel ) 00346 m_highestMessageLevel = m_loggerLevel; 00347 00348 if ( isTraceEnabled() ) 00349 { 00350 std::ostringstream buf; 00351 buf << "\n"; 00352 00353 // get subtimes 00354 if ( !m_subTimes.empty() ) 00355 { 00356 std::map<std::string, int>::const_iterator it; 00357 for ( it = m_subTimes.begin(); it != m_subTimes.end(); ++it ) 00358 buf << ">>> " << m_subTimingsIndentation << it->first << ": " << it->second << "ms\n"; 00359 00360 } 00361 00362 // get overall time 00363 int timeMs = static_cast<int> ( 00364 ( boost::posix_time::microsec_clock::local_time() - 00365 m_startTime 00366 ).total_milliseconds() ); 00367 00368 buf << " " << m_totTimingsHeader << timeMs << "ms\n"; 00369 00370 m_messages.push_back( sLogEntry() ); 00371 sLogEntry& b = m_messages.back(); 00372 b.level = log4cxx::Level::getDebug(); 00373 b.message = buf.str(); 00374 } 00375 00376 std::vector< std::pair<log4cxx::LevelPtr, log4cxx::AppenderPtr> >::iterator aIt; 00377 std::vector<sLogEntry>::const_iterator mIt; 00378 00379 std::string message; 00380 log4cxx::helpers::Pool p; 00381 log4cxx::LogString msg; 00382 00383 for ( aIt = m_appenders.begin(); aIt != m_appenders.end(); ++aIt ) 00384 { 00385 const log4cxx::LevelPtr& appenderLevel = aIt->first; 00386 log4cxx::AppenderPtr& appender = aIt->second; 00387 00388 std::ostringstream buf; 00389 log4cxx::spi::LocationInfo const* pLocationInfo = NULL; 00390 00391 if(!m_messages.empty()) 00392 { 00393 buf << "\n"; 00394 00395 for ( mIt = m_messages.begin(); mIt != m_messages.end(); ++mIt ) 00396 { 00397 if ( mIt->level->isGreaterOrEqual( appenderLevel ) ) 00398 { 00399 buf << " " << mIt->message << "\n"; 00400 pLocationInfo = mIt->pLocationInfo; 00401 } 00402 } 00403 } 00404 00405 message = buf.str(); 00406 if ( message.empty() ) 00407 continue; 00408 00409 LOG4CXX_DECODE_CHAR(msg, message); 00410 00411 if ( pLocationInfo ) 00412 { 00413 log4cxx::spi::LoggingEventPtr event(new log4cxx::spi::LoggingEvent( m_name, m_highestMessageLevel, msg, 00414 *pLocationInfo )); 00415 appender->doAppend(event, p); 00416 } 00417 else 00418 { 00419 log4cxx::spi::LoggingEventPtr event(new log4cxx::spi::LoggingEvent( m_name, m_highestMessageLevel, msg, 00420 log4cxx::spi::LocationInfo::getLocationUnavailable())); 00421 appender->doAppend(event, p); 00422 } 00423 00424 } 00425 } 00426 00427 void updateHighestLevel(const log4cxx::LevelPtr& level) 00428 { 00429 if ( !m_highestMessageLevel || // no level was set 00430 ( !level->equals(m_highestMessageLevel) && level->isGreaterOrEqual(m_highestMessageLevel) ) // it's a higher level! 00431 ) 00432 { 00433 m_highestMessageLevel = level; 00434 } 00435 } 00436 00437 public: 00443 void init(const std::string& name, log4cxx::LevelPtr level = log4cxx::Level::getFatal()) 00444 { 00445 setTimingsHeader(); 00446 log4cxx::helpers::Transcoder::decode(name, m_name); 00447 00448 log4cxx::LoggerPtr pRoot = log4cxx::Logger::getRootLogger(); 00449 m_loggerLevel = level; 00450 00451 //const log4cxx::helpers::Mutex& mutex = pRoot->getMutex(); 00452 //log4cxx::helpers::synchronized s(mutex); 00453 00454 // go through the list of appenders and set the lowest threshold! 00455 log4cxx::AppenderList al = pRoot->getAllAppenders(); 00456 log4cxx::AppenderList::const_iterator it; 00457 for ( it = al.begin(); it != al.end(); ++it ) 00458 { 00459 // Looks ugly, but works quite nicely (TM) 00460 // The static_cast<> invokes the overloaded cast operator of the ObjectPtrT<> template and turns 00461 // the AppenderPtr into and Appender *, which we can easily downcast to an AppenderSkeleton *. 00462 log4cxx::AppenderSkeleton *pSkeletonAppender = dynamic_cast<log4cxx::AppenderSkeleton*>(static_cast<log4cxx::Appender *>(*it)); 00463 if ( !pSkeletonAppender ) 00464 continue; 00465 00466 const log4cxx::LevelPtr& pLvl = pSkeletonAppender->getThreshold(); 00467 00468 if ( !pLvl ) 00469 continue; 00470 00471 m_appenders.push_back( std::make_pair(pLvl, *it) ); 00472 00473 if ( m_loggerLevel->isGreaterOrEqual(pLvl) ) 00474 { 00475 m_loggerLevel = pLvl; 00476 } 00477 } 00478 } 00479 00480 private: 00481 00487 log4cxx::LevelPtr m_loggerLevel; 00488 00493 log4cxx::LevelPtr m_highestMessageLevel; 00494 00498 log4cxx::LogString m_name; 00499 00503 std::vector<sLogEntry> m_messages; 00504 00508 std::vector< std::pair<log4cxx::LevelPtr, log4cxx::AppenderPtr> > m_appenders; 00509 00510 boost::posix_time::ptime m_startTime; 00511 std::map<std::string, int> m_subTimes; 00512 00513 std::string m_totTimingsHeader; 00514 std::string m_subTimingsIndentation; 00515 }; 00516 00517 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00518 00519 typedef boost::shared_ptr<moost::logging::scoped_logger> LoggerPtr; 00520 00521 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00522 00523 class scoped_timing 00524 { 00525 public: 00526 scoped_timing( LoggerPtr& logger, const std::string& str) 00527 : m_pLogger(logger), m_str(str), 00528 m_startTime(boost::posix_time::microsec_clock::local_time()) 00529 {} 00530 00531 ~scoped_timing() 00532 { 00533 try 00534 { 00535 int timeMs = static_cast<int> ( 00536 ( boost::posix_time::microsec_clock::local_time() - 00537 m_startTime 00538 ).total_milliseconds() ); 00539 00540 m_pLogger->addSubTime( m_str, timeMs); 00541 } 00542 catch (...) 00543 {} 00544 } 00545 00546 private: 00547 00548 LoggerPtr& m_pLogger; 00549 std::string m_str; 00550 boost::posix_time::ptime m_startTime; 00551 }; 00552 00553 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00554 00555 #define MLOG_SCOPED_NAMED_DEFINE(logger, name) \ 00556 moost::logging::LoggerPtr logger( new moost::logging::scoped_logger( name ) ) 00557 00558 #define MLOG_SCOPED_FUNC_DEFINE(logger) \ 00559 moost::logging::LoggerPtr logger( new moost::logging::scoped_logger( MLOG_FUNC_NAME() ) ) 00560 00561 #define MLOG_SCOPED_NAMED_TIME_DEFINE(logger, name, time) \ 00562 moost::logging::LoggerPtr logger( new moost::logging::scoped_logger( name, time ) ) 00563 00564 #define MLOG_SCOPED_FUNC_TIME_DEFINE(logger, time) \ 00565 moost::logging::LoggerPtr logger( new moost::logging::scoped_logger( MLOG_FUNC_NAME(), time ) ) 00566 00572 #define MLOG_SCOPED_FM303_DEFINE(logger, name) \ 00573 moost::multi_timer::scoped_time st(fm303_multi_timer(), name); \ 00574 MLOG_SCOPED_NAMED_TIME_DEFINE(logger, name, st) 00575 00581 #define MLOG_SCOPED_FM303_FUNCTION_DEFINE(logger) \ 00582 moost::multi_timer::scoped_time st(fm303_multi_timer(), MLOG_FUNC_NAME()); \ 00583 MLOG_SCOPED_NAMED_TIME_DEFINE(logger, MLOG_FUNC_NAME(), st) 00584 00591 #define MLOG_SCOPED_FM303_CLASS_DEFINE(logger) \ 00592 moost::multi_timer::scoped_time st(fm303_multi_timer(), typeid(*this).name()); \ 00593 MLOG_SCOPED_NAMED_TIME_DEFINE(logger, typeid(*this).name(), st) 00594 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00595 00596 #if defined(_MSC_VER) 00597 #pragma warning ( pop ) 00598 #endif 00599 00600 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00601 00602 }} 00603 00604 #endif // #define MOOST_LOGGING_SCOPED_LOGGER_HPP