diff --git a/core/src/CMakeLists.txt b/core/src/CMakeLists.txt index 96928a7..44a02ce 100644 --- a/core/src/CMakeLists.txt +++ b/core/src/CMakeLists.txt @@ -1,4 +1,5 @@ set(CORE_SRC + log.c hash_table.c http_server.c core.c diff --git a/core/src/log.c b/core/src/log.c new file mode 100644 index 0000000..9bd46c6 --- /dev/null +++ b/core/src/log.c @@ -0,0 +1,105 @@ +#include "log.h" +#include +#include +#include +#include +#include +#include + +logger_t *g_core_logger; + +void logger_init(const char *filename) { + g_core_logger = (logger_t *)calloc(1, sizeof(logger_t)); + assert(g_core_logger != NULL); + + if (filename) { + FILE *file = fopen(filename, "w"); + assert(file != NULL); + + g_core_logger->log_file = file; + } + + g_core_logger->time = clock(); +} + +void logger_msg(log_level_e level, const char *filename, const char *msg, ...) { + // formate string + // write to file if available + // print to console + size_t str_len = 0; + char *level_str; + char *color; + char *fmt_msg; + char *output_msg; + va_list args, args_cpy; + int32_t curr_time = (clock() - g_core_logger->time) / CLOCKS_PER_SEC; + + switch (level) { + case LOG_INFO: + level_str = "INFO"; + color = INFO_COLOR; + break; + + case LOG_DEBUG: + level_str = "DEBUG"; + color = DEBUG_COLOR; + break; + + case LOG_WARN: + level_str = "WARN"; + color = WARN_COLOR; + break; + + case LOG_ERROR: + level_str = "ERROR"; + color = ERROR_COLOR; + break; + } + + // Format user's string + va_start(args, msg); + va_copy(args_cpy, args); + + str_len = vsnprintf(NULL, 0, msg, args); + if (str_len < 0) { + perror("Error occured while formatting log string."); + return; + } + + fmt_msg = malloc(str_len + 1); + + vsnprintf(fmt_msg, str_len + 1, msg, args); + + va_end(args_cpy); + va_end(args); + + // Make log system format + str_len = snprintf(NULL, 0, "%s[%s].%d %s: %s %s\n", color, level_str, + curr_time, filename, fmt_msg, COLOR_RESET); + if (str_len < 0) { + perror("Error occured while formatting log string."); + free(fmt_msg); + return; + } + + output_msg = malloc(str_len + 1); + snprintf(output_msg, str_len + 1, "%s[%s].%d %s: %s %s\n", color, level_str, + curr_time, filename, fmt_msg, COLOR_RESET); + + if (g_core_logger->log_file) { + fprintf(g_core_logger->log_file, "%s", output_msg); + } + + printf("%s", output_msg); + + free(fmt_msg); + free(output_msg); +} + +void logger_deinit() { + if (g_core_logger->log_file) { + fclose(g_core_logger->log_file); + } + + free(g_core_logger); +} diff --git a/core/src/log.h b/core/src/log.h new file mode 100644 index 0000000..48daa2e --- /dev/null +++ b/core/src/log.h @@ -0,0 +1,45 @@ +#ifndef LOG_H +#define LOG_H + +#include +#include + +#if defined(__unix__) || defined(__unix) || \ + (defined(__APPLE__) && defined(__MACH__)) +#define INFO_COLOR "\e[38;5;15m" +#define DEBUG_COLOR "\e[38;5;36m" +#define WARN_COLOR "\e[38;5;214m" +#define ERROR_COLOR "\e[38;5;196m" +#define COLOR_RESET "\e[0m" +#else +#define INFO_COLOR "" +#define DEBUG_COLOR "" +#define WARN_COLOR "" +#define ERROR_COLOR "" +#define COLOR_RESET "" +#endif + +typedef enum { + LOG_INFO, + LOG_DEBUG, + LOG_WARN, + LOG_ERROR, +} log_level_e; + +typedef struct { + FILE *log_file; + clock_t time; +} logger_t; + +extern logger_t *g_core_logger; + +void logger_init(const char *filename); +void logger_msg(log_level_e level, const char *filename, const char *msg, ...); +void logger_deinit(); + +#define log_info(...) logger_msg(LOG_INFO, __FILE__, __VA_ARGS__) +#define log_debug(...) logger_msg(LOG_DEBUG, __FILE__, __VA_ARGS__) +#define log_warn(...) logger_msg(LOG_WARN, __FILE__, __VA_ARGS__) +#define log_error(...) logger_msg(LOG_ERROR, __FILE__, __VA_ARGS__); + +#endif // !LOG_H