Logger.cpp
Go to the documentation of this file.
00001 
00048 #include <iostream>
00049 #include <fstream>
00050 #include <signal.h>
00051 #include <unistd.h>
00052 
00053 using namespace std;
00054 
00055 #include "roch_base/core/Logger.h"
00056 
00057 namespace sawyer
00058 {
00059 
00060   const char *Logger::levelNames[] = {"ERROR", "EXCEPTION", "WARNING", "INFO", "DETAIL"};
00061 
00062   void loggerTermHandler(int signum)
00063   {
00064     Logger::instance().close();
00065 
00066     if ((signum == SIGABRT) || (signum == SIGSEGV))
00067     {
00068       /* We need to catch these so we can flush out any last messages.
00069        * having done this, probably the most consistent thing to do
00070        * is re-raise the signal.  (We certainly don't want to just
00071        * ignore these) */
00072       signal(signum, SIG_DFL);
00073       kill(getpid(), signum);
00074     }
00075   }
00076 
00077   Logger &Logger::instance()
00078   {
00079     static Logger instance;
00080     return instance;
00081   }
00082 
00083   Logger::Logger() :
00084       enabled(true),
00085       level(WARNING),
00086       stream(&cerr)
00087   {
00088     nullStream = new ofstream("/dev/null");
00089   }
00090 
00091   Logger::~Logger()
00092   {
00093     close();
00094   }
00095 
00096   void Logger::close()
00097   {
00098     // The actual output stream is owned by somebody else, we only need to flush it
00099     stream->flush();
00100 
00101     nullStream->close();
00102     delete nullStream;
00103     nullStream = 0;
00104   }
00105 
00106   std::ostream &Logger::entry(enum logLevels msg_level, const char *file, int line)
00107   {
00108     if (!enabled) { return *nullStream; }
00109     if (msg_level > this->level) { return *nullStream; }
00110 
00111     /* Construct the log entry tag */
00112     // Always the level of the message
00113     *stream << levelNames[msg_level];
00114     // If file/line information is provided, need to print it with brackets:
00115     if (file || (line >= 0))
00116     {
00117       *stream << " (";
00118       if (file) { *stream << file; }
00119       // Only want a comma if we have both items
00120       if (file && (line >= 0)) { *stream << ","; }
00121       if (line >= 0) { *stream << line; }
00122       *stream << ")";
00123     }
00124     *stream << ": ";
00125     return *stream;
00126   }
00127 
00128   void Logger::setEnabled(bool en)
00129   {
00130     enabled = en;
00131   }
00132 
00133   void Logger::setLevel(enum logLevels newLevel)
00134   {
00135     level = newLevel;
00136   }
00137 
00138   void Logger::setStream(ostream *newStream)
00139   {
00140     stream->flush();
00141     stream = newStream;
00142   }
00143 
00144   void Logger::hookFatalSignals()
00145   {
00146     signal(SIGINT, loggerTermHandler);
00147     signal(SIGTERM, loggerTermHandler);
00148     /* If there's an abort or segfault in Logger.close(), well...
00149      * we're pretty much totally screwed anyway. */
00150     signal(SIGABRT, loggerTermHandler);
00151     signal(SIGSEGV, loggerTermHandler);
00152   }
00153 
00154 }; // namespace sawyer
00155 


roch_base
Author(s): Mike Purvis , Paul Bovbel , Carl
autogenerated on Sat Jun 8 2019 20:32:33