00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "find_object/utilite/ULogger.h"
00021
00022 #include "utilite/UConversion.h"
00023 #include "utilite/UFile.h"
00024 #include "utilite/UStl.h"
00025 #include <fstream>
00026 #include <string>
00027 #include <string.h>
00028
00029 #ifndef WIN32
00030 #include <sys/time.h>
00031 #endif
00032
00033 #ifdef WIN32
00034 #include <Windows.h>
00035 #define COLOR_NORMAL FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
00036 #define COLOR_RED FOREGROUND_RED | FOREGROUND_INTENSITY
00037 #define COLOR_GREEN FOREGROUND_GREEN
00038 #define COLOR_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
00039 #else
00040 #define COLOR_NORMAL "\033[0m"
00041 #define COLOR_RED "\033[31m"
00042 #define COLOR_GREEN "\033[32m"
00043 #define COLOR_YELLOW "\033[33m"
00044 #endif
00045
00046 bool ULogger::append_ = true;
00047 bool ULogger::printTime_ = true;
00048 bool ULogger::printLevel_ = true;
00049 bool ULogger::printEndline_ = true;
00050 bool ULogger::printColored_ = true;
00051 bool ULogger::printWhere_ = true;
00052 bool ULogger::printWhereFullPath_ = false;
00053 bool ULogger::limitWhereLength_ = false;
00054 bool ULogger::buffered_ = false;
00055 bool ULogger::exitingState_ = false;
00056 ULogger::Level ULogger::level_ = kWarning;
00057 ULogger::Level ULogger::exitLevel_ = kFatal;
00058 ULogger::Level ULogger::eventLevel_ = kFatal;
00059 const char * ULogger::levelName_[5] = {"DEBUG", " INFO", " WARN", "ERROR", "FATAL"};
00060 ULogger* ULogger::instance_ = 0;
00061 UDestroyer<ULogger> ULogger::destroyer_;
00062 ULogger::Type ULogger::type_ = ULogger::kTypeConsole;
00063 UMutex ULogger::loggerMutex_;
00064 const std::string ULogger::kDefaultLogFileName = "./ULog.txt";
00065 std::string ULogger::logFileName_;
00066 std::string ULogger::bufferedMsgs_;
00067
00074 class UConsoleLogger : public ULogger
00075 {
00076 public :
00077 virtual ~UConsoleLogger() {this->_flush();}
00078
00079 protected:
00084 friend class ULogger;
00085
00086 UConsoleLogger() {}
00087
00088 private:
00089 virtual void _write(const char* msg, va_list arg)
00090 {
00091 vprintf(msg, arg);
00092 }
00093 virtual void _writeStr(const char* msg)
00094 {
00095 printf("%s", msg);
00096 }
00097 };
00098
00105 class UFileLogger : public ULogger
00106 {
00107 public:
00108 virtual ~UFileLogger()
00109 {
00110 this->_flush();
00111 if(fout_)
00112 {
00113 fclose(fout_);
00114 }
00115 }
00116
00117 protected:
00122 friend class ULogger;
00123
00131 UFileLogger(const std::string &fileName, bool append)
00132 {
00133 fileName_ = fileName;
00134
00135 if(!append) {
00136 std::ofstream fileToClear(fileName_.c_str(), std::ios::out);
00137 fileToClear.clear();
00138 fileToClear.close();
00139 }
00140
00141 #ifdef _MSC_VER
00142 fopen_s(&fout_, fileName_.c_str(), "a");
00143 #else
00144 fout_ = fopen(fileName_.c_str(), "a");
00145 #endif
00146
00147 if(!fout_) {
00148 printf("FileLogger : Cannot open file : %s\n", fileName_.c_str());
00149 return;
00150 }
00151 }
00152
00153 private:
00154 virtual void _write(const char* msg, va_list arg)
00155 {
00156 if(fout_)
00157 {
00158 vfprintf(fout_, msg, arg);
00159 }
00160 }
00161 virtual void _writeStr(const char* msg)
00162 {
00163 if(fout_)
00164 {
00165 fprintf(fout_, "%s", msg);
00166 }
00167 }
00168
00169 private:
00170 std::string fileName_;
00171 FILE* fout_;
00172 std::string bufferedMsgs_;
00173 };
00174
00175 void ULogger::setType(Type type, const std::string &fileName, bool append)
00176 {
00177 ULogger::flush();
00178 loggerMutex_.lock();
00179 {
00180
00181 if(!instance_)
00182 {
00183 type_ = type;
00184 logFileName_ = fileName;
00185 append_ = append;
00186 instance_ = createInstance();
00187 }
00188
00189 else if(type_ != type || (type_ == kTypeFile && logFileName_.compare(fileName)!=0))
00190 {
00191 destroyer_.setDoomed(0);
00192 delete instance_;
00193 instance_ = 0;
00194 type_ = type;
00195 logFileName_ = fileName;
00196 append_ = append;
00197 instance_ = createInstance();
00198 }
00199 }
00200 loggerMutex_.unlock();
00201 }
00202
00203 void ULogger::reset()
00204 {
00205 ULogger::setType(ULogger::kTypeNoLog);
00206 append_ = true;
00207 printTime_ = true;
00208 printLevel_ = true;
00209 printEndline_ = true;
00210 printColored_ = true;
00211 printWhere_ = true;
00212 printWhereFullPath_ = false;
00213 limitWhereLength_ = false;
00214 level_ = kInfo;
00215 logFileName_ = ULogger::kDefaultLogFileName;
00216 }
00217
00218 void ULogger::setBuffered(bool buffered)
00219 {
00220 if(!buffered)
00221 {
00222 ULogger::flush();
00223 }
00224 buffered_ = buffered;
00225 }
00226
00227
00228 void ULogger::flush()
00229 {
00230 loggerMutex_.lock();
00231 if(!instance_ || bufferedMsgs_.size()==0)
00232 {
00233 loggerMutex_.unlock();
00234 return;
00235 }
00236
00237 instance_->_flush();
00238 loggerMutex_.unlock();
00239 }
00240
00241 void ULogger::_flush()
00242 {
00243 ULogger::getInstance()->_writeStr(bufferedMsgs_.c_str());
00244 bufferedMsgs_.clear();
00245 }
00246
00247 void ULogger::write(const char* msg, ...)
00248 {
00249 loggerMutex_.lock();
00250 if(!instance_)
00251 {
00252 loggerMutex_.unlock();
00253 return;
00254 }
00255
00256 std::string endline = "";
00257 if(printEndline_) {
00258 endline = "\r\n";
00259 }
00260
00261 std::string time = "";
00262 if(printTime_)
00263 {
00264 getTime(time);
00265 time.append(" - ");
00266 }
00267
00268
00269 if(printTime_)
00270 {
00271 if(buffered_)
00272 {
00273 bufferedMsgs_.append(time.c_str());
00274 }
00275 else
00276 {
00277 ULogger::getInstance()->_writeStr(time.c_str());
00278 }
00279 }
00280
00281 va_list args;
00282 va_start(args, msg);
00283 if(buffered_)
00284 {
00285 bufferedMsgs_.append(uFormatv(msg, args));
00286 }
00287 else
00288 {
00289 ULogger::getInstance()->_write(msg, args);
00290 }
00291 va_end(args);
00292 if(printEndline_)
00293 {
00294 if(buffered_)
00295 {
00296 bufferedMsgs_.append(endline.c_str());
00297 }
00298 else
00299 {
00300 ULogger::getInstance()->_writeStr(endline.c_str());
00301 }
00302 }
00303 loggerMutex_.unlock();
00304
00305 }
00306
00307 void ULogger::write(ULogger::Level level,
00308 const char * file,
00309 int line,
00310 const char * function,
00311 const char* msg,
00312 ...)
00313 {
00314 if(exitingState_)
00315 {
00316
00317 return;
00318 }
00319 loggerMutex_.lock();
00320 if(type_ == kTypeNoLog && level < kFatal)
00321 {
00322 loggerMutex_.unlock();
00323 return;
00324 }
00325 if(strlen(msg) == 0 && !printWhere_ && level < exitLevel_)
00326 {
00327 loggerMutex_.unlock();
00328
00329 return;
00330 }
00331
00332 if(level >= level_)
00333 {
00334 #ifdef WIN32
00335 int color = 0;
00336 #else
00337 const char* color = NULL;
00338 #endif
00339 switch(level)
00340 {
00341 case kDebug:
00342 color = COLOR_GREEN;
00343 break;
00344 case kInfo:
00345 color = COLOR_NORMAL;
00346 break;
00347 case kWarning:
00348 color = COLOR_YELLOW;
00349 break;
00350 case kError:
00351 case kFatal:
00352 color = COLOR_RED;
00353 break;
00354 default:
00355 break;
00356 }
00357
00358 std::string endline = "";
00359 if(printEndline_) {
00360 endline = "\r\n";
00361 }
00362
00363 std::string time = "";
00364 if(printTime_)
00365 {
00366 time.append("(");
00367 getTime(time);
00368 time.append(") ");
00369 }
00370
00371 std::string levelStr = "";
00372 if(printLevel_)
00373 {
00374 const int bufSize = 30;
00375 char buf[bufSize] = {0};
00376
00377 #ifdef _MSC_VER
00378 sprintf_s(buf, bufSize, "[%s]", levelName_[level]);
00379 #else
00380 snprintf(buf, bufSize, "[%s]", levelName_[level]);
00381 #endif
00382 levelStr = buf;
00383 levelStr.append(" ");
00384 }
00385
00386 std::string whereStr = "";
00387 if(printWhere_)
00388 {
00389 whereStr.append("");
00390
00391 if(printWhereFullPath_)
00392 {
00393 whereStr.append(file);
00394 }
00395 else
00396 {
00397 std::string fileName = UFile::getName(file);
00398 if(limitWhereLength_ && fileName.size() > 8)
00399 {
00400 fileName.erase(8);
00401 fileName.append("~");
00402 }
00403 whereStr.append(fileName);
00404 }
00405
00406
00407 whereStr.append(":");
00408 std::string lineStr = uNumber2Str(line);
00409 whereStr.append(lineStr);
00410
00411
00412 whereStr.append("::");
00413 std::string funcStr = function;
00414 if(!printWhereFullPath_ && limitWhereLength_ && funcStr.size() > 8)
00415 {
00416 funcStr.erase(8);
00417 funcStr.append("~");
00418 }
00419 funcStr.append("()");
00420 whereStr.append(funcStr);
00421
00422 whereStr.append(" ");
00423 }
00424
00425 va_list args;
00426
00427 if(type_ != kTypeNoLog)
00428 {
00429 va_start(args, msg);
00430 #ifdef WIN32
00431 HANDLE H = GetStdHandle(STD_OUTPUT_HANDLE);
00432 #endif
00433 if(type_ == ULogger::kTypeConsole && printColored_)
00434 {
00435 #ifdef WIN32
00436 SetConsoleTextAttribute(H,color);
00437 #else
00438 if(buffered_)
00439 {
00440 bufferedMsgs_.append(color);
00441 }
00442 else
00443 {
00444 ULogger::getInstance()->_writeStr(color);
00445 }
00446 #endif
00447 }
00448
00449 if(buffered_)
00450 {
00451 bufferedMsgs_.append(levelStr.c_str());
00452 bufferedMsgs_.append(time.c_str());
00453 bufferedMsgs_.append(whereStr.c_str());
00454 bufferedMsgs_.append(uFormatv(msg, args));
00455 }
00456 else
00457 {
00458 ULogger::getInstance()->_writeStr(levelStr.c_str());
00459 ULogger::getInstance()->_writeStr(time.c_str());
00460 ULogger::getInstance()->_writeStr(whereStr.c_str());
00461 ULogger::getInstance()->_write(msg, args);
00462 }
00463 if(type_ == ULogger::kTypeConsole && printColored_)
00464 {
00465 #ifdef WIN32
00466 SetConsoleTextAttribute(H,COLOR_NORMAL);
00467 #else
00468 if(buffered_)
00469 {
00470 bufferedMsgs_.append(COLOR_NORMAL);
00471 }
00472 else
00473 {
00474 ULogger::getInstance()->_writeStr(COLOR_NORMAL);
00475 }
00476 #endif
00477 }
00478 if(buffered_)
00479 {
00480 bufferedMsgs_.append(endline.c_str());
00481 }
00482 else
00483 {
00484 ULogger::getInstance()->_writeStr(endline.c_str());
00485 }
00486 va_end (args);
00487 }
00488
00489 if(level >= exitLevel_)
00490 {
00491 printf("\n*******\n%s message occurred! Application will now exit.\n", levelName_[level]);
00492 if(type_ != kTypeConsole)
00493 {
00494 printf(" %s%s%s\n", levelStr.c_str(), time.c_str(), whereStr.c_str());
00495 va_start(args, msg);
00496 vprintf(msg, args);
00497 va_end(args);
00498 }
00499 printf("*******\n");
00500 destroyer_.setDoomed(0);
00501 delete instance_;
00502 instance_ = 0;
00503
00504
00505 exit(1);
00506
00507 }
00508 }
00509 loggerMutex_.unlock();
00510 }
00511
00512 int ULogger::getTime(std::string &timeStr)
00513 {
00514 if(!printTime_) {
00515 return 0;
00516 }
00517 struct tm timeinfo;
00518 const int bufSize = 30;
00519 char buf[bufSize] = {0};
00520
00521 #if _MSC_VER
00522 time_t rawtime;
00523 time(&rawtime);
00524 localtime_s (&timeinfo, &rawtime );
00525 int result = sprintf_s(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
00526 timeinfo.tm_year+1900,
00527 (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
00528 (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
00529 (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
00530 (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
00531 (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec);
00532 #elif WIN32
00533 time_t rawtime;
00534 time(&rawtime);
00535 timeinfo = *localtime (&rawtime);
00536 int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
00537 timeinfo.tm_year+1900,
00538 (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
00539 (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
00540 (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
00541 (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
00542 (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec);
00543 #else
00544 struct timeval rawtime;
00545 gettimeofday(&rawtime, NULL);
00546 localtime_r (&rawtime.tv_sec, &timeinfo);
00547 int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d.%s%d",
00548 timeinfo.tm_year+1900,
00549 (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
00550 (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
00551 (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
00552 (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
00553 (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec,
00554 (rawtime.tv_usec/1000) < 10 ? "00":(rawtime.tv_usec/1000) < 100?"0":"", int(rawtime.tv_usec/1000));
00555 #endif
00556 if(result)
00557 {
00558 timeStr.append(buf);
00559 }
00560 return result;
00561 }
00562
00563 ULogger* ULogger::getInstance()
00564 {
00565 if(!instance_)
00566 {
00567 instance_ = createInstance();
00568 }
00569 return instance_;
00570 }
00571
00572 ULogger* ULogger::createInstance()
00573 {
00574 ULogger* instance = 0;
00575 if(type_ == ULogger::kTypeConsole)
00576 {
00577 instance = new UConsoleLogger();
00578 }
00579 else if(type_ == ULogger::kTypeFile)
00580 {
00581 instance = new UFileLogger(logFileName_, append_);
00582 }
00583 destroyer_.setDoomed(instance);
00584 return instance;
00585 }
00586
00587 ULogger::~ULogger()
00588 {
00589 instance_ = 0;
00590
00591 }