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 for (LevelMap::const_iterator l = defaultLevels.begin(); l != defaultLevels.end(); ++l) {
00081 }
00082 existingLogs[name] = new Log(name, level);
00083 }
00084 return *existingLogs[name];
00085 }
00086
00087
00088 string Log::getLevelName(int level) {
00089
00090 switch(level) {
00091 case TRACE:
00092 return "TRACE";
00093 case DEBUG:
00094 return "DEBUG";
00095 case INFO:
00096 return "INFO";
00097 case WARN:
00098 return "WARN";
00099 case ERROR:
00100 return "ERROR";
00101 default:
00102 return "";
00103 }
00104
00105 }
00106
00107
00108 string Log::getColorCode(int level) {
00109 if (!Log::useShellColors) return "";
00110
00111 if (Log::colorCodes.empty()) {
00112
00113 if (isatty(1)) {
00114
00115 Log::colorCodes[TRACE] = "\033[0;37m";
00116 Log::colorCodes[DEBUG] = "\033[0;36m";
00117 Log::colorCodes[INFO] = "\033[0;32m";
00118 Log::colorCodes[WARN] = "\033[0;33m";
00119 Log::colorCodes[ERROR] = "\033[0;31m";
00120 Log::endColorCode = "\033[0m";
00121 } else {
00122 Log::colorCodes[TRACE] = "";
00123 Log::colorCodes[DEBUG] = "";
00124 Log::colorCodes[INFO] = "";
00125 Log::colorCodes[WARN] = "";
00126 Log::colorCodes[ERROR] = "";
00127 }
00128 }
00129
00130
00131 return colorCodes[level];
00132 }
00133
00134
00135 Log::Level Log::getLevelFromName(const string& level) {
00136 if (level == "TRACE") return TRACE;
00137 if (level == "DEBUG") return DEBUG;
00138 if (level == "INFO") return INFO;
00139 if (level == "WARN") return WARN;
00140 if (level == "ERROR") return ERROR;
00141 throw Error("Couldn't create a log level from string '" + level + "'");
00142 }
00143
00144
00145 string Log::formatMessage(int level, const string& message) {
00146 string out;
00147 if (Log::useShellColors) {
00148 out += getColorCode(level);
00149 }
00150
00151 if (Log::showLoggerName) {
00152 out += getName();
00153 out += ": ";
00154 }
00155
00156 if (Log::showLogLevel) {
00157 out += Log::getLevelName(level);
00158 out += " ";
00159 }
00160
00161 if (Log::showTimestamp) {
00162 time_t rawtime;
00163 time(&rawtime);
00164 char* timestr = ctime(&rawtime);
00165 timestr[24] = ' ';
00166 out += timestr;
00167 out += " ";
00168 }
00169
00170 if (Log::useShellColors) {
00171 out += endColorCode;
00172 }
00173
00174 out += " ";
00175 out += message;
00176
00177 return out;
00178 }
00179
00180
00181 void Log::log(int level, const string& message) {
00182 if (isActive(level)) {
00183 cout << formatMessage(level, message) << endl;
00184 }
00185 }
00186
00187
00188 ostream& operator<<(Log& log, int level) {
00189 if (log.isActive(level)) {
00190 cout << log.formatMessage(level, "");
00191 return cout;
00192 } else {
00193 return *(log._nostream);
00194 }
00195 }
00196
00197 }