#include "logger.h" #include "../defines.h" #include #include #include #include typedef enum level_color { COLOR_FATAL, COLOR_ERROR, COLOR_WARN, COLOR_INFO, COLOR_DEBUG, } level_color; void send_to_console(const char *message, level_color color) { const char *color_strings[] = {"41;97", "0;91", "0;93", "0;94", "0;92"}; printf("\033[%sm%s\033[0m\n", color_strings[color], message); } void send_to_error_log(const char *message) { // First we need to open up our log file to append to it FILE *log_file = fopen("./quantum.log", "a"); // Lets make sure we actually opened the file, and if not we return if (log_file == NULL) { send_to_console("[ERROR]: Could not open log file.", COLOR_ERROR); return; } // Now we just need to write our message to the file int chars_written = fprintf(log_file, "%s\n", message); // fprintf returns a negative number on an error so let's check for that and // display an error message if (chars_written < 0) { send_to_console("[ERROR]: Could not write to log file.", COLOR_ERROR); } // Now we need to make sure we close the file so that we do not leak fclose(log_file); } void log_output(log_level level, const char *message, ...) { const char *level_strings[] = { "[FATAL]: ", "[ERROR]: ", "[WARN]: ", "[INFO]: ", "[DEBUG]: "}; // We are going to want to put a timestamp on our logs so lets get the current // time and convert it into localtime time_t cur_time = time(NULL); struct tm local_time = *localtime(&cur_time); // We are going to impose a 32K char limit on a single log entry // we will hold this in format_message as a place to collect all // the variadic arguments and process them together. We make sure // that the memory is cleared to 0 before we start working on it. const i32 msg_length = 32000; char format_message[msg_length]; memset(format_message, 0, sizeof(format_message)); // Now we need to assemble the message from the message + // the variadic arguments __builtin_va_list arg_ptr; va_start(arg_ptr, message); vsnprintf(format_message, msg_length, message, arg_ptr); va_end(arg_ptr); // Now we prepend the message with a timestamp and our message level char log_message[msg_length]; sprintf(log_message, "[%02d-%02d-%d %02d:%02d:%02d]%s%s", local_time.tm_mon + 1, local_time.tm_mday, local_time.tm_year + 1900, local_time.tm_hour, local_time.tm_min, local_time.tm_sec, level_strings[level], format_message); // Now we call the appropriate function depending on the level if (level <= 1) { send_to_console(log_message, level == FATAL ? COLOR_FATAL : COLOR_ERROR); send_to_error_log(log_message); } else { send_to_console(log_message, (level_color)level); } }