/** @file $Id$ $Date$ $Author$ @copy © Marc Wäckerlin @license LGPL, see file COPYING */ #include #include #include #include #ifndef _T #define _T #endif namespace mrw { /** @addtogroup AutoTrace @section trclog4cxx Trace using the log4cxx Library If you link to the library @c libmrwexclog4cxx using a linker option such as: @c -lmrwexclog4cxx, then an unexpected and a terminate handler are registered, that trace a fatal error using the log4cxx library. You don't need to change a single line in your code! The log4cxx library is located at: - http://logging.apache.org/log4cxx @note The configurator is not installed automatically. If you want to trace e.g. on the console, you have to call @c log4cxx::BasicConfigurator::configure(); as first statement in your @c main(). @see @ref AutoInitLog4cxx if you also want to automatically configure @c log4cxx. */ //@{ /** @brief unexpected handler, that traces using log4cxx The unexpected handler is installed automatically when you link to @c -lmrwexclog4cxx. The implementation of this unexpected handler is as follows: @code void unexpected_log4cxx() { log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); logger->fatal("Unexpected Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:+\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } throw std::bad_exception(); } @endcode */ void unexpected_log4cxx() { log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); logger->fatal("Unexpected Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } throw std::bad_exception(); } /** @brief terminate handler, that traces using log4cxx The terminate handler is installed automatically when you link to @c -lmrwexclog4cxx. The implementation of this terminate handler is as follows: @code void terminate_log4cxx() { log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); logger->fatal("Uncaught Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; exit(0); } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:+\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } exit(1); } @endcode */ void terminate_log4cxx() { log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); logger->fatal("Uncaught Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() +"\nStack:\n"+st); } catch (...) { logger->fatal(std::string("Reason: **** not available ****") +"\nStack:\n"+st); } exit(1); } //@} class AutoStackTrace { public: AutoStackTrace() { std::set_unexpected(&mrw::unexpected_log4cxx); std::set_terminate(&mrw::terminate_log4cxx); } }; // initialize stack traces (load symbols) static AutoStackTrace _autoStackTrace; }