#include #include #include #include #include #include #include #define LOG_LINE_SIZE 1024 enum LogLevel { LOG_INFO, LOG_WARN, }; char g_log_buff[LOG_LINE_SIZE]; void log_msg_to_buff(char *out, int size, enum LogLevel level, bool colored, const char *format, va_list args) { assert(out); assert(size); assert(level == LOG_INFO || level == LOG_WARN); assert(format); struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); long msec = ts.tv_nsec / 1000000; struct tm tm = *localtime(&ts.tv_sec); pid_t pid = getpid(); char *level_str = NULL; switch (level) { case LOG_INFO: level_str = "INFO"; break; case LOG_WARN: level_str = "WARN"; break; default: assert(false); } char *color_code = NULL; if (colored) { switch (level) { case LOG_INFO: color_code = "\033[1;32m"; break; case LOG_WARN: color_code = "\033[1;33m"; break; default: assert(false); } } // Imitate formatting style configured in 'salis.py' int col = snprintf( out, size, "%s%d-%02d-%02d %02d:%02d:%02d,%03ld %07d [%s]%s ", colored ? color_code : "", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, msec, pid, level_str, colored ? "\033[0m" : "" ); vsnprintf(out + col, size - col, format, args); } void log_msg(enum LogLevel level, bool colored, const char *format, va_list args) { assert(level == LOG_INFO || level == LOG_WARN); assert(format); log_msg_to_buff(g_log_buff, LOG_LINE_SIZE, level, colored, format, args); printf("\r%s\n", g_log_buff); } void log_info(const char *format, ...) { assert(format); va_list args; va_start(args, format); log_msg(LOG_INFO, true, format, args); va_end(args); } void log_warn(const char *format, ...) { assert(format); va_list args; va_start(args, format); log_msg(LOG_WARN, true, format, args); va_end(args); }