util/Log.cpp

Go to the documentation of this file.
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