log.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** \file log.cpp Implementation of Log class */
00020 
00021 #include <hn/hnprec.h>
00022 #include <hn/osdep.h>
00023 #include <hn/log.h>
00024 #include <boost/date_time/posix_time/posix_time.hpp> // for ptime
00025 
00026 boost::recursive_mutex Log::s_iosLock;
00027 Log *Log::s_log = new Log;
00028 std::deque<std::string> Log::s_messages;
00029 
00030 Log::Log() {}
00031 
00032 Log::~Log() {
00033         s_log = 0;
00034 }
00035 Log& Log::instance() {
00036         return s_log ? *s_log : *(s_log = new Log);
00037 }
00038 
00039 void Log::sendToFiles(std::string msg) {
00040         boost::mutex::scoped_lock l(m_filesLock);
00041         using namespace boost::posix_time;
00042         ptime t(second_clock::local_time());
00043 
00044 #ifdef __ANSI_COLORS__
00045         size_t pos = msg.find(0x1b, 0);
00046         while (pos != std::string::npos) {
00047                 uint32_t j = msg.find('m', pos);
00048                 msg.erase(pos, j-pos + 1);
00049                 pos = msg.find(0x1b, 0);
00050         }
00051 #endif
00052 
00053         FIter i = m_logFiles.begin();
00054         while (i != m_logFiles.end()) {
00055                 std::ofstream ofs((*i).c_str(), std::ios::app);
00056                 ofs << "[" << t << "] " << msg << std::endl;
00057                 ofs.flush();
00058                 ++i;
00059         }
00060 }
00061 
00062 void Log::printLast(uint32_t count) {
00063         if (count > s_messages.size()) {
00064                 count = s_messages.size();
00065         }
00066         CMIter i = s_messages.end();
00067         while (--i != s_messages.begin() && --count);
00068         while (i != s_messages.end()) {
00069                 std::cerr << " [" << count++ << "] " <<  *i++ << std::endl;
00070         }
00071         std::cerr.flush();
00072 }
00073 
00074 void Log::getLast(uint32_t count, std::vector<std::string> *cont) {
00075         CHECK(count);
00076 
00077         if (count > s_messages.size()) {
00078                 count = s_messages.size();
00079         }
00080         while (count--) {
00081                 cont->push_back(s_messages.at(s_messages.size()-count-1));
00082         }
00083 }
00084 
00085 void Log::doLogString(MessageType t, const std::string &msg) {
00086         // clear any existing garbage
00087         std::cerr << '\r' << m_preStr << msg;
00088         int amount = 77 - (m_preStr.size() + msg.size());
00089         if (amount > 0) {
00090                 std::cerr << std::string(amount, ' ');
00091         }
00092         std::cerr << std::endl;
00093         sendToFiles(msg);
00094         addMsg(t, msg);
00095 }
00096 
00097 /**
00098  * Log a simple message.
00099  *
00100  * @param msg    Message to be logged
00101  */
00102 void logMsg(const std::string &msg) {
00103         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00104         Log::instance().doLogString(MT_MSG, msg);
00105 }
00106 
00107 /**
00108  * Log a formatted mesage
00109  *
00110  * @param fmt    Format object to be logged
00111  */
00112 void logMsg(const boost::format &fmt) {
00113         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00114         logMsg(fmt.str());
00115 }
00116 
00117 /**
00118  * Log a simple message only in debug mode
00119  *
00120  * @param msg     Message to be logged
00121  */
00122 void logDebug(const std::string &msg) {
00123 #ifndef NDEBUG
00124         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00125         Log::instance().doLogString(
00126                 MT_DEBUG, (boost::format("Debug: %s") % msg).str()
00127         );
00128 #else
00129         (void)msg; // Suppress compiler warning
00130 #endif
00131 }
00132 /**
00133  * Log a formatted message only in debug mode
00134  *
00135  * @param fmt     Format object to be logged
00136  */
00137 void logDebug(const boost::format &fmt) {
00138 #ifndef NDEBUG
00139         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00140         logDebug(fmt.str());
00141 #else
00142         (void)fmt; // Suppress compiler warning
00143 #endif
00144 }
00145 
00146 /**
00147  * Log a warning (message will be prepended by "Warning:"
00148  *
00149  * @param msg      Message to be logged
00150  */
00151 void logWarning(const std::string &msg) {
00152         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00153         Log::instance().doLogString(
00154                 MT_WARNING,
00155                 (boost::format(COL_YELLOW "Warning: %s" COL_NONE) % msg).str()
00156         );
00157 }
00158 /**
00159  * Log a formatted warning (message will be prepended by "Warning:"
00160  *
00161  * @param fmt      Formatted message to be logged
00162  */
00163 void logWarning(const boost::format &fmt) {
00164         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00165         logWarning(fmt.str());
00166 }
00167 
00168 /**
00169  * Log an error (message will be prepended by "Error:")
00170  *
00171  * @param msg      Message to be logged
00172  */
00173 void logError(const std::string &msg) {
00174         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00175         Log::instance().doLogString(
00176                 MT_ERROR,
00177                 (boost::format(COL_RED "Error: %s" COL_NONE) % msg).str()
00178         );
00179 }
00180 /**
00181  * Log a formatted error message (message will be prepended by "Error:")
00182  *
00183  * @param fmt    Formatted message to be logged
00184  */
00185 void logError(const boost::format &fmt) {
00186         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00187         logError(fmt.str());
00188 }
00189 
00190 /**
00191  * Log a fatal error and abort the application.
00192  *
00193  * @param msg    Message to be logged
00194  */
00195 void logFatalError(const std::string &msg) {
00196         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00197         logError(boost::format("Fatal Error, aborting: %s") %msg);
00198         abort();
00199 }
00200 /**
00201  * Log a fatal error and abort the application
00202  *
00203  * @param fmt      Formatted message to be logged
00204  */
00205 void logFatalError(const boost::format &fmt) {
00206         boost::recursive_mutex::scoped_lock l(Log::s_iosLock);
00207         logFatalError(fmt.str());
00208 }
00209 
00210 #if !defined(NDEBUG) && !defined(NTRACE)
00211 void logTrace(uint32_t mask, const boost::format &msg) {
00212         Log::instance().doLogString(mask, msg.str());
00213 }
00214 void logTrace(uint32_t mask, const std::string &msg) {
00215         Log::instance().doLogString(mask, msg);
00216 }
00217 void logTrace(const std::string &mask, const std::string &msg) {
00218         Log::instance().doLogString(mask, msg);
00219 }
00220 void logTrace(const std::string &mask, const boost::format &msg) {
00221         Log::instance().doLogString(mask, msg.str());
00222 }
00223 #endif