Brian Silverman | 9c0f145 | 2015-01-10 21:19:39 -0800 | [diff] [blame^] | 1 | #pragma once |
| 2 | |
| 3 | #include <sstream> |
| 4 | #include <iomanip> |
| 5 | #include <string> |
| 6 | #include <stdio.h> |
| 7 | #include <sys/time.h> |
| 8 | |
| 9 | inline std::string NowTime(); |
| 10 | |
| 11 | enum TLogLevel {logNONE, logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4}; |
| 12 | |
| 13 | class Log |
| 14 | { |
| 15 | public: |
| 16 | Log(); |
| 17 | virtual ~Log(); |
| 18 | std::ostringstream& Get(TLogLevel level = logINFO); |
| 19 | public: |
| 20 | static TLogLevel& ReportingLevel(); |
| 21 | static std::string ToString(TLogLevel level); |
| 22 | static TLogLevel FromString(const std::string& level); |
| 23 | protected: |
| 24 | std::ostringstream os; |
| 25 | private: |
| 26 | Log(const Log&); |
| 27 | Log& operator =(const Log&); |
| 28 | }; |
| 29 | |
| 30 | inline Log::Log() |
| 31 | { |
| 32 | } |
| 33 | |
| 34 | inline std::ostringstream& Log::Get(TLogLevel level) |
| 35 | { |
| 36 | os << "- " << NowTime(); |
| 37 | os << " " << ToString(level) << ": "; |
| 38 | os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t'); |
| 39 | return os; |
| 40 | } |
| 41 | |
| 42 | inline Log::~Log() |
| 43 | { |
| 44 | os << std::endl; |
| 45 | fprintf(stderr, "%s", os.str().c_str()); |
| 46 | fflush(stderr); |
| 47 | } |
| 48 | |
| 49 | inline TLogLevel& Log::ReportingLevel() |
| 50 | { |
| 51 | static TLogLevel reportingLevel = logDEBUG4; |
| 52 | return reportingLevel; |
| 53 | } |
| 54 | |
| 55 | inline std::string Log::ToString(TLogLevel level) |
| 56 | { |
| 57 | static const char* const buffer[] = {"NONE", "ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"}; |
| 58 | return buffer[level]; |
| 59 | } |
| 60 | |
| 61 | inline TLogLevel Log::FromString(const std::string& level) |
| 62 | { |
| 63 | if (level == "DEBUG4") |
| 64 | return logDEBUG4; |
| 65 | if (level == "DEBUG3") |
| 66 | return logDEBUG3; |
| 67 | if (level == "DEBUG2") |
| 68 | return logDEBUG2; |
| 69 | if (level == "DEBUG1") |
| 70 | return logDEBUG1; |
| 71 | if (level == "DEBUG") |
| 72 | return logDEBUG; |
| 73 | if (level == "INFO") |
| 74 | return logINFO; |
| 75 | if (level == "WARNING") |
| 76 | return logWARNING; |
| 77 | if (level == "ERROR") |
| 78 | return logERROR; |
| 79 | if (level == "NONE") |
| 80 | return logNONE; |
| 81 | Log().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default."; |
| 82 | return logINFO; |
| 83 | } |
| 84 | |
| 85 | typedef Log FILELog; |
| 86 | |
| 87 | #define FILE_LOG(level) \ |
| 88 | if (level > FILELog::ReportingLevel()) ; \ |
| 89 | else Log().Get(level) |
| 90 | |
| 91 | inline std::string NowTime() |
| 92 | { |
| 93 | char buffer[11]; |
| 94 | time_t t; |
| 95 | time(&t); |
| 96 | tm * r = gmtime(&t); |
| 97 | strftime(buffer, sizeof(buffer), "%H:%M:%S", r); |
| 98 | struct timeval tv; |
| 99 | gettimeofday(&tv, 0); |
| 100 | char result[100] = {0}; |
| 101 | sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); |
| 102 | return result; |
| 103 | } |