Logging.cc

Go to the documentation of this file.
00001 
00002 #include "Rivet/Tools/Logging.hh"
00003 #include <ctime>
00004 
00005 using namespace std;
00006 
00007 
00008 namespace Rivet {
00009 
00010   Log::LogMap Log::existingLogs;
00011   Log::LevelMap Log::defaultLevels;
00012   bool Log::showTimestamp = false;
00013   bool Log::showLogLevel = true;
00014   bool Log::showLoggerName = true;
00015 
00016   Log::Log(const string& name) 
00017     : _name(name), _level(INFO), _nostream(new ostream(0)) { }
00018 
00019 
00020   Log::Log(const string& name, const Level& level)
00021     : _name(name), _level(level), _nostream(new ostream(0)) { }
00022 
00023 
00024   Log& Log::getLog(const string& name) {
00025     if (existingLogs.find(name) == existingLogs.end()) {
00026       Level level = INFO;
00027       // Try running through all parent classes to find an existing level
00028       string tmpname = name;
00029       bool triedAllParents = false;
00030       while (! triedAllParents) {
00031         // Is there a default level?
00032         if (defaultLevels.find(tmpname) != defaultLevels.end()) {
00033           level = defaultLevels.find(tmpname)->second;
00034           break;
00035         }
00036         // Is there already such a logger?
00037         if (existingLogs.find(tmpname) != existingLogs.end()) {
00038           level = existingLogs.find(tmpname)->second->getLevel();
00039           break;
00040         }
00041         // Crop the string back to the next parent level
00042         size_t lastDot = tmpname.find_last_of(".");
00043         if (lastDot == string::npos) {
00044           triedAllParents = true;
00045         } else {
00046           tmpname = tmpname.substr(0, lastDot);
00047         }
00048       }
00049       existingLogs[name] = new Log(name, level);
00050     }
00051     return *existingLogs[name];
00052   }
00053 
00054 
00055   Log& Log::getLog(const string& name, const Level& level) {
00056     //cout << "Log::getLog(name, level): are we really using this? Does it make sense?" << endl;
00057     if (existingLogs.find(name) == existingLogs.end()) {
00058       existingLogs[name] = new Log(name, level);
00059     }
00060     return *existingLogs[name];
00061   }
00062 
00063 
00064   string Log::getLevelName(const Level& level) {
00065     switch(level) {
00066     case TRACE:
00067       return "TRACE";
00068     case DEBUG:
00069       return "DEBUG";
00070     case INFO:
00071       return "INFO";
00072     case WARN:
00073       return "WARN";
00074     case ERROR:
00075       return "ERROR";
00076     }
00077     throw runtime_error("Enum value was not a valid log level. How did that happen?");
00078   }
00079 
00080 
00081   Log::Level Log::getLevelFromName(const string& level) {
00082     if (level == "TRACE") return TRACE;
00083     if (level == "DEBUG") return DEBUG;
00084     if (level == "INFO") return INFO;
00085     if (level == "WARN") return WARN;
00086     if (level == "ERROR") return ERROR;
00087     throw runtime_error("Couldn't create a log level from string '" + level + "'");
00088   }
00089 
00090 
00091   string Log::formatMessage(const Level& level, const std::string& message) {
00092     string out;
00093     if (Log::showLoggerName) {
00094       out += getName();
00095       out += ": ";
00096     }
00097 
00098     if (Log::showLogLevel) {
00099       out += Log::getLevelName(level);
00100       out += " ";
00101     }
00102 
00103     if (Log::showTimestamp) {
00104       time_t rawtime;
00105       time(&rawtime);
00106       char* timestr = ctime(&rawtime);
00107       timestr[24] = ' ';
00108       out += timestr;
00109       out += " ";
00110     }
00111 
00112     out += message;
00113     return out;
00114   }
00115 
00116 
00117   void Log::log(const Level& level, const std::string& message) {
00118     if (isActive(level)) {
00119       cout << formatMessage(level, message) << endl;
00120     }
00121   }
00122 
00123 
00124   ostream& operator<<(Log& log, const Log::Level& level) {
00125     if (log.isActive(level)) {
00126       cout << log.formatMessage(level, "");
00127       return cout;
00128     } else {
00129       return *(log._nostream);
00130     }
00131   }
00132 
00133 }