diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f7be31..e85e264 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ endif() if (SKIPTEST) else() -add_executable(test_main ${CMAKE_SOURCE_DIR}/test_package/main.c ${SRC}) + add_executable(test_simple ${CMAKE_SOURCE_DIR}/test_package/test_simple.c ${SRC}) + add_executable(test_interceptor ${CMAKE_SOURCE_DIR}/test_package/test_interceptor.c ${SRC}) endif() diff --git a/README.md b/README.md index dc2c831..22ec38e 100644 --- a/README.md +++ b/README.md @@ -55,4 +55,47 @@ int main() { destroyLogging(log); return 0; } -``` \ No newline at end of file +``` + +### 日志拦截器 +> 支持添加自定义的拦截器, 目前内置了子串拦截器 + +> 拦截器的作用:可以将拦截到的日志重定向到拦截器的专属处理器中 + + +#### 例子 +将拦截到的日志重定向到专属文件处理器中 +```c +#include "logging.h" + + +int main() { + Logging *log = createLogging(); + Logger *logger = log->getLogger("testLogger",LOG_DEBUG); + logger->addHandler(consoleHandler("test")); + + logger->info("This is an info message"); + logger->error("你好,这是一个错误消息%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"); + + char *test1[] = {"123", "你好"};//要拦截的字符串 + //添加拦截器,将拦截到的日志重定向到拦截器的专属处理器中 + log_Interceptor * tint = substringInterceptor(test1,2,LOG_DEBUG,fileHandler("被拦截")); + logger->addInterceptor(tint); + printf("Interceptor added\n"); + + logger->info("This is an info message"); + logger->error("你好,这是一个错误消息%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"); + + destroyLogging(log); + return 0; +} +``` +![](docs/img/![](2024-08-13-22-20-18.png).png) +![](docs/img/2024-08-13-22-21-37.png) diff --git a/conanfile.py b/conanfile.py index d9d1e53..298effa 100644 --- a/conanfile.py +++ b/conanfile.py @@ -9,7 +9,7 @@ import os class loggingRecipe(ConanFile): name = "logging" - version = "0.1.0" + version = "0.1.1" license = "MIT" author = "321640253@qq.com" url = "https://github.com/WangZhongDian/logging.git" diff --git a/docs/img/![](2024-08-13-22-20-18.png).png b/docs/img/![](2024-08-13-22-20-18.png).png new file mode 100644 index 0000000..a981785 Binary files /dev/null and b/docs/img/![](2024-08-13-22-20-18.png).png differ diff --git a/docs/img/2024-08-13-22-21-37.png b/docs/img/2024-08-13-22-21-37.png new file mode 100644 index 0000000..c8c816e Binary files /dev/null and b/docs/img/2024-08-13-22-21-37.png differ diff --git a/include/logging.h b/include/logging.h index 8cb29e5..f10ab5a 100644 --- a/include/logging.h +++ b/include/logging.h @@ -22,17 +22,29 @@ typedef enum { L_OK, } log_status; -typedef struct Handler { +typedef struct log_Handler { void* out; bool apply_color; + bool need_free; //是否有资源释放需求 + void (*_free)(struct log_Handler* handler);//释放资源 } log_Handler; +typedef struct log_Interceptor { + log_level level; //拦截级别 + log_Handler* handler; //拦截目标处理器 + bool need_free; //是否有资源释放需求 + bool (*_dispose)(char* level,const char *message, ...); //拦截触发器 + void (*_free)(struct log_Interceptor* Interceptor); //释放资源 +} log_Interceptor; + + //日志操作器 typedef struct Logger { log_level level; log_Handler* handler; + log_Interceptor* interceptor; const char* name; void (*fatal)(const char* format, ...); void (*error)(const char* format, ...); @@ -43,6 +55,7 @@ typedef struct Logger void (*addHandler)(log_Handler* handler); // void (*addFormat)(const char* format); // void (*addFilter)(const char* filter); + void (*addInterceptor)(log_Interceptor* Interceptor); } Logger; @@ -54,13 +67,21 @@ typedef struct Logging { -Logging* createLogging(); //创建日志操作器 +Logging* createLogging(); log_status destroyLogging(Logging* logging); Logger* getCurrentLogger(void); -log_Handler* fileHandler(const char* name); //文件处理器 -log_Handler* consoleHandler(const char* name); //控制台处理器 +/** + * @def 创建日志处理器 + * @file logging-handler.c +*/ +log_Handler* fileHandler(const char* name); +log_Handler* consoleHandler(const char* name); + + + +log_Interceptor* substringInterceptor(char *keywords[], int count, log_level level, log_Handler* handler); #endif // __LOGGING_H \ No newline at end of file diff --git a/src/logging-handler.c b/src/logging-handler.c index 711d3ae..a9d9570 100644 --- a/src/logging-handler.c +++ b/src/logging-handler.c @@ -5,6 +5,15 @@ #include "logging.h" +/** +* @description :释放文件日志处理器相关资源 +* @param +* @return +*/ +static void __freeFileHandler(log_Handler* handler){ + fclose(handler->out); +} + /** * @description :文件日志处理器 * @param @@ -17,6 +26,8 @@ log_Handler* fileHandler(const char* name){ log_Handler* handler = (log_Handler*)malloc(sizeof(log_Handler)); handler->out = fp; handler->apply_color = false; + handler->need_free = true; + handler->_free = __freeFileHandler; return handler; } @@ -30,5 +41,7 @@ log_Handler* consoleHandler(const char* name){ log_Handler* handler = (log_Handler*)malloc(sizeof(log_Handler)); handler->out = stdout; handler->apply_color = true; + handler->need_free = false; + handler->_free = NULL; return handler; } \ No newline at end of file diff --git a/src/logging-interceptor.c b/src/logging-interceptor.c new file mode 100644 index 0000000..19758ff --- /dev/null +++ b/src/logging-interceptor.c @@ -0,0 +1,114 @@ +/******************************************** +* @Date: 2024 08 12 +* @Description: 日志拦截器 +*********************************************/ + +#include "logging.h" + +static log_Interceptor* G_interceptor = NULL; + +static char **G_keywords = NULL; + +void get_next(char *str, int *next) { + next[1] = 0; + int i=1; + int j=0; + while (i < strlen(str)) { + if (j==0|| str[i] == str[j]) { + next[++i] = ++j; + } + else { + j = next[j]; + } + } +} + + +bool kmp_search(char *substr, char *master) { + int i = 0; + int j = 0; + int substrlen = strlen(substr); + int masterlen = strlen(master); + int *next = (int *)malloc(sizeof(int) * substrlen + 1); + get_next(substr, next); + + while (i < masterlen && j < substrlen) { + if (master[i] == substr[j]) { + i++; + j++; + } else { + if(j == 0) { + i++; + } else { + j = next[j]; + } + } + } + + free(next); + if (j == substrlen)return true; + else return false; +} + + +static bool _disposeSubstring(char* level,const char *message, ...){ + int count = 0; + + if (G_keywords == NULL) { + return false; + } + + while (G_keywords[count] != NULL) + { + if (kmp_search(G_keywords[count],(char*)message)) { + if(G_interceptor->handler != NULL) { + + } + return true; + } + count++; + } + + return false; +} + +/** +* @description : 释放内存 +*/ +static void _freeSubstring(log_Interceptor* interceptor) { + int sum = 0; + while (G_keywords[sum] != NULL) { + free(G_keywords[sum]); + sum++; + } + free(G_keywords); + G_keywords = NULL; + + free(interceptor); +} + +/** +* @description : 子字符串拦截器 +*/ +log_Interceptor* substringInterceptor(char *keywords[], int count, log_level level, log_Handler* handler) { + log_Interceptor* interceptor = (log_Interceptor*)malloc(sizeof(log_Interceptor)); + interceptor->_dispose = _disposeSubstring; + interceptor->need_free = true; + interceptor->handler = handler; + interceptor->level = level; + interceptor->_free = _freeSubstring; + + G_keywords = (char**)malloc( (sizeof(G_keywords)*count) + 1); + + for (int i = 0; i < count; i++) { + G_keywords[i] = (char*)malloc(strlen(keywords[i])+1); + strcpy(G_keywords[i], keywords[i]); + } + G_keywords[count] = NULL; + + G_interceptor = interceptor; + return G_interceptor; +} + + + diff --git a/src/logging.c b/src/logging.c index 672bb5c..5442907 100644 --- a/src/logging.c +++ b/src/logging.c @@ -35,13 +35,38 @@ static void addHandler(log_Handler* handler){ if (G_LOGGER == NULL){ return; } + if (G_LOGGER->handler == NULL){ + G_LOGGER->handler = handler; + return; + } + + if(G_LOGGER->handler->need_free){ + G_LOGGER->handler->_free(G_LOGGER->handler); + } + free(G_LOGGER->handler); G_LOGGER->handler = handler; } +void addInterceptor(log_Interceptor* Interceptor){ + if (G_LOGGER == NULL){ + return; + } + if (G_LOGGER->interceptor == NULL){ + G_LOGGER->interceptor = Interceptor; + return; + } + + if(G_LOGGER->interceptor->need_free){ + G_LOGGER->interceptor->_free(G_LOGGER->interceptor); + } + free(G_LOGGER->interceptor); + G_LOGGER->interceptor = Interceptor; +} + /** * @description : 内置日志记录函数 */ -static void _builtin_log(char* level, const char *color, const char* format, ...){ +static void _builtin_log(char* level, const char *color, const char* message, ...){ if (G_LOGGER == NULL){ return; } @@ -51,63 +76,77 @@ static void _builtin_log(char* level, const char *color, const char* format, ... char timeStr[20]; getTimeStr(timeStr); char logStr[LOG_BUFFER_SIZE]; - if (G_LOGGER->handler->apply_color) sprintf(logStr, "%s %s%s%s %s\n", timeStr, color,level,RESET, format); - else sprintf(logStr, "%s %s %s\n", timeStr, level, format); - fputs(logStr, G_LOGGER->handler->out); + + log_Handler * handler = G_LOGGER->handler; + + //通过拦截器 + if (G_LOGGER->interceptor != NULL){ + if(G_LOGGER->interceptor->_dispose(level,message)){ + if(G_LOGGER->interceptor->handler != NULL){ + handler = G_LOGGER->interceptor->handler; + } + } + } + + //判断处理器是否应用颜色 + if (handler->apply_color) sprintf(logStr, "%s %s%s%s %s\n", timeStr, color,level,RESET, message); + else sprintf(logStr, "%s %s %s\n", timeStr, level, message); + + fputs(logStr, handler->out); } //*************************记录日志******************************* */ -static void fatal(const char* format, ...){ +static void fatal(const char* message, ...){ if (G_LOGGER->level >= LOG_ERROR){ char logStr[LOG_BUFFER_SIZE]; va_list args; - va_start(args, format); - vsprintf(logStr, format, args); + va_start(args, message); + vsprintf(logStr, message, args); va_end(args); _builtin_log("Fatal",RED, logStr, args); } } -static void error(const char* format, ...){ +static void error(const char* message, ...){ if (G_LOGGER->level >= LOG_ERROR){ char logStr[LOG_BUFFER_SIZE]; va_list args; - va_start(args, format); - vsprintf(logStr, format, args); + va_start(args, message); + vsprintf(logStr, message, args); va_end(args); _builtin_log("Error",RED, logStr, args); } } -static void warning(const char* format, ...){ +static void warning(const char* message, ...){ if (G_LOGGER->level >= LOG_WARNING){ char logStr[LOG_BUFFER_SIZE]; va_list args; - va_start(args, format); - vsprintf(logStr, format, args); + va_start(args, message); + vsprintf(logStr, message, args); va_end(args); _builtin_log("Warning",YELLOW, logStr, args); } } -static void info(const char* format, ...){ +static void info(const char* message, ...){ if (G_LOGGER->level >= LOG_INFO){ char logStr[LOG_BUFFER_SIZE]; va_list args; - va_start(args, format); - vsprintf(logStr, format, args); + va_start(args, message); + vsprintf(logStr, message, args); va_end(args); _builtin_log("Info",GREEN, logStr, args); } } -static void debug(const char* format, ...){ +static void debug(const char* message, ...){ if (G_LOGGER->level >= LOG_DEBUG){ char logStr[LOG_BUFFER_SIZE]; va_list args; - va_start(args, format); - vsprintf(logStr, format, args); + va_start(args, message); + vsprintf(logStr, message, args); va_end(args); _builtin_log("Debug",CYAN, logStr, args); } @@ -132,10 +171,12 @@ static Logger* getLogger(const char* name, log_level level){ logger->debug = debug; logger->addHandler = addHandler; + logger->addInterceptor = addInterceptor; logger->level = level; logger->handler = NULL; logger->name = name; + logger->interceptor = NULL; G_LOGGER = logger; return G_LOGGER; @@ -160,9 +201,14 @@ log_status destroyLogging(Logging* logging){ } if (G_LOGGER != NULL){ if (G_LOGGER->handler != NULL){ - fclose(G_LOGGER->handler->out); + if(G_LOGGER->handler->need_free)G_LOGGER->handler->_free(G_LOGGER->handler); free(G_LOGGER->handler); } + + if (G_LOGGER->interceptor != NULL){ + if(G_LOGGER->interceptor->need_free)G_LOGGER->interceptor->_free(G_LOGGER->interceptor); + } + free(G_LOGGER); G_LOGGER = NULL; } @@ -180,4 +226,6 @@ Logger* getCurrentLogger(void){ return NULL; } return G_LOGGER; -} \ No newline at end of file +} + + diff --git a/test_package/test_interceptor.c b/test_package/test_interceptor.c new file mode 100644 index 0000000..7261f6f --- /dev/null +++ b/test_package/test_interceptor.c @@ -0,0 +1,30 @@ +#include "logging.h" + + +int main() { + Logging *log = createLogging(); + Logger *logger = log->getLogger("testLogger",LOG_DEBUG); + logger->addHandler(consoleHandler("test")); + + logger->info("This is an info message"); + logger->error("你好,这是一个错误消息%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"); + + char *test1[] = {"123", "你好"};//要拦截的字符串 + //添加拦截器,将拦截到的日志重定向到拦截器的专属处理器中 + log_Interceptor * tint = substringInterceptor(test1,2,LOG_DEBUG,fileHandler("被拦截")); + logger->addInterceptor(tint); + printf("Interceptor added\n"); + + logger->info("This is an info message"); + logger->error("你好,这是一个错误消息%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"); + + destroyLogging(log); + return 0; +} \ No newline at end of file diff --git a/test_package/main.c b/test_package/test_simple.c similarity index 76% rename from test_package/main.c rename to test_package/test_simple.c index 97dd020..9d5aaf7 100644 --- a/test_package/main.c +++ b/test_package/test_simple.c @@ -4,7 +4,6 @@ int main() { Logging *log = createLogging(); Logger *logger = log->getLogger("testLogger",LOG_DEBUG); - // logger->addHandler(fileHandler("test")); logger->addHandler(consoleHandler("test")); logger->info("This is an info message"); @@ -13,9 +12,6 @@ int main() { logger->debug("This is a debug message"); logger->warning("This is a warning message%s", "123"); - Logger *logger1 = getCurrentLogger(); - logger1->info("This is an info message from logger1"); - destroyLogging(log); return 0; } \ No newline at end of file