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
00028 string tmpname = name;
00029 bool triedAllParents = false;
00030 while (! triedAllParents) {
00031
00032 if (defaultLevels.find(tmpname) != defaultLevels.end()) {
00033 level = defaultLevels.find(tmpname)->second;
00034 break;
00035 }
00036
00037 if (existingLogs.find(tmpname) != existingLogs.end()) {
00038 level = existingLogs.find(tmpname)->second->getLevel();
00039 break;
00040 }
00041
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
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 }