00001 /*---------------------------------------------------------------------------- 00002 Name: Log.cpp 00003 Project: xmlBlaster.org 00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 00005 Comment: Handling the Client data 00006 ----------------------------------------------------------------------------*/ 00007 #include <util/Log.h> 00008 #include <iostream> 00009 #include <ctime> //<time.h> 00010 #include <cstdlib> //<stdlib.h> 00011 #include <util/lexical_cast.h> 00012 #include <util/PropertyDef.h> 00013 00014 using namespace std; 00015 00016 namespace org { namespace xmlBlaster { 00017 namespace util { 00018 00019 const char* const Log::ESC = "\033[0m"; 00020 const char* const Log::BOLD = "\033[1m"; 00021 const char* const Log::RED_BLACK = "\033[31;40m"; 00022 const char* const Log::GREEN_BLACK = "\033[32;40m"; 00023 const char* const Log::YELLOW_BLACK = "\033[33;40m"; 00024 const char* const Log::BLUE_BLACK = "\033[34;40m"; 00025 const char* const Log::PINK_BLACK = "\033[35;40m"; 00026 const char* const Log::LTGREEN_BLACK= "\033[36;40m"; 00027 const char* const Log::WHITE_BLACK = "\033[37;40m"; 00028 const char* const Log::WHITE_RED = "\033[37;41m"; 00029 const char* const Log::BLACK_RED = "\033[30;41m"; 00030 const char* const Log::BLACK_GREEN = "\033[40;42m"; 00031 const char* const Log::BLACK_PINK = "\033[40;45m"; 00032 const char* const Log::BLACK_LTGREEN= "\033[40;46m"; 00033 00034 00035 00039 Log::Log(Property& properties, int /*args*/, const char * const /*argc*/[], const string& name) 00040 : withXtermColor_(true), properties_(properties), name_(name) 00041 { 00042 ME = "Log"; 00043 # ifdef _WIN32 00044 withXtermColor_ = false; 00045 # endif 00046 withXtermColor_ = properties.getBoolProperty("xmlBlaster.withXtermColor", withXtermColor_, true); 00047 call_ = true; 00048 time_ = true; 00049 trace_ = true; 00050 dump_ = true; 00051 numWarnInvocations = 0; 00052 numErrorInvocations = 0; 00053 currentLogFormat = "{0} {1} {2}: {3}"; 00054 logFormatPropertyRead = false; 00055 logLevel_ = L_PANIC | L_ERROR | L_WARN | L_INFO; 00056 00057 timeE = string(LTGREEN_BLACK) + "TIME " + ESC; 00058 callE = string(BLACK_LTGREEN) + "CALL " + ESC; 00059 traceE = string(WHITE_BLACK ) + "TRACE" + ESC; 00060 plainE = string(WHITE_BLACK ) + " " + ESC; 00061 infoE = string(GREEN_BLACK ) + "INFO " + ESC; 00062 warnE = string(YELLOW_BLACK ) + "WARN " + ESC; 00063 errorE = string(RED_BLACK ) + "ERROR" + ESC; 00064 panicE = string(BLACK_RED ) + "PANIC" + ESC; 00065 exitE = string(GREEN_BLACK ) + "EXIT " + ESC; 00066 00067 timeX = "TIME "; 00068 callX = "CALL "; 00069 traceX = "TRACE"; 00070 plainX = " "; 00071 infoX = "INFO "; 00072 warnX = "WARN "; 00073 errorX = "ERROR"; 00074 panicX = "PANIC"; 00075 exitX = "EXIT "; 00076 } 00077 00078 00079 Log::~Log() { 00080 } 00081 00082 void Log::exitLow(int val) { 00083 // gcc 3.x: The functions abort, exit, _Exit and _exit are recognized and presumed not to return, 00084 // but otherwise are not built in. 00085 // _exit is not recognized in strict ISO C mode (`-ansi', `-std=c89' or `-std=c99'). 00086 // _Exit is not recognized in strict C89 mode (`-ansi' or `-std=c89'). 00087 # if defined(__ICC) 00088 ::exit(val); 00089 # elif __GNUC__==3 00090 ::exit(val); 00091 # elif defined(__sun) 00092 ::exit(val); 00093 # else 00094 ::_exit(val); 00095 # endif 00096 } 00097 00098 void Log::setWithXtermColor(bool val /* = true */) { 00099 withXtermColor_ = val; 00100 } 00101 00102 void Log::setDefaultLogLevel() { 00103 logLevel_ = L_PANIC | L_ERROR | L_WARN | L_INFO; 00104 setPreLogLevelCheck(); 00105 } 00106 00107 00108 void Log::setLogLevel(int level) { 00109 logLevel_ = level; 00110 setPreLogLevelCheck(); 00111 } 00112 00113 void Log::setLogLevel(int argc, const char * const args[]) { 00114 if ((properties_.findArgument(argc, args, "-?") > 0) || 00115 (properties_.findArgument(argc, args, "-h") > 0)) { 00116 std::cout << usage() << std::endl; 00117 return; 00118 } 00119 initialize(); 00120 } 00121 00122 00123 void Log::removeLogLevel(string logLevel) { 00124 int level = logLevelToBit(logLevel); 00125 logLevel_ = (logLevel_ & ~level); 00126 setPreLogLevelCheck(); 00127 } 00128 00129 00130 void Log::addLogLevel(string logLevel) { 00131 int level = logLevelToBit(logLevel); 00132 logLevel_ = (logLevel_ | level); 00133 setPreLogLevelCheck(); 00134 //std::cout << "DEBUG: " << "Adding logLevel '" << logLevel << "' level=" << level << " dump=" << dump_ << std::endl; 00135 } 00136 00137 00138 void Log::setPreLogLevelCheck() { 00139 call_ = time_ = trace_ = dump_ = false; 00140 if (logLevel_ & L_CALL) call_ = true; 00141 if (logLevel_ & L_TIME ) time_ = true; 00142 if (logLevel_ & L_TRACE) trace_ = true; 00143 if (logLevel_ & L_DUMP ) dump_ = true; 00144 } 00145 00146 00147 string Log::bitToLogLevel(int level) const { 00148 string sb = ""; 00149 if (level & L_PANIC) sb += "PANIC"; 00150 if (level & L_ERROR) sb += " | ERROR"; 00151 if (level & L_WARN ) sb += " | WARN"; 00152 if (level & L_INFO ) sb += " | INFO"; 00153 if (level & L_CALL) sb += " | CALL"; 00154 if (level & L_TIME ) sb += " | TIME"; 00155 if (level & L_TRACE) sb += " | TRACE"; 00156 if (level & L_DUMP ) sb += " | DUMP"; 00157 return sb; 00158 } 00159 00160 00161 void Log::panic(const string &instance, const string &text) { 00162 if (logLevel_ & L_PANIC) { 00163 if (withXtermColor_) 00164 log(panicE, L_PANIC, instance, text); 00165 else 00166 log(panicX, L_PANIC, instance, text); 00167 cerr << text << endl; 00168 numErrorInvocations++; 00169 // displayStatistics(); 00170 exitLow(1); 00171 } 00172 } 00173 00174 00175 void Log::exit(const string &instance, const string &text) { 00176 if (withXtermColor_) 00177 log(exitE, L_EXIT, instance, text); 00178 else 00179 log(exitX, L_EXIT, instance, text); 00180 displayStatistics(); 00181 exitLow(0); 00182 } 00183 00184 00185 void Log::info(const string &instance, const string &text) { 00186 if (logLevel_ & L_INFO) { 00187 if (withXtermColor_) 00188 log(infoE, L_INFO, instance, text); 00189 else 00190 log(infoX, L_INFO, instance, text); 00191 } 00192 } 00193 00194 00195 void Log::warn(const string &instance, const string &text) { 00196 if(logLevel_ & L_WARN) { 00197 numWarnInvocations++; 00198 if (withXtermColor_) 00199 log(warnE, L_WARN, instance, text); 00200 else 00201 log(warnX, L_WARN, instance, text); 00202 } 00203 } 00204 00205 00206 void Log::error(const string &instance, const string &text) { 00207 if(logLevel_ & L_PANIC) { 00208 numErrorInvocations++; 00209 if (withXtermColor_) 00210 log(errorE, L_ERROR, instance, text); 00211 else 00212 log(errorX, L_ERROR, instance, text); 00213 } 00214 } 00215 00216 00217 void Log::plain(const string &/*instance*/, const string &text) { 00218 log("", L_PLAIN, "", text); 00219 } 00220 00221 00222 void Log::dump(const string &instance, const string &text) { 00223 if((logLevel_ & L_DUMP) != 0) { 00224 log("", L_DUMP, instance, text); 00225 // log("", L_DUMP, instance, Memory.getStatistic()); 00226 } 00227 } 00228 00229 00230 void Log::trace(const string &instance, const string &text) { 00231 if(logLevel_ & L_TRACE) { 00232 if (withXtermColor_) 00233 log(traceE, L_TRACE, instance, text); 00234 else 00235 log(traceX, L_TRACE, instance, text); 00236 } 00237 } 00238 00239 00240 void Log::call(const string &instance, const string &text) { 00241 if(logLevel_ & L_CALL) { 00242 if (withXtermColor_) 00243 log(callE, L_CALL, instance, text); 00244 else 00245 log(callX, L_CALL, instance, text); 00246 } 00247 } 00248 00249 00250 void Log::time(const string &instance, const string &text) { 00251 if(logLevel_ & L_TIME) { 00252 if (withXtermColor_) 00253 log(timeE, L_TIME, instance, text); 00254 else 00255 log(timeX, L_TIME, instance, text); 00256 } 00257 } 00258 00259 void Log::log(const string &levelStr, int level, const string &instance, 00260 const string &text) { 00261 if (logFormatPropertyRead == false) { 00262 initialize(); 00263 } 00264 00265 string logFormat; 00266 if(level & L_DUMP) 00267 logFormat = "{3}"; 00268 else 00269 logFormat = currentLogFormat; 00270 00271 string logEntry = levelStr + " "; 00272 if (level & L_TIME) logEntry += getTime() + ": "; 00273 if ((level & L_ERROR) || (level & L_WARN) || (level & L_PANIC)) 00274 cerr << logEntry << instance << " " << text << endl; 00275 else 00276 cout << logEntry << instance << " " << text << endl; 00277 } 00278 00279 std::string Log::usage() const { 00280 std::string text = string(""); 00281 text += string("\nLogging options:"); 00282 text += string("\n -trace true Show code trace."); 00283 text += string("\n -dump true Dump internal state."); 00284 text += string("\n -call true Show important method entries"); 00285 text += string("\n -time true Display some performance data."); 00286 //text += string("\n -logFile <fileName> Log to given file instead to console."); 00287 return text; 00288 } 00289 00290 00291 void Log::displayStatistics() { 00292 // Log.info(ME, Memory.getStatistic()); 00293 if (withXtermColor_) { 00294 if (numErrorInvocations>0) { 00295 info(ME, string(BLACK_RED) + "There were " + lexical_cast<std::string>(numErrorInvocations) + 00296 " ERRORS and " + lexical_cast<std::string>(numWarnInvocations) + " WARNINGS" + ESC); 00297 } 00298 else if (numWarnInvocations>0) { 00299 info(ME, string(BLACK_PINK) + "There were " + lexical_cast<std::string>(numErrorInvocations) + 00300 " ERRORS and " + lexical_cast<std::string>(numWarnInvocations) + " WARNINGS" + ESC); 00301 } 00302 else { 00303 info(ME, string(BLACK_GREEN) + "No errors/warnings were reported" + ESC); 00304 } 00305 } 00306 else { 00307 if (numErrorInvocations>0 || numWarnInvocations>0) { 00308 info(ME, string("There were ") + lexical_cast<std::string>(numErrorInvocations) + " ERRORS and " + (lexical_cast<std::string>(numWarnInvocations)) + " WARNINGS"); 00309 } 00310 else 00311 info(ME, "No errors/warnings were reported"); 00312 } 00313 } 00314 00315 00316 void Log::printStack() { 00317 cerr << "sorry, no Stack aviable" << endl; 00318 } 00319 00320 00321 00322 void Log::initSpecificTrace(const string& trace, const string& traceId) 00323 { 00324 if (properties_.propertyExists(trace + "[" + name_ + "]")) { 00325 if (properties_.getBoolProperty(trace + "[" + name_ + "]", false)) 00326 addLogLevel(traceId); 00327 else removeLogLevel(traceId); 00328 return; 00329 } 00330 if (properties_.propertyExists(trace)) { 00331 if (properties_.getBoolProperty(trace, false)) 00332 addLogLevel(traceId); 00333 else removeLogLevel(traceId); 00334 } 00335 } 00336 00337 00338 void Log::initialize() { 00339 setPreLogLevelCheck(); 00340 logFormatPropertyRead = true; 00341 // Given flag -info switches off Log.info messages: 00342 initSpecificTrace("info", "INFO"); 00343 initSpecificTrace("warn", "WARN"); 00344 initSpecificTrace("error", "ERROR"); 00345 initSpecificTrace("call", "CALL"); 00346 initSpecificTrace("time", "TIME"); 00347 initSpecificTrace("trace", "TRACE"); 00348 initSpecificTrace("dump", "DUMP"); 00349 00350 if (properties_.getBoolProperty("+call", false)) 00351 addLogLevel("CALL"); 00352 if (properties_.getBoolProperty("+time", false)) 00353 addLogLevel("TIME"); 00354 if (properties_.getBoolProperty("+trace", false)) 00355 addLogLevel("TRACE"); 00356 if (properties_.getBoolProperty("+dump", false)) 00357 addLogLevel("DUMP"); 00358 00359 // format: {0}:{1}:{2}:{3} <timestamp>:<levelStr>:<instance>:<text> 00360 currentLogFormat = properties_.getStringProperty("LogFormat", 00361 currentLogFormat); 00362 00363 //std::cout << "DEBUG: " << "Current logLevel for [" << name_ << "] is " << bitToLogLevel(logLevel_) << std::endl; 00364 00365 // string tmp = properties_.getStringProperty("LogFormat.Date","MEDIUM"); 00366 // if (tmp == "SHORT") lookAndFeelDate = java.text.DateFormat.SHORT; 00367 // else if (tmp.equals("MEDIUM")) 00368 // lookAndFeelDate = java.text.DateFormat.MEDIUM; 00369 // else if (tmp.equals("LONG")) 00370 // lookAndFeelDate = java.text.DateFormat.LONG; 00371 // else if (tmp.equals("FULL")) 00372 // lookAndFeelDate = java.text.DateFormat.FULL; 00373 // tmp = properties_.getStringProperty("LogFormat.Time","MEDIUM"); 00374 // if (tmp.equals("SHORT")) 00375 // lookAndFeelTime = java.text.DateFormat.SHORT; 00376 // else if (tmp.equals("MEDIUM")) 00377 // lookAndFeelTime = java.text.DateFormat.MEDIUM; 00378 // else if (tmp.equals("LONG")) 00379 // lookAndFeelTime = java.text.DateFormat.LONG; 00380 // else if (tmp.equals("FULL")) 00381 // lookAndFeelTime = java.text.DateFormat.FULL; 00382 00383 // string la = properties_.getStringProperty("LogFormat.Language",""); 00384 // string co = properties_.getStringProperty("LogFormat.Country", ""); 00385 // if (la != null && co != null) country = new Locale(la, co); 00386 00387 // String fileName = properties_.getProperty("logFile", (String)null); 00388 // if (fileName != null) 00389 // Log.logToFile(fileName); 00390 } 00391 00392 00393 string Log::getTime() { 00394 // adapt it here to the correct time format (locales) ?! 00395 time_t theTime; 00396 ::time(&theTime); 00397 string timeStr = ctime(&theTime), ret; 00398 // eliminate new lines (if any) 00399 string::size_type pos = timeStr.find("\n"); 00400 if (pos == string::npos) return timeStr; 00401 ret.assign(timeStr, 0, pos); 00402 return ret; 00403 } 00404 00405 }}} // end of namespace 00406 00407 00408 00409 00410 00411