1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| #include "Logger.h" #include "Timestamp.h" #include <mutex> #include <thread> #include <cstdarg> #include <cstring> #include <cstdio> #include <cstdlib> #include <string> namespace mylib {
Logger::LogLevel g_logLevel = Logger::TRACE; bool showMicroseconds = false; bool enableColorLog = true;
static std::mutex g_mutex; static Logger::OutputFunc g_output = [](const char *msg, int len) { fwrite(msg, 1, len, stdout); }; static Logger::FlushFunc g_flush = []() { fflush(stdout); };
__thread char t_errnobuf[512]; __thread char t_time[32]; __thread time_t t_lastSecond;
const char *strerror_tl(int savedErrno) { return strerror_r(savedErrno, t_errnobuf, sizeof(t_errnobuf)); }
static void formatTime(char *buf, size_t size) { time_t now = time(nullptr); if (now != t_lastSecond) { t_lastSecond = now; struct tm tm_time; gmtime_r(&now, &tm_time); snprintf(buf, size, "%4d%02d%02d %02d:%02d:%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); } }
static const char *levelNames[] = { mylib::enableColorLog ? "\033[36mTRACE\033[0m" : "TRACE", mylib::enableColorLog ? "\033[34mDEBUG\033[0m" : "DEBUG", mylib::enableColorLog ? "\033[32mINFO\033[0m" : "INFO", mylib::enableColorLog ? "\033[33mWARN\033[0m" : "WARN", mylib::enableColorLog ? "\033[31mERROR\033[0m" : "ERROR", mylib::enableColorLog ? "\033[35mFATAL\033[0m" : "FATAL", }; void Logger::log(SourceFile file, int line, LogLevel level, const char *fmt, ...) { if (level < g_logLevel) return;
std::string time_buf; Timestamp timestamp = Timestamp::now(); time_buf = timestamp.toFormattedString(showMicroseconds);
char msg_buf[1024]; va_list args; va_start(args, fmt); vsnprintf(msg_buf, sizeof(msg_buf), fmt, args); va_end(args);
char line_buf[2048]; snprintf(line_buf, sizeof(line_buf), "[%s][%s] %s:%d: %s\n", time_buf.c_str(), levelNames[level], file.data_, line, msg_buf);
std::lock_guard<std::mutex> lock(g_mutex); g_output(line_buf, strlen(line_buf)); g_flush(); if (level == FATAL) abort(); }
void Logger::log(SourceFile file, int line, LogLevel level, const char *func, const char *fmt, ...) { if (level < g_logLevel) return;
std::string time_buf; Timestamp timestamp = Timestamp::now(); time_buf = timestamp.toFormattedString(showMicroseconds);
char msg_buf[1024]; va_list args; va_start(args, fmt); vsnprintf(msg_buf, sizeof(msg_buf), fmt, args); va_end(args);
char line_buf[2048]; snprintf(line_buf, sizeof(line_buf), "[%s][%s] %s %s:%d: %s\n", time_buf.c_str(), levelNames[level], func, file.data_, line, msg_buf);
std::lock_guard<std::mutex> lock(g_mutex); g_output(line_buf, strlen(line_buf)); g_flush(); if (level == FATAL) abort(); }
void Logger::logSys(SourceFile file, int line, bool fatal, const char *fmt, ...) { int savedErrno = errno; LogLevel level = fatal ? FATAL : ERROR; if (level < g_logLevel) return;
std::string time_buf; Timestamp timestamp = Timestamp::now(); time_buf = timestamp.toFormattedString(showMicroseconds);
char msg_buf[1024]; va_list args; va_start(args, fmt); vsnprintf(msg_buf, sizeof(msg_buf), fmt, args); va_end(args);
char line_buf[2048]; snprintf(line_buf, sizeof(line_buf), "[%s][%s] %s:%d: %s (errno=%d: %s)\n", time_buf.c_str(), levelNames[level], file.data_, line, msg_buf, savedErrno, strerror_tl(savedErrno));
std::lock_guard<std::mutex> lock(g_mutex); g_output(line_buf, strlen(line_buf)); g_flush(); if (fatal) abort(); }
Logger::LogLevel Logger::logLevel() { return g_logLevel; }
void Logger::setLogLevel(LogLevel level) { g_logLevel = level; }
void Logger::setOutput(OutputFunc output) { std::lock_guard<std::mutex> lock(g_mutex); g_output = output; }
void Logger::setFlush(FlushFunc flush) { std::lock_guard<std::mutex> lock(g_mutex); g_flush = flush; } };
|