00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "rtabmap/utilite/ULogger.h"
00021 #include "rtabmap/utilite/UConversion.h"
00022 #include "rtabmap/utilite/UFile.h"
00023 #include "rtabmap/utilite/UStl.h"
00024 #include "rtabmap/utilite/UEventsManager.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_ = kInfo;
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::kTypeNoLog;
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_ || level == kFatal)
00365 {
00366 time.append("(");
00367 getTime(time);
00368 time.append(") ");
00369 }
00370
00371 std::string levelStr = "";
00372 if(printLevel_ || level == kFatal)
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_ || level == kFatal)
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 >= eventLevel_)
00490 {
00491 std::string fullMsg = uFormat("%s%s%s", levelStr.c_str(), time.c_str(), whereStr.c_str());
00492 va_start(args, msg);
00493 fullMsg.append(uFormatv(msg, args));
00494 va_end(args);
00495 if(level >= exitLevel_)
00496 {
00497
00498
00499 exitingState_ = true;
00500 UEventsManager::post(new ULogEvent(fullMsg, kFatal), false);
00501 }
00502 else
00503 {
00504 UEventsManager::post(new ULogEvent(fullMsg, level));
00505 }
00506 }
00507
00508 if(level >= exitLevel_)
00509 {
00510 printf("\n*******\n%s message occurred! Application will now exit.\n", levelName_[level]);
00511 if(type_ != kTypeConsole)
00512 {
00513 printf(" %s%s%s", levelStr.c_str(), time.c_str(), whereStr.c_str());
00514 va_start(args, msg);
00515 vprintf(msg, args);
00516 va_end(args);
00517 }
00518 printf("\n*******\n");
00519 destroyer_.setDoomed(0);
00520 delete instance_;
00521 instance_ = 0;
00522
00523
00524 exit(1);
00525
00526 }
00527 }
00528 loggerMutex_.unlock();
00529 }
00530
00531 int ULogger::getTime(std::string &timeStr)
00532 {
00533 struct tm timeinfo;
00534 const int bufSize = 30;
00535 char buf[bufSize] = {0};
00536
00537 #if _MSC_VER
00538 time_t rawtime;
00539 time(&rawtime);
00540 localtime_s (&timeinfo, &rawtime );
00541 int result = sprintf_s(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
00542 timeinfo.tm_year+1900,
00543 (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
00544 (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
00545 (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
00546 (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
00547 (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec);
00548 #elif WIN32
00549 time_t rawtime;
00550 time(&rawtime);
00551 timeinfo = *localtime (&rawtime);
00552 int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
00553 timeinfo.tm_year+1900,
00554 (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
00555 (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
00556 (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
00557 (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
00558 (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec);
00559 #else
00560 struct timeval rawtime;
00561 gettimeofday(&rawtime, NULL);
00562 localtime_r (&rawtime.tv_sec, &timeinfo);
00563 int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d.%s%d",
00564 timeinfo.tm_year+1900,
00565 (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
00566 (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
00567 (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
00568 (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
00569 (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec,
00570 (rawtime.tv_usec/1000) < 10 ? "00":(rawtime.tv_usec/1000) < 100?"0":"", int(rawtime.tv_usec/1000));
00571 #endif
00572 if(result)
00573 {
00574 timeStr.append(buf);
00575 }
00576 return result;
00577 }
00578
00579 ULogger* ULogger::getInstance()
00580 {
00581 if(!instance_)
00582 {
00583 instance_ = createInstance();
00584 }
00585 return instance_;
00586 }
00587
00588 ULogger* ULogger::createInstance()
00589 {
00590 ULogger* instance = 0;
00591 if(type_ == ULogger::kTypeConsole)
00592 {
00593 instance = new UConsoleLogger();
00594 }
00595 else if(type_ == ULogger::kTypeFile)
00596 {
00597 instance = new UFileLogger(logFileName_, append_);
00598 }
00599 destroyer_.setDoomed(instance);
00600 return instance;
00601 }
00602
00603 ULogger::~ULogger()
00604 {
00605 instance_ = 0;
00606
00607 }