diff --git a/README.md b/README.md index 3e4f84a..34f0226 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,15 @@ logging是一个轻量级的简单易用C语言日志库,支持日志级别、 - 支持日志输出:控制台、文件 - 支持日志文件:自动创建、自动滚动、自动删除(未完成) +## 安装 +- conan安装使用 +```shell +conan create . --build=missing +``` +- cmake安装使用 +```shell +``` + ## 使用方法 ### 控制台日志 @@ -18,16 +27,15 @@ logging是一个轻量级的简单易用C语言日志库,支持日志级别、 #include "logging.h" int main() { - Logging *log = newLogging(); - Logger *logger = log->getLogger("testLogger", LOG_DEBUG); + Logger *logger = newLogger("testLogger", LOG_DEBUG); logger->info("This is an info message"); - logger->error("你好,这是一个错误消息%s", "123"); + logger->error("This is an error message%s", "123"); logger->fatal("This is an fatal message"); logger->debug("This is a debug message"); logger->warning("This is a warning message%s", "123"); - log->destroyLogging(log); + destroyLogger(); return 0; } ``` @@ -35,20 +43,19 @@ int main() { ### 文件日志 ```c #include "logging.h" +#include "logging/logging-handler.h" int main() { - Logging *log = newLogging(); - Logger *logger = log->getLogger("testLogger",LOG_DEBUG); - - logger->addHandler(loggingFileHandler("test")); //为日志对象添加文件处理器 + Logger *logger = newLogger("testLogger", LOG_DEBUG); + logger->addHandler(loggingFileHandler("test1", 1024*1024)); logger->info("This is an info message"); - logger->error("你好,这是一个错误消息%s", "123"); + logger->error("This is an error message%s", "123"); logger->fatal("This is an fatal message"); logger->debug("This is a debug message"); logger->warning("This is a warning message%s", "123"); - log->destroyLogging(log); + destroyLogger(); return 0; } ``` @@ -66,8 +73,7 @@ int main() { #include int main() { - Logging *log = newLogging(); - Logger *logger = log->getLogger("testLogger", LOG_DEBUG); + Logger *logger = newLogger("testLogger", LOG_DEBUG); logger->info("This is an info message"); logger->error("This is an error message%s", "123"); @@ -95,15 +101,10 @@ int main() { logger->debug("This is a debug message"); logger->warning("This is a warning message%s", "123"); - log->destroyLogging(log); + destroyLogger(); return 0; } ``` ![](docs/img/2024-09-21-11-44-25.png) ![](docs/img/2024-09-21-11-44-06.png) - -# build -```shell -conan create . --build=missing -``` \ No newline at end of file diff --git a/conanfile.py b/conanfile.py index d2e2cb5..2787442 100644 --- a/conanfile.py +++ b/conanfile.py @@ -5,7 +5,7 @@ import os class loggingRecipe(ConanFile): name = "logging" - version = "0.2.4" + version = "0.3.0" license = "MIT" author = "321640253@qq.com" url = "https://github.com/WangZhongDian/logging.git" diff --git a/include/logging.h b/include/logging.h index c9c87de..853aa6d 100644 --- a/include/logging.h +++ b/include/logging.h @@ -23,19 +23,32 @@ typedef struct Logger { void (*info)(const char *format, ...); void (*debug)(const char *format, ...); - void (*addHandler)(log_Handler *handler); - void (*addInterceptor)(log_Interceptor *Interceptor); + bool (*addHandler)(log_Handler *handler); + bool (*addInterceptor)(log_Interceptor *Interceptor); } Logger; - -typedef struct Logging { - Logger *(*getLogger)(const char *name, log_level level); - log_status (*setLevel)(Logger *logger, log_level level); - Logger *(*getCurrentLogger)(void); - log_status (*destroyLogging)(struct Logging *logging); -} Logging; - -Logging *newLogging(); +/** +* @brief 创建日志对象,日志对象为单例模式,后续可通过getDefaultLogger方法获取, + 重复调用该方法不会创建新的日志对象,只会返回默认日志对象,并且会修改默认日志对象的名称和等级 +* @param name 日志名称 +* @param level 日志等级 +* @return Logger* 日志对象指针 +*/ +Logger *newLogger(const char *name, log_level level); +/** + * @brief 设置日志等级 + * @param logger 日志对象 + * @param level 日志等级 + */ +log_status setLevel(Logger *logger, log_level level); +/** + * @brief 获取默认日志对象 + */ +Logger *getDefaultLogger(void); +/** + * @brief 销毁日志对象,该方法会销毁默认日志对象 + */ +log_status destroyLogger(void); #ifdef __cplusplus } diff --git a/include/logging/logging-interceptor.h b/include/logging/logging-interceptor.h index d93e201..543b16a 100644 --- a/include/logging/logging-interceptor.h +++ b/include/logging/logging-interceptor.h @@ -16,12 +16,14 @@ typedef struct log_Interceptor { } log_Interceptor; - /** -* @brief 子字符串拦截器 -* @param -* @return -*/ + * @brief 子字符串拦截器 + * @param keywords: 关键字数组 + * @param count: 关键字数组长度 + * @param level: 最低拦截日志等级 + * @param handler: 日志处理器,用于处理拦截下来的日志 + * @return log_Interceptor * + */ log_Interceptor *loggingSubStringInterceptor(char *keywords[], int count, log_level level, diff --git a/src/handler/logging-handler-file.c b/src/handler/logging-handler-file.c index f951800..c2719f7 100644 --- a/src/handler/logging-handler-file.c +++ b/src/handler/logging-handler-file.c @@ -3,8 +3,12 @@ #include #include -#define Handler_FILE_EX_PRT(fp) \ - ((log_Handler_file_ex_t *)(fp + sizeof(log_Handler))) +// 根据log_Handler结构体指针获取log_Handler_file_ex_t结构体指针 +// log_Handler_file_ex_t与log_Handler处于连续内存中 +#define Handler_file_EX_PRT(handler) \ + ((log_Handler_file_ex_t *)((void*)handler + sizeof(log_Handler))) + +#define FILE_NAME_MAX_SIZE 50 typedef struct log_Handler_file_ex_s { unsigned int file_size; @@ -20,54 +24,73 @@ static unsigned int getFileSize(FILE *fp) { static void __freeFileHandler(log_Handler *handler) { fclose(handler->stream); - free(Handler_FILE_EX_PRT(handler)->file_name); + free(Handler_file_EX_PRT(handler)->file_name); free(handler); } static void changeFile(log_Handler *handler) { - log_Handler_file_ex_t *handler_ex = Handler_FILE_EX_PRT(handler); + log_Handler_file_ex_t *handler_ex = Handler_file_EX_PRT(handler); fclose(handler->stream); - char new_file_name[30]; - sprintf(new_file_name, "%s_%d.log", handler_ex->file_name, ++handler_ex->suffix); - handler->stream = fopen(new_file_name, "at"); + char new_file_name[FILE_NAME_MAX_SIZE]; + sprintf(new_file_name, + "%s_%d.log", + handler_ex->file_name, + ++handler_ex->suffix); + handler->stream = fopen(new_file_name, "at"); handler_ex->file_size = getFileSize(handler->stream); } static void outputFileHandler(log_Handler *handler, const char *message) { fputs(message, handler->stream); - log_Handler_file_ex_t *handler_ex = Handler_FILE_EX_PRT(handler); + log_Handler_file_ex_t *handler_ex = Handler_file_EX_PRT(handler); handler_ex->file_size += strlen(message); if (handler_ex->file_size > handler_ex->file_size_max) changeFile(handler); } log_Handler *loggingFileHandler(const char *name, unsigned int max_size) { - char new_file_name[30]; - int suffix = 0; - unsigned int file_size; - FILE *fp; + char new_file_name[FILE_NAME_MAX_SIZE]; + int suffix = 0; + unsigned int file_size; + FILE *fp = NULL; + log_Handler *handler = NULL; + log_Handler_file_ex_t *handler_ex = NULL; do { sprintf(new_file_name, "%s_%d.log", name, suffix++); - fp = fopen(new_file_name, "at"); + fp = fopen(new_file_name, "at"); + if (fp == NULL) + goto ERROR; file_size = getFileSize(fp); } while (file_size > max_size); /// 分配log_Handler与记录文件大小的空间 - log_Handler *handler = (log_Handler *)malloc(sizeof(log_Handler) + - sizeof(log_Handler_file_ex_t)); - - log_Handler_file_ex_t *handler_ex = Handler_FILE_EX_PRT(handler); - handler_ex->file_size_max = max_size; - handler_ex->file_size = file_size; - handler_ex->suffix = suffix; - handler_ex->file_name = malloc(strlen(new_file_name) + 1); - strcpy(handler_ex->file_name, name); - - handler->stream = fp; - handler->apply_color = false; - handler->_free = __freeFileHandler; - handler->output = outputFileHandler; + handler = (log_Handler *)malloc(sizeof(log_Handler) + + sizeof(log_Handler_file_ex_t)); + if (handler == NULL) + goto ERROR; + + handler_ex = Handler_file_EX_PRT(handler); + // printf("%p\n", handler); + handler_ex->file_size_max = max_size; + handler_ex->file_size = file_size; + handler_ex->suffix = suffix; + handler_ex->file_name = strdup(name); + if (handler_ex->file_name == NULL) + goto ERROR; + handler->stream = fp; + handler->apply_color = false; + handler->_free = __freeFileHandler; + handler->output = outputFileHandler; return handler; + +ERROR: + if (fp) + fclose(fp); + if (handler) { + free(Handler_file_EX_PRT(handler)->file_name); // 直接释放,无需检查NULL + free(handler); + } + return NULL; } \ No newline at end of file diff --git a/src/logging.c b/src/logging.c index e58324a..55571b7 100644 --- a/src/logging.c +++ b/src/logging.c @@ -1,6 +1,7 @@ #include "logging.h" #include "logging/logging-handler.h" #include "utils/logging-utils.h" +#include #include #include #include @@ -22,32 +23,32 @@ Logger *G_LOGGER = NULL; * @brief 为日志添加一个handler * @param handler 处理器对象 */ -static void addHandler(log_Handler *handler) { - if (G_LOGGER == NULL) { - return; +static bool addHandler(log_Handler *handler) { + if (G_LOGGER == NULL || handler == NULL) { + return false; } if (G_LOGGER->handler == NULL) { G_LOGGER->handler = handler; - return; + return true; } G_LOGGER->handler->_free(G_LOGGER->handler); - G_LOGGER->handler = handler; + return true; } -void addInterceptor(log_Interceptor *Interceptor) { - if (G_LOGGER == NULL) { - return; +static bool addInterceptor(log_Interceptor *Interceptor) { + if (G_LOGGER == NULL || Interceptor == NULL) { + return false; } if (G_LOGGER->interceptor == NULL) { G_LOGGER->interceptor = Interceptor; - return; + return true; } G_LOGGER->interceptor->_free(G_LOGGER->interceptor); - G_LOGGER->interceptor = Interceptor; + return true; } /** @@ -90,8 +91,12 @@ _builtin_log(char *level, const char *color, const char *message, ...) { RESET, message); else - sprintf( - logStr, "[%s]: %s %s %s\n", G_LOGGER->name, timeStr, level, message); + sprintf(logStr, + "[%s]: %s %s %s\n", + G_LOGGER->name, + timeStr, + level, + message); handler->output(handler, logStr); } @@ -151,7 +156,7 @@ static void debug(const char *message, ...) { } } -static Logger *getLogger(const char *name, log_level level) { +Logger *newLogger(const char *name, log_level level) { if (G_LOGGER != NULL) { G_LOGGER->name = name; G_LOGGER->level = level; @@ -179,12 +184,9 @@ static Logger *getLogger(const char *name, log_level level) { } /** - * @description :销毁日志对象 + * @brief 销毁日志对象 */ -log_status destroyLogging(Logging *logging) { - if (logging == NULL) { - return L_ERROR; - } +log_status destroyLogger(void) { if (G_LOGGER != NULL) { if (G_LOGGER->handler != NULL) { G_LOGGER->handler->_free(G_LOGGER->handler); @@ -197,21 +199,12 @@ log_status destroyLogging(Logging *logging) { free(G_LOGGER); G_LOGGER = NULL; } - free(logging); return L_OK; } -Logger *getCurrentLogger(void) { +Logger *getDefaultLogger(void) { if (G_LOGGER == NULL) { return NULL; } return G_LOGGER; -} - -Logging *newLogging() { - Logging *logging = (Logging *)malloc(sizeof(Logging)); - logging->getLogger = getLogger; - logging->destroyLogging = destroyLogging; - logging->getCurrentLogger = getCurrentLogger; - return logging; } \ No newline at end of file diff --git a/tests/test_interceptor.c b/tests/test_interceptor.c index 5ccc97a..986d574 100644 --- a/tests/test_interceptor.c +++ b/tests/test_interceptor.c @@ -2,8 +2,7 @@ #include int main() { - Logging *log = newLogging(); - Logger *logger = log->getLogger("testLogger", LOG_DEBUG); + Logger *logger = newLogger("testLogger", LOG_DEBUG); logger->info("This is an info message"); logger->error("This is an error message%s", "123"); @@ -31,6 +30,6 @@ int main() { logger->debug("This is a debug message"); logger->warning("This is a warning message%s", "123"); - log->destroyLogging(log); + destroyLogger(); return 0; } \ No newline at end of file diff --git a/tests/test_simple.c b/tests/test_simple.c index 9abc796..d803794 100644 --- a/tests/test_simple.c +++ b/tests/test_simple.c @@ -1,8 +1,7 @@ #include "logging.h" int main() { - Logging *log = newLogging(); - Logger *logger = log->getLogger("testLogger", LOG_DEBUG); + Logger *logger = newLogger("testLogger", LOG_DEBUG); logger->info("This is an info message"); logger->error("This is an error message%s", "123"); @@ -10,6 +9,6 @@ int main() { logger->debug("This is a debug message"); logger->warning("This is a warning message%s", "123"); - log->destroyLogging(log); + destroyLogger(); return 0; } \ No newline at end of file