00001 #include "Rivet/Tools/Logging.hh"
00002 #include <ctime>
00003 #include <unistd.h>
00004 using namespace std;
00005
00006 namespace Rivet {
00007
00008
00009 Log::LogMap Log::existingLogs;
00010 Log::LevelMap Log::defaultLevels;
00011 Log::ColorCodes Log::colorCodes;
00012 string Log::endColorCode;
00013 bool Log::showTimestamp = false;
00014 bool Log::showLogLevel = true;
00015 bool Log::showLoggerName = true;
00016 bool Log::useShellColors = true;
00017
00018
00019 Log::Log(const string& name)
00020 : _name(name), _level(INFO), _nostream(new ostream(0)) { }
00021
00022
00023 Log::Log(const string& name, int level)
00024 : _name(name), _level(level), _nostream(new ostream(0)) { }
00025
00026
00027
00028 void _updateLevels(const Log::LevelMap& defaultLevels, Log::LogMap& existingLogs) {
00029
00030 for (Log::LevelMap::const_iterator lev = defaultLevels.begin(); lev != defaultLevels.end(); ++lev) {
00031 for (Log::LogMap::iterator log = existingLogs.begin(); log != existingLogs.end(); ++log) {
00032 if (log->first.find(lev->first) == 0) {
00033 log->second->setLevel(lev->second);
00034 }
00035 }
00036 }
00037 }
00038
00039
00040 void Log::setLevel(const string& name, int level) {
00041 defaultLevels[name] = level;
00042
00043 _updateLevels(defaultLevels, existingLogs);
00044 }
00045
00046
00047 void Log::setLevels(const LevelMap& logLevels) {
00048 for (LevelMap::const_iterator lev = logLevels.begin(); lev != logLevels.end(); ++lev) {
00049 defaultLevels[lev->first] = lev->second;
00050 }
00051 _updateLevels(defaultLevels, existingLogs);
00052 }
00053
00054
00055 Log& Log::getLog(const string& name) {
00056 if (existingLogs.find(name) == existingLogs.end()) {
00057 int level = INFO;
00058
00059 string tmpname = name;
00060 bool triedAllParents = false;
00061 while (! triedAllParents) {
00062
00063 if (defaultLevels.find(tmpname) != defaultLevels.end()) {
00064 level = defaultLevels.find(tmpname)->second;
00065 break;
00066 }
00067
00068 if (existingLogs.find(tmpname) != existingLogs.end()) {
00069 level = existingLogs.find(tmpname)->second->getLevel();
00070 break;
00071 }
00072
00073 size_t lastDot = tmpname.find_last_of(".");
00074 if (lastDot != string::npos) {
00075 tmpname = tmpname.substr(0, lastDot);
00076 } else {
00077 triedAllParents = true;
00078 }
00079 }
00080
00081
00082
00083 existingLogs[name] = new Log(name, level);
00084 }
00085 return *existingLogs[name];
00086 }
00087
00088
00089 string Log::getLevelName(int level) {
00090
00091 switch(level) {
00092 case TRACE:
00093 return "TRACE";
00094 case DEBUG:
00095 return "DEBUG";
00096 case INFO:
00097 return "INFO";
00098 case WARN:
00099 return "WARN";
00100 case ERROR:
00101 return "ERROR";
00102 default:
00103 return "";
00104 }
00105
00106 }
00107
00108
00109 string Log::getColorCode(int level) {
00110 if (!Log::useShellColors) return "";
00111
00112 if (Log::colorCodes.empty()) {
00113
00114 if (isatty(1)) {
00115
00116 Log::colorCodes[TRACE] = "\033[0;37m";
00117 Log::colorCodes[DEBUG] = "\033[0;36m";
00118 Log::colorCodes[INFO] = "\033[0;32m";
00119 Log::colorCodes[WARN] = "\033[0;33m";
00120 Log::colorCodes[ERROR] = "\033[0;31m";
00121 Log::endColorCode = "\033[0m";
00122 } else {
00123 Log::colorCodes[TRACE] = "";
00124 Log::colorCodes[DEBUG] = "";
00125 Log::colorCodes[INFO] = "";
00126 Log::colorCodes[WARN] = "";
00127 Log::colorCodes[ERROR] = "";
00128 }
00129 }
00130
00131
00132 return colorCodes[level];
00133 }
00134
00135
00136 Log::Level Log::getLevelFromName(const string& level) {
00137 if (level == "TRACE") return TRACE;
00138 if (level == "DEBUG") return DEBUG;
00139 if (level == "INFO") return INFO;
00140 if (level == "WARN") return WARN;
00141 if (level == "ERROR") return ERROR;
00142 throw Error("Couldn't create a log level from string '" + level + "'");
00143 }
00144
00145
00146 string Log::formatMessage(int level, const string& message) {
00147 string out;
00148 if (Log::useShellColors) {
00149 out += getColorCode(level);
00150 }
00151
00152 if (Log::showLoggerName) {
00153 out += getName();
00154 out += ": ";
00155 }
00156
00157 if (Log::showLogLevel) {
00158 out += Log::getLevelName(level);
00159 out += " ";
00160 }
00161
00162 if (Log::showTimestamp) {
00163 time_t rawtime;
00164 time(&rawtime);
00165 char* timestr = ctime(&rawtime);
00166 timestr[24] = ' ';
00167 out += timestr;
00168 out += " ";
00169 }
00170
00171 if (Log::useShellColors) {
00172 out += endColorCode;
00173 }
00174
00175 out += " ";
00176 out += message;
00177
00178 return out;
00179 }
00180
00181
00182 void Log::log(int level, const string& message) {
00183 if (isActive(level)) {
00184 cout << formatMessage(level, message) << endl;
00185 }
00186 }
00187
00188
00189 ostream& operator<<(Log& log, int level) {
00190 if (log.isActive(level)) {
00191 cout << log.formatMessage(level, "");
00192 return cout;
00193 } else {
00194 return *(log._nostream);
00195 }
00196 }
00197
00198 }