Compare commits
	
		
			19 Commits
		
	
	
		
			01273809da
			...
			v0.5.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6ff484fef8 | |||
|  | 8e512563e4 | ||
|  | 9d3a7bbb8d | ||
|  | 064881c0ad | ||
|  | f0c3a5d56a | ||
|  | 56e1ac52ff | ||
|  | cc53e07788 | ||
|  | a4b4ad7452 | ||
|  | f4494515ca | ||
|  | d0bfc31563 | ||
|  | 650ce0dc3f | ||
|  | 3ef229ed65 | ||
|  | b7f49188ad | ||
|  | d61f7b6fde | ||
|  | 86cf4c4526 | ||
|  | 6765dd1214 | ||
|  | 0c96f67b47 | ||
|  | 3bc9704258 | ||
|  | 9448a294a2 | 
							
								
								
									
										16
									
								
								.github/workflows/linux_test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/linux_test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | name: test on Linux | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |     push: | ||||||
|  |         branches: ["main"] | ||||||
|  |     pull_request:  | ||||||
|  |         branches: ["main"] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |     test: | ||||||
|  |         runs-on: ubuntu-latest | ||||||
|  |         steps: | ||||||
|  |             - name: checkout code | ||||||
|  |               uses: actions/checkout@v4 | ||||||
|  |             - name: test | ||||||
|  |               run: bash ./script/test.sh | ||||||
							
								
								
									
										17
									
								
								.github/workflows/windows_test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/windows_test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | name: test on Windows | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |     push: | ||||||
|  |         branches: ["main","dev"] | ||||||
|  |  | ||||||
|  |     pull_request:  | ||||||
|  |         branches: ["main"] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |     test: | ||||||
|  |         runs-on: windows-latest | ||||||
|  |         steps: | ||||||
|  |             - name: checkout code | ||||||
|  |               uses: actions/checkout@v4 | ||||||
|  |             - name: test | ||||||
|  |               run: ./script/test_windows.ps1 | ||||||
| @@ -1,9 +1,18 @@ | |||||||
| cmake_minimum_required( VERSION 3.28) | cmake_minimum_required(VERSION 3.28...3.30) | ||||||
|  |  | ||||||
|  | project(logging) | ||||||
|  |  | ||||||
| set(LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) | set(CMAKE_C_STANDARD 99) | ||||||
| set(ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) |  | ||||||
| set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) | if(MSVC) | ||||||
|  |     add_compile_options("/source-charset:utf-8") | ||||||
|  |     add_compile_options("/execution-charset:utf-8") | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | set(CMAKE_EXPORT_COMPILE_COMMANDS yes) | ||||||
|  |  | ||||||
|  | option(TEST "是否启动单元测试" ON) | ||||||
|  | option(SHARED "是否编译为动态库" OFF) | ||||||
|  |  | ||||||
| include_directories(${CMAKE_SOURCE_DIR}/include) | include_directories(${CMAKE_SOURCE_DIR}/include) | ||||||
|  |  | ||||||
| @@ -11,7 +20,7 @@ include_directories(${CMAKE_SOURCE_DIR}/include) | |||||||
| add_subdirectory(src) | add_subdirectory(src) | ||||||
|  |  | ||||||
| #测试单元 | #测试单元 | ||||||
| if (SKIPTEST) | if (TEST) | ||||||
| else() |     enable_testing() | ||||||
|     add_subdirectory(tests) |     add_subdirectory(tests) | ||||||
| endif() | endif() | ||||||
|   | |||||||
							
								
								
									
										163
									
								
								README.en.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								README.en.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | |||||||
|  | # C language logging library logging | ||||||
|  |  | ||||||
|  | ## brief | ||||||
|  |  | ||||||
|  | Logging is a lightweight and easy-to-use C language log library that supports log level, log format, log output, log files, and other functions. | ||||||
|  |  | ||||||
|  | ## function | ||||||
|  | - Support log levels: DEBUG, INFO, Warning, ERROR, FATAL | ||||||
|  | - Support log formats: timestamp, log level, log content | ||||||
|  | - Support log output: console, file | ||||||
|  | - Support log files: automatic creation, automatic scrolling, log segmentation | ||||||
|  |  | ||||||
|  | ## install | ||||||
|  | - Conan | ||||||
|  | ```shell | ||||||
|  | conan create . | ||||||
|  | ``` | ||||||
|  | - cmake | ||||||
|  | ```shell | ||||||
|  | git clone https://github.com/WangZhongDian/logging.git | ||||||
|  | cd logging | ||||||
|  | cmake build -B build . && cd build && cmake --build . | ||||||
|  | cmake --install . | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## usage | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### console log  | ||||||
|  | ```c | ||||||
|  | #include "logging.h" | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |  | ||||||
|  |     log_info("This is an info message"); | ||||||
|  |     log_error("This is an error message%s", "123"); | ||||||
|  |     log_fatal("This is an fatal message"); | ||||||
|  |     log_debug("This is a debug message"); | ||||||
|  |     log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### file log | ||||||
|  | ```c | ||||||
|  | #include "logging.h" | ||||||
|  | #include "logging/logging-handler.h" | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |     logger->addHandler(loggingHandlerFile("test1", 1024*1024)); | ||||||
|  |  | ||||||
|  |     log_info("This is an info message"); | ||||||
|  |     log_error("This is an error message%s", "123"); | ||||||
|  |     log_fatal("This is an fatal message"); | ||||||
|  |     log_debug("This is a debug message"); | ||||||
|  |     log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Logging filter  | ||||||
|  | > Support adding custom filters, currently with built-in substring filters | ||||||
|  | > The function of an filter is to redirect filtered logs to the filter's dedicated processor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### example | ||||||
|  | Redirects filtered logs to a dedicated file processor | ||||||
|  | ```c | ||||||
|  | #include "logging.h" | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger  *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |  | ||||||
|  |     log_info("This is an info message"); | ||||||
|  |     log_error("This is an error message%s", "123"); | ||||||
|  |     log_fatal("This is an fatal message"); | ||||||
|  |     log_debug("This is a debug message"); | ||||||
|  |     log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     char *test1[]         = {"123", "tt", NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint = loggingFilterSubStr( | ||||||
|  |         test1, | ||||||
|  |         LOG_DEBUG, | ||||||
|  |         loggingHandlerFile("test_interceptor", 1024 * 1024), | ||||||
|  |         true); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint); | ||||||
|  |  | ||||||
|  |     printf("\n"); | ||||||
|  |     printf("filter added\n"); | ||||||
|  |     printf("\n"); | ||||||
|  |  | ||||||
|  |     log_info("This is an info message"); | ||||||
|  |     log_error("This is an error message%s", "123"); | ||||||
|  |     log_fatal("This is an fatal message"); | ||||||
|  |     log_debug("This is a debug message"); | ||||||
|  |     log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Multiple substring filters | ||||||
|  | ```c | ||||||
|  | #include "logging.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |  | ||||||
|  |     log_info("This is an info message"); | ||||||
|  |     log_error("This is an error message%s", "123"); | ||||||
|  |     log_fatal("This is an fatal message"); | ||||||
|  |     log_debug("This is a debug message"); | ||||||
|  |     log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     char *test1[]         = {"This",NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint = loggingFilterSubStr( | ||||||
|  |         test1, | ||||||
|  |         LOG_DEBUG, | ||||||
|  |         loggingHandlerFile("test_interceptor", 1024 * 1024), | ||||||
|  |         false); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint); | ||||||
|  |  | ||||||
|  |     char *test2[]         = {"123",NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint1 = loggingFilterSubStr( | ||||||
|  |         test2, | ||||||
|  |         LOG_DEBUG, | ||||||
|  |         loggingHandlerFile("test_interceptor1", 1024 * 1024), | ||||||
|  |         true); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint1); | ||||||
|  |  | ||||||
|  |     printf("\n"); | ||||||
|  |     printf("filter added\n"); | ||||||
|  |     printf("\n"); | ||||||
|  |  | ||||||
|  |     log_info("This is an info message"); | ||||||
|  |     log_error("This is an error message%s", "123"); | ||||||
|  |     log_fatal("This is an fatal message"); | ||||||
|  |     log_debug("This is a debug message"); | ||||||
|  |     log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
							
								
								
									
										178
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,5 +1,7 @@ | |||||||
| # C语言日志库logging | # C语言日志库logging | ||||||
|  |  | ||||||
|  | [English](README.en.md) | ||||||
|  |  | ||||||
| ## 简介 | ## 简介 | ||||||
|  |  | ||||||
| logging是一个轻量级的简单易用C语言日志库,支持日志级别、日志格式、日志输出、日志文件等功能。 | logging是一个轻量级的简单易用C语言日志库,支持日志级别、日志格式、日志输出、日志文件等功能。 | ||||||
| @@ -9,28 +11,51 @@ logging是一个轻量级的简单易用C语言日志库,支持日志级别、 | |||||||
| - 支持日志级别:DEBUG、INFO、WARN、ERROR、FATAL | - 支持日志级别:DEBUG、INFO、WARN、ERROR、FATAL | ||||||
| - 支持日志格式:时间戳、日志级别、日志内容 | - 支持日志格式:时间戳、日志级别、日志内容 | ||||||
| - 支持日志输出:控制台、文件 | - 支持日志输出:控制台、文件 | ||||||
| - 支持日志文件:自动创建、自动滚动、自动删除(未完成) | - 支持日志文件:自动创建、自动滚动、日志分割 | ||||||
|  |  | ||||||
|  | ## 安装 | ||||||
|  | ### conan安装使用 | ||||||
|  | ```shell | ||||||
|  | git clone https://github.com/WangZhongDian/logging.git | ||||||
|  | cd logging | ||||||
|  | conan create .  | ||||||
|  | ``` | ||||||
|  | 在你的项目的conanfile.txt中添加 | ||||||
|  | ```txt | ||||||
|  | [requires] | ||||||
|  | logging/0.5.0 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | conan install . --build=missing | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### cmake安装使用 | ||||||
|  | ```shell | ||||||
|  | git clone https://github.com/WangZhongDian/logging.git | ||||||
|  | cd logging | ||||||
|  | cmake build -B build . && cd build && cmake --build . | ||||||
|  | cmake --install . | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ## 使用方法 | ## 使用方法 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ### 控制台日志 | ### 控制台日志 | ||||||
| ```c | ```c | ||||||
| #include "logging.h" | #include "logging.h" | ||||||
|  |  | ||||||
| int main() { | int main() { | ||||||
|     Logging *log = createLogging(); // 创建日志对象 |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |  | ||||||
|     Logger *logger = log->getLogger("testLogger",LOG_DEBUG); //获取日志控制器 |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|     logger->addHandler(consoleHandler("test")); //为日志对象添加控制台处理器 |     destroyDefaultLogger(); | ||||||
|  |  | ||||||
|     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; |     return 0; | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
| @@ -38,70 +63,117 @@ int main() { | |||||||
| ### 文件日志 | ### 文件日志 | ||||||
| ```c | ```c | ||||||
| #include "logging.h" | #include "logging.h" | ||||||
|  | #include "logging/logging-handler.h" | ||||||
|  |  | ||||||
| int main() { | int main() { | ||||||
|     // Your code goes here |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|     Logging *log = createLogging(); |     logger->addHandler(loggingHandlerFile("test1", 1024*1024)); | ||||||
|     Logger *logger = log->getLogger("testLogger",LOG_DEBUG); |  | ||||||
|  |  | ||||||
|     logger->addHandler(consoleHandler("test"));   //为日志对象添加文件处理器 |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|     logger->info("This is an info message"); |     destroyDefaultLogger(); | ||||||
|     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; |     return 0; | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### 日志拦截器 | ### 日志过滤器 | ||||||
| > 支持添加自定义的拦截器, 目前内置了子串拦截器 | > 支持添加自定义的过滤器, 目前内置了子串过滤器 | ||||||
|  |  | ||||||
| > 拦截器的作用:可以将拦截到的日志重定向到拦截器的专属处理器中 | > 过滤器的作用:可以将过滤到的日志重定向到过滤器的专属处理器中 | ||||||
|  |  | ||||||
|  |  | ||||||
| #### 例子 | #### 单个子串过滤器 | ||||||
| 将拦截到的日志重定向到专属文件处理器中 | 将过滤到的日志重定向到专属处理器中 | ||||||
| ```c | ```c | ||||||
| #include "logging.h" | #include "logging.h" | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
| int main() { | int main() { | ||||||
|     Logging *log = createLogging(); |     Logger  *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|     Logger *logger = log->getLogger("testLogger",LOG_DEBUG); |  | ||||||
|     logger->addHandler(consoleHandler("test")); |  | ||||||
|  |  | ||||||
|     logger->info("This is an info message"); |     Log_info("This is an info message"); | ||||||
|     logger->error("你好,这是一个错误消息%s", "123"); |     Log_error("This is an error message%s", "123"); | ||||||
|     logger->fatal("This is an fatal message"); |     Log_fatal("This is an fatal message"); | ||||||
|     logger->debug("This is a debug message"); |     Log_debug("This is a debug message"); | ||||||
|     logger->warning("This is a warning message%s", "123"); |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|     char *test1[] = {"123", "你好"};//要拦截的字符串 |     char *test1[]         = {"123", "tt", NULL}; | ||||||
|     //添加拦截器,将拦截到的日志重定向到拦截器的专属处理器中 |  | ||||||
|     log_Interceptor * tint = substringInterceptor(test1,2,LOG_DEBUG,fileHandler("被拦截"));  |  | ||||||
|     logger->addInterceptor(tint); |  | ||||||
|     printf("Interceptor added\n"); |  | ||||||
|  |  | ||||||
|     logger->info("This is an info message"); |     log_filter *tint = loggingFilterSubStr( | ||||||
|     logger->error("你好,这是一个错误消息%s", "123"); |         test1, | ||||||
|     logger->fatal("This is an fatal message"); |         LOG_DEBUG, | ||||||
|  |         loggingHandlerFile("test_interceptor", 1024 * 1024), | ||||||
|  |         true); | ||||||
|  |  | ||||||
|     logger->debug("This is a debug message"); |     logger->addFilter(tint); | ||||||
|     logger->warning("This is a warning message%s", "123"); |  | ||||||
|  |  | ||||||
|     destroyLogging(log); |     printf("\n"); | ||||||
|  |     printf("filter added\n"); | ||||||
|  |     printf("\n"); | ||||||
|  |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
| .png) |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### 多个子串过滤器 | ||||||
|  | ```c | ||||||
|  | #include "logging.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
| # build | int main() { | ||||||
| ```shell |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
| conan create . --build=missing |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     char *test1[]         = {"This",NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint = loggingFilterSubStr( | ||||||
|  |         test1, | ||||||
|  |         LOG_DEBUG, | ||||||
|  |         loggingHandlerFile("test_interceptor", 1024 * 1024), | ||||||
|  |         false); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint); | ||||||
|  |  | ||||||
|  |     char *test2[]         = {"123",NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint1 = loggingFilterSubStr( | ||||||
|  |         test2, | ||||||
|  |         LOG_DEBUG, | ||||||
|  |         loggingHandlerFile("test_interceptor1", 1024 * 1024), | ||||||
|  |         true); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint1); | ||||||
|  |  | ||||||
|  |     printf("\n"); | ||||||
|  |     printf("filter added\n"); | ||||||
|  |     printf("\n"); | ||||||
|  |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								conanfile.py
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								conanfile.py
									
									
									
									
									
								
							| @@ -1,14 +1,11 @@ | |||||||
| from conan import ConanFile | from conan import ConanFile | ||||||
| from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout | from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout | ||||||
| from conan.tools.files import copy, get | from conan.tools.files import copy | ||||||
| from conan.tools.build import check_min_cppstd |  | ||||||
| from conan import tools |  | ||||||
| import os | import os | ||||||
|  |  | ||||||
|  |  | ||||||
| class loggingRecipe(ConanFile): | class loggingRecipe(ConanFile): | ||||||
|     name = "logging" |     name = "logging" | ||||||
|     version = "0.2.2" |     version = "0.5.1" | ||||||
|     license = "MIT" |     license = "MIT" | ||||||
|     author = "321640253@qq.com" |     author = "321640253@qq.com" | ||||||
|     url = "https://github.com/WangZhongDian/logging.git" |     url = "https://github.com/WangZhongDian/logging.git" | ||||||
| @@ -16,11 +13,11 @@ class loggingRecipe(ConanFile): | |||||||
|     topics = ("logging", "C", "simple", "easy-to-use", "log","Logging") |     topics = ("logging", "C", "simple", "easy-to-use", "log","Logging") | ||||||
|  |  | ||||||
|     settings = "os", "compiler", "build_type", "arch" |     settings = "os", "compiler", "build_type", "arch" | ||||||
|     options = {"shared": [True, False], "fPIC": [True, False]} |     options = {"shared": [True, False], "fPIC": [True, False],"test":[True,False]} | ||||||
|     default_options = {"shared": False, "fPIC": True} |     default_options = {"shared": False, "fPIC": True,"test":True} | ||||||
|  |  | ||||||
|  |  | ||||||
|     exports_sources = "include/*", "CMakeLists.txt", "src/*" |     exports_sources = "include/*", "CMakeLists.txt", "src/*", "tests/*" | ||||||
|  |  | ||||||
|     def config_options(self): |     def config_options(self): | ||||||
|         if self.settings.os == "Windows": |         if self.settings.os == "Windows": | ||||||
| @@ -30,8 +27,6 @@ class loggingRecipe(ConanFile): | |||||||
|         if self.options.shared: |         if self.options.shared: | ||||||
|             self.options.rm_safe("fPIC") |             self.options.rm_safe("fPIC") | ||||||
|  |  | ||||||
|  |  | ||||||
|      |  | ||||||
|     def layout(self): |     def layout(self): | ||||||
|         cmake_layout(self) |         cmake_layout(self) | ||||||
|  |  | ||||||
| @@ -39,18 +34,16 @@ class loggingRecipe(ConanFile): | |||||||
|         deps = CMakeDeps(self) |         deps = CMakeDeps(self) | ||||||
|         deps.generate() |         deps.generate() | ||||||
|         tc = CMakeToolchain(self) |         tc = CMakeToolchain(self) | ||||||
|         tc.variables["SKIPTEST"]=True |         tc.variables["TEST"] = True if self.options.test else False | ||||||
|         if self.options.shared: |         tc.variables["SHARED"] = True if self.options.shared else False | ||||||
|             tc.variables["SHARED"] = True |  | ||||||
|         else: |  | ||||||
|             tc.variables["SHARED"] = False |  | ||||||
|         tc.generate() |         tc.generate() | ||||||
|  |  | ||||||
|     def build(self): |     def build(self): | ||||||
|         cmake = CMake(self) |         cmake = CMake(self) | ||||||
|         cmake.configure() |         cmake.configure() | ||||||
|         cmake.build(target="Logging") |         cmake.build() | ||||||
|  |         if self.options.test: | ||||||
|  |             cmake.test() | ||||||
|  |  | ||||||
|     def package(self): |     def package(self): | ||||||
|         copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) |         copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) | ||||||
| @@ -62,4 +55,4 @@ class loggingRecipe(ConanFile): | |||||||
|         copy(self, pattern="*.dylib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) |         copy(self, pattern="*.dylib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) | ||||||
|  |  | ||||||
|     def package_info(self): |     def package_info(self): | ||||||
|         self.cpp_info.libs = ["Logging"] |         self.cpp_info.libs = ["logging"] | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 63 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 43 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/img/2024-09-21-11-44-06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/img/2024-09-21-11-44-06.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 58 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/img/2024-09-21-11-44-25.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/img/2024-09-21-11-44-25.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 47 KiB | 
| @@ -5,33 +5,61 @@ | |||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  |  | ||||||
| #include "logging/logging-core.h" | #include "logging/logging-core.h" | ||||||
|  | #include "logging/logging-filter.h" | ||||||
| #include "logging/logging-handler.h" | #include "logging/logging-handler.h" | ||||||
| #include "logging/logging-interceptor.h" |  | ||||||
|  |  | ||||||
| // 日志操作器 | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define Log_fatal(format, ...)                                                 \ | ||||||
|  |     log_fatal(__FILE__, __LINE__, format, ##__VA_ARGS__) | ||||||
|  | #define Log_error(format, ...)                                                 \ | ||||||
|  |     log_error(__FILE__, __LINE__, format, ##__VA_ARGS__) | ||||||
|  | #define Log_warning(format, ...)                                               \ | ||||||
|  |     log_warning(__FILE__, __LINE__, format, ##__VA_ARGS__) | ||||||
|  | #define Log_info(format, ...)                                                  \ | ||||||
|  |     log_info(__FILE__, __LINE__, format, ##__VA_ARGS__) | ||||||
|  | #define Log_debug(format, ...)                                                 \ | ||||||
|  |     log_debug(__FILE__, __LINE__, format, ##__VA_ARGS__) | ||||||
|  |  | ||||||
| typedef struct Logger { | typedef struct Logger { | ||||||
|     log_level        level; |     log_level    level; | ||||||
|     log_Handler     *handler; |     log_Handler *handler; | ||||||
|     log_Interceptor *interceptor; |     log_filter  *filter; | ||||||
|     const char      *name; |     const char  *name; | ||||||
|     void (*fatal)(const char *format, ...); |     bool (*addHandler)(log_Handler *handler); | ||||||
|     void (*error)(const char *format, ...); |     bool (*addFilter)(log_filter *filter); | ||||||
|     void (*warning)(const char *format, ...); |  | ||||||
|     void (*info)(const char *format, ...); |  | ||||||
|     void (*debug)(const char *format, ...); |  | ||||||
|  |  | ||||||
|     void (*addHandler)(log_Handler *handler); |  | ||||||
|     void (*addInterceptor)(log_Interceptor *Interceptor); |  | ||||||
| } Logger; | } Logger; | ||||||
|  |  | ||||||
| // 日志类对象 | void log_fatal(const char *file, int line, const char *format, ...); | ||||||
| typedef struct Logging { | void log_error(const char *file, int line, const char *format, ...); | ||||||
|     Logger *(*getLogger)(const char *name, log_level level); | void log_warning(const char *file, int line, const char *format, ...); | ||||||
|     log_status (*setLevel)(Logger *logger, log_level level); | void log_info(const char *file, int line, const char *format, ...); | ||||||
| } Logging; | void log_debug(const char *file, int line, const char *format, ...); | ||||||
|  |  | ||||||
| Logging   *createLogging();                  // 创建日志类对象 | /** | ||||||
| log_status destroyLogging(Logging *logging); // 销毁日志类对象 | * @brief | ||||||
| Logger    *getCurrentLogger(void);           // 获取当前日志记录器 | 创建默认日志对象,日志对象为单例模式,后续可通过getDefaultLogger方法获取, | ||||||
|  |         重复调用该方法不会创建新的日志对象,只会返回默认日志对象,并且会修改默认日志对象的名称和等级 | ||||||
|  | * @param name 日志名称 | ||||||
|  | * @param level 日志等级 | ||||||
|  | * @return Logger* 日志对象指针 | ||||||
|  | */ | ||||||
|  | Logger *newDefaultLogger(const char *name, log_level level); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 获取默认日志对象 | ||||||
|  |  */ | ||||||
|  | Logger *getDefaultLogger(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 销毁日志对象,该方法会销毁默认日志对象 | ||||||
|  |  */ | ||||||
|  | log_status destroyDefaultLogger(void); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif // __LOGGING_H__ | #endif // __LOGGING_H__ | ||||||
| @@ -1,8 +1,12 @@ | |||||||
| #ifndef __LOGGING_CORE_H__ | #ifndef __LOGGING_CORE_H__ | ||||||
| #define __LOGGING_CORE_H__ | #define __LOGGING_CORE_H__ | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|     LOG_FATAL, |     LOG_FATAL = 0, | ||||||
|     LOG_ERROR, |     LOG_ERROR, | ||||||
|     LOG_WARNING, |     LOG_WARNING, | ||||||
|     LOG_INFO, |     LOG_INFO, | ||||||
| @@ -14,5 +18,8 @@ typedef enum { | |||||||
|     L_OK, |     L_OK, | ||||||
| } log_status; | } log_status; | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif // __LOGGING_CORE_H__ | #endif // __LOGGING_CORE_H__ | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								include/logging/logging-filter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/logging/logging-filter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | #ifndef __LOGGING_INTERCEPTOR_H__ | ||||||
|  | #define __LOGGING_INTERCEPTOR_H__ | ||||||
|  |  | ||||||
|  | #include "logging-core.h" | ||||||
|  | #include "logging-handler.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | typedef struct log_filter { | ||||||
|  |     log_level    level; | ||||||
|  |     log_Handler *handler; | ||||||
|  |     bool         jump_out; | ||||||
|  |     bool (*_dispose)(struct log_filter *filter, | ||||||
|  |                      log_level          level, | ||||||
|  |                      const char        *message, | ||||||
|  |                      ...); | ||||||
|  |     void (*_free)(struct log_filter *filter); | ||||||
|  |     struct log_filter *next; | ||||||
|  | } log_filter; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief  子字符串过滤器 | ||||||
|  |  * @param keywords: 关键字数组 | ||||||
|  |  * @param count: 关键字数组长度 | ||||||
|  |  * @param level: 过滤截日志等级 | ||||||
|  |  * @param handler: 日志处理器,用于处理过滤下来的日志 | ||||||
|  |  * @return log_filter * | ||||||
|  |  */ | ||||||
|  | log_filter *loggingFilterSubStr(char        *keywords[], | ||||||
|  |                                 log_level    level, | ||||||
|  |                                 log_Handler *handler, | ||||||
|  |                                 bool         jump_out); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif // __LOGGING_INTERCEPTOR_H__ | ||||||
| @@ -3,15 +3,34 @@ | |||||||
|  |  | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
| typedef struct log_Handler { | typedef struct log_Handler { | ||||||
|     void* stream; |     void *stream; | ||||||
|     bool apply_color; |     bool  apply_color; | ||||||
|     void (*_free)(struct log_Handler* handler);//释放资源 |     void (*_free)(struct log_Handler *handler); | ||||||
|     void (*output)(struct log_Handler* handler,const char* message); |     void (*output)(struct log_Handler *handler, const char *message); | ||||||
| } log_Handler; | } log_Handler; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 文件处理器 | ||||||
|  |  * @param name 文件名 | ||||||
|  |  * @param max_size 文件最大大小 | ||||||
|  |  * @return | ||||||
|  |  */ | ||||||
|  | log_Handler *loggingHandlerFile(const char *name, unsigned int max_size); | ||||||
|  |  | ||||||
| log_Handler* fileHandler(const char* name);      | /** | ||||||
| log_Handler* consoleHandler(); |  * @brief 控制台处理器 | ||||||
|  |  * @param | ||||||
|  |  * @return | ||||||
|  |  */ | ||||||
|  | log_Handler *loggingHandlerConsole(); | ||||||
|  |  | ||||||
| #endif  //__LOGGING_HANDLER_H__ | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif //__LOGGING_HANDLER_H__ | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| #ifndef __LOGGING_INTERCEPTOR_H__ |  | ||||||
| #define __LOGGING_INTERCEPTOR_H__ |  | ||||||
|  |  | ||||||
| #include "logging-core.h" |  | ||||||
| #include "logging-handler.h" |  | ||||||
|  |  | ||||||
| typedef struct log_Interceptor { |  | ||||||
|     log_level    level;   // 拦截级别 |  | ||||||
|     log_Handler *handler; // 拦截目标处理器 |  | ||||||
|     bool (*_dispose)(char *level, const char *message, ...); // 拦截触发器 |  | ||||||
|     void (*_free)(struct log_Interceptor *Interceptor);      // 释放资源 |  | ||||||
|  |  | ||||||
| } log_Interceptor; |  | ||||||
|  |  | ||||||
| log_Interceptor *substringInterceptor(char        *keywords[], |  | ||||||
|                                       int          count, |  | ||||||
|                                       log_level    level, |  | ||||||
|                                       log_Handler *handler); |  | ||||||
|  |  | ||||||
| #endif // __LOGGING_INTERCEPTOR_H__ |  | ||||||
							
								
								
									
										3
									
								
								script/format.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								script/format.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # Run clang-format on all C/C++ files in this directory and below. | ||||||
|  | find . -name "*.c" -o -name "*.h" -exec clang-format -style=file -i {} + | ||||||
							
								
								
									
										2
									
								
								script/test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2
									
								
								script/test.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | cmake build -B build . && cd build && cmake --build . && ctest | ||||||
							
								
								
									
										5
									
								
								script/test_windows.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								script/test_windows.ps1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | cmake build -B build .  | ||||||
|  | Set-Location -Path "./build" | ||||||
|  | cmake --build . | ||||||
|  | ctest | ||||||
|  | Set-Location -Path ".." | ||||||
| @@ -1,8 +1,9 @@ | |||||||
| project(Logging) | project(logging) | ||||||
|  |  | ||||||
| aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC) | aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC) | ||||||
| aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/handler SRC) | aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/handler SRC) | ||||||
| aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/interceptor SRC) | aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/filter SRC) | ||||||
|  | aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/utils SRC) | ||||||
|  |  | ||||||
| if (SHARED) | if (SHARED) | ||||||
|     add_library(${PROJECT_NAME} SHARED ${SRC}) |     add_library(${PROJECT_NAME} SHARED ${SRC}) | ||||||
|   | |||||||
							
								
								
									
										133
									
								
								src/filter/logging-filter-substr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/filter/logging-filter-substr.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | |||||||
|  | #include "logging/logging-filter.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
|  | typedef struct keywords_s { | ||||||
|  |     char              *key; | ||||||
|  |     struct keywords_s *next; | ||||||
|  | } keywords_t; | ||||||
|  |  | ||||||
|  | static 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]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool kmp_search(char *substr, char *master) { | ||||||
|  |     if (substr == NULL) | ||||||
|  |         return true; // 空串全匹配 | ||||||
|  |     if (master == NULL) | ||||||
|  |         return false; | ||||||
|  |     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(log_filter *filter, | ||||||
|  |                               log_level   level, | ||||||
|  |                               const char *message, | ||||||
|  |                               ...) { | ||||||
|  |     int         count   = 0; | ||||||
|  |     keywords_t *keyword = (keywords_t *)(filter + 1); | ||||||
|  |  | ||||||
|  |     if (keyword->key == NULL && keyword->next == NULL) { | ||||||
|  |         if (level <= filter->level) | ||||||
|  |             return true; | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     while (keyword != NULL && level <= filter->level) { | ||||||
|  |         if (kmp_search(keyword->key, (char *)message)) | ||||||
|  |             return true; | ||||||
|  |         keyword = keyword->next; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void _freeFilter(log_filter *filter) { | ||||||
|  |     keywords_t *it_keyword = | ||||||
|  |         (keywords_t *)(filter + 1); // it_keyword 不是起始地址,请勿free | ||||||
|  |     keywords_t *keyword = it_keyword->next; | ||||||
|  |     keywords_t *next    = NULL; | ||||||
|  |  | ||||||
|  |     while (keyword != NULL) { | ||||||
|  |         next = keyword->next; | ||||||
|  |         free(keyword->key); | ||||||
|  |         free(keyword); | ||||||
|  |         keyword = next; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (filter->handler != NULL) { | ||||||
|  |         filter->handler->_free(filter->handler); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (it_keyword->key != NULL) | ||||||
|  |         free(it_keyword->key); | ||||||
|  |     free(filter); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | log_filter *loggingFilterSubStr(char        *keywords[], | ||||||
|  |                                 log_level    level, | ||||||
|  |                                 log_Handler *handler, | ||||||
|  |                                 bool         jump_out) { | ||||||
|  |     // 分配log_filter和keywords_t的连续内存 | ||||||
|  |     log_filter *filter = | ||||||
|  |         (log_filter *)malloc(sizeof(log_filter) + sizeof(keywords_t)); | ||||||
|  |     filter->_dispose    = _disposeSubstring; | ||||||
|  |     filter->handler     = handler; | ||||||
|  |     filter->level       = level; | ||||||
|  |     filter->jump_out    = jump_out; | ||||||
|  |     filter->_free       = _freeFilter; | ||||||
|  |  | ||||||
|  |     keywords_t *keyword = (keywords_t *)(filter + 1); | ||||||
|  |     keyword->key        = NULL; | ||||||
|  |     int count           = 0; | ||||||
|  |     if (keywords[count] != NULL) { | ||||||
|  |         keyword->key = strdup(keywords[count]); | ||||||
|  |         count++; | ||||||
|  |         keyword->next = NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     while (keywords[count] != NULL) { | ||||||
|  |         keyword->next = (keywords_t *)malloc(sizeof(keywords_t)); | ||||||
|  |         keyword       = keyword->next; | ||||||
|  |         keyword->key  = strdup(keywords[count]); | ||||||
|  |         count++; | ||||||
|  |     } | ||||||
|  |     keyword->next = NULL; | ||||||
|  |  | ||||||
|  |     return filter; | ||||||
|  | } | ||||||
| @@ -1,37 +1,20 @@ | |||||||
| /******************************************** |  | ||||||
|  * @Date: 2024 09 18 |  | ||||||
|  * @Description: 控制台日志处理器 |  | ||||||
|  ********************************************/ |  | ||||||
| #include "logging/logging-handler.h" | #include "logging/logging-handler.h" | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  |  | ||||||
| /** | static void __freeHandlerConsole(log_Handler *handler) { free(handler); } | ||||||
|  * @brief 释放组件 |  | ||||||
|  * @param handler 处理器 |  | ||||||
|  */ |  | ||||||
| static void __freeConsoleHandler(log_Handler *handler) { free(handler); } |  | ||||||
|  |  | ||||||
| /** | static void __outputHandlerConsole(log_Handler *handler, const char *message) { | ||||||
|  * @brief 输出组件 |  | ||||||
|  * @param handler 处理器 |  | ||||||
|  * @param message 消息 |  | ||||||
|  */ |  | ||||||
| static void outputConsoleHandler(log_Handler *handler, const char *message) { |  | ||||||
|     fputs(message, handler->stream); |     fputs(message, handler->stream); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | log_Handler *loggingHandlerConsole() { | ||||||
|  * @brief :控制台日志处理器 |  | ||||||
|  * @param |  | ||||||
|  */ |  | ||||||
| log_Handler *consoleHandler() { |  | ||||||
|     log_Handler *handler = (log_Handler *)malloc(sizeof(log_Handler)); |     log_Handler *handler = (log_Handler *)malloc(sizeof(log_Handler)); | ||||||
|  |  | ||||||
|     handler->stream      = stdout; |     handler->stream      = stdout; | ||||||
|     handler->apply_color = true; |     handler->apply_color = true; | ||||||
|     handler->_free       = __freeConsoleHandler; |     handler->_free       = __freeHandlerConsole; | ||||||
|     handler->output      = outputConsoleHandler; |     handler->output      = __outputHandlerConsole; | ||||||
|  |  | ||||||
|     return handler; |     return handler; | ||||||
| } | } | ||||||
| @@ -1,47 +1,98 @@ | |||||||
| /******************************************** |  | ||||||
|  * @Date: 2024 09 18 |  | ||||||
|  * @Description: 文件日志处理器 |  | ||||||
|  ********************************************/ |  | ||||||
| #include "logging/logging-handler.h" | #include "logging/logging-handler.h" | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | // 根据log_Handler结构体指针起始获取log_Handler_file_ex_t结构体指针 | ||||||
|  | // log_Handler_file_ex_t与log_Handler处于连续内存中 | ||||||
|  | // 使用char*指针进行偏移,达到以偏移1个字节为单位的偏移 | ||||||
|  | #define Handler_file_EX_PRT(handler)                                           \ | ||||||
|  |     ((log_Handler_file_ex_t *)((char *)handler + sizeof(log_Handler))) | ||||||
|  |  | ||||||
|  | #define FILE_NAME_MAX_SIZE 50 | ||||||
|  |  | ||||||
|  | // 文件日志处理器的扩展 | ||||||
|  | typedef struct log_Handler_file_ex_s { | ||||||
|  |     unsigned int file_size; | ||||||
|  |     unsigned int file_size_max; | ||||||
|  |     unsigned int suffix; | ||||||
|  |     char        *file_name; | ||||||
|  | } log_Handler_file_ex_t; | ||||||
|  |  | ||||||
|  | static unsigned int getFileSize(FILE *fp) { | ||||||
|  |     fseek(fp, 0L, SEEK_END); | ||||||
|  |     return ftell(fp); | ||||||
|  | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @brief 文件日志处理器释放组件 |  | ||||||
|  * @param |  | ||||||
|  * @return |  | ||||||
|  */ |  | ||||||
| static void __freeFileHandler(log_Handler *handler) { | static void __freeFileHandler(log_Handler *handler) { | ||||||
|     fclose(handler->stream); |     fclose(handler->stream); | ||||||
|  |     free(Handler_file_EX_PRT(handler)->file_name); | ||||||
|     free(handler); |     free(handler); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | static void changeFile(log_Handler *handler) { | ||||||
|  * @brief 文件日志处理器输出组件 |     log_Handler_file_ex_t *handler_ex = Handler_file_EX_PRT(handler); | ||||||
|  * @param |     fclose(handler->stream); | ||||||
|  * @return |     char new_file_name[FILE_NAME_MAX_SIZE]; | ||||||
|  */ |     sprintf(new_file_name, | ||||||
| static void outputFileHandler(log_Handler *handler, const char *message) { |             "%s_%d.log", | ||||||
|     fputs(message, handler->stream); |             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) { | ||||||
|  * @brief 文件日志处理器 |     fputs(message, handler->stream); | ||||||
|  * @param |     log_Handler_file_ex_t *handler_ex = Handler_file_EX_PRT(handler); | ||||||
|  * @return |     handler_ex->file_size += strlen(message); | ||||||
|  */ |     if (handler_ex->file_size > handler_ex->file_size_max) | ||||||
| log_Handler *fileHandler(const char *name) { |         changeFile(handler); | ||||||
|     char new_file_name[100]; | } | ||||||
|     sprintf(new_file_name, "%s.log", name); |  | ||||||
|  |  | ||||||
|     FILE *fp             = fopen(new_file_name, "at"); | log_Handler *loggingHandlerFile(const char *name, unsigned int max_size) { | ||||||
|  |     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; | ||||||
|  |  | ||||||
|     log_Handler *handler = (log_Handler *)malloc(sizeof(log_Handler)); |     /// 获取未写满于设置最大文件大小的文件名 | ||||||
|  |     do { | ||||||
|  |         sprintf(new_file_name, "%s_%d.log", name, suffix++); | ||||||
|  |         fp = fopen(new_file_name, "at"); | ||||||
|  |         if (fp == NULL) | ||||||
|  |             goto ERROR; | ||||||
|  |         file_size = getFileSize(fp); | ||||||
|  |     } while (file_size > max_size); | ||||||
|  |  | ||||||
|  |     /// 分配log_Handler与记录文件大小的空间 | ||||||
|  |     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); | ||||||
|  |     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->stream      = fp; | ||||||
|     handler->apply_color = false; |     handler->apply_color = false; | ||||||
|     handler->_free       = __freeFileHandler; |     handler->_free       = __freeFileHandler; | ||||||
|     handler->output      = outputFileHandler; |     handler->output      = outputFileHandler; | ||||||
|  |  | ||||||
|     return handler; |     return handler; | ||||||
|  |  | ||||||
|  | ERROR: | ||||||
|  |     if (fp) | ||||||
|  |         fclose(fp); | ||||||
|  |     if (handler) { | ||||||
|  |         free(Handler_file_EX_PRT(handler)->file_name); // 直接释放,无需检查NULL | ||||||
|  |         free(handler); | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
| } | } | ||||||
| @@ -1,122 +0,0 @@ | |||||||
| /******************************************** |  | ||||||
|  * @Date: 2024 08 12 |  | ||||||
|  * @Description: 日志拦截器 |  | ||||||
|  *********************************************/ |  | ||||||
|  |  | ||||||
| #include "logging/logging-interceptor.h" |  | ||||||
| #include <stdbool.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
|  |  | ||||||
| static log_Interceptor *G_interceptor = NULL; |  | ||||||
|  |  | ||||||
| static char **G_keywords              = NULL; |  | ||||||
|  |  | ||||||
| static 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]; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static 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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @description 处理 |  | ||||||
|  * @param |  | ||||||
|  * @return |  | ||||||
|  */ |  | ||||||
| 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)) { |  | ||||||
|             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; |  | ||||||
|  |  | ||||||
|     if (interceptor->handler != NULL) { |  | ||||||
|         interceptor->handler->_free(interceptor->handler); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     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->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; |  | ||||||
| } |  | ||||||
							
								
								
									
										346
									
								
								src/logging.c
									
									
									
									
									
								
							
							
						
						
									
										346
									
								
								src/logging.c
									
									
									
									
									
								
							| @@ -1,233 +1,253 @@ | |||||||
| /******************************************** |  | ||||||
|  * @Date: 2024 08 12 |  | ||||||
|  * @Description: 日志模块 |  | ||||||
|  ********************************************/ |  | ||||||
|  |  | ||||||
| #include "logging.h" | #include "logging.h" | ||||||
|  | #include "logging/logging-core.h" | ||||||
| #include "logging/logging-handler.h" | #include "logging/logging-handler.h" | ||||||
|  | #include "utils/logging-utils.h" | ||||||
|  | #include <stdbool.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <time.h> | #include <time.h> | ||||||
|  |  | ||||||
| Logger *G_LOGGER = NULL; | #define RED    "\033[0;31m" | ||||||
|  | #define RED_B  "\033[0;41m" | ||||||
|  | #define GREEN  "\033[0;32m" | ||||||
|  | #define YELLOW "\033[0;33m" | ||||||
|  | #define BLUE   "\033[0;34m" | ||||||
|  | #define RESET  "\033[0m" | ||||||
|  | #define CYAN   "\033[0;36m" | ||||||
|  |  | ||||||
| #define RED     "\033[0;31m" | #define LOG_BUFFER_SIZE 4096 // 日志缓冲区大小,单个日志长度不能超过该值 | ||||||
| #define GREEN   "\033[0;32m" |  | ||||||
| #define YELLOW  "\033[0;33m" |  | ||||||
| #define BLUE    "\033[0;34m" |  | ||||||
| #define RESET   "\033[0m" |  | ||||||
| #define CYAN    "\033[0;36m" |  | ||||||
| #define MAGENTA "\033[0;35m" |  | ||||||
| #define WHITE   "\033[0;37m" |  | ||||||
| #define BLACK   "\033[0;30m" |  | ||||||
|  |  | ||||||
| #define LOG_BUFFER_SIZE 1024 | static Logger *G_LOGGER = NULL; // 全局日志对象,唯一实例 | ||||||
|  |  | ||||||
| static void getTimeStr(char *timeStr) { |  | ||||||
|     time_t     t = time(NULL); |  | ||||||
|     struct tm *p = localtime(&t); |  | ||||||
|     char       _timeStr[20]; |  | ||||||
|     strftime(_timeStr, sizeof(_timeStr), "%Y-%m-%d %H:%M:%S", p); |  | ||||||
|     strcpy(timeStr, _timeStr); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @description : 添加日志处理器 |  * @brief 为日志添加一个handler | ||||||
|  |  * @param handler 处理器对象 | ||||||
|  */ |  */ | ||||||
| static void addHandler(log_Handler *handler) { | static bool addHandler(log_Handler *handler) { | ||||||
|     if (G_LOGGER == NULL) { |     if (G_LOGGER == NULL || handler == NULL) { | ||||||
|         return; |         return false; | ||||||
|     } |     } | ||||||
|     if (G_LOGGER->handler == NULL) { |     if (G_LOGGER->handler == NULL) { | ||||||
|         G_LOGGER->handler = handler; |         G_LOGGER->handler = handler; | ||||||
|         return; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     G_LOGGER->handler->_free(G_LOGGER->handler); |     G_LOGGER->handler->_free(G_LOGGER->handler); | ||||||
|  |  | ||||||
|     G_LOGGER->handler = handler; |     G_LOGGER->handler = handler; | ||||||
|  |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @description : 添加日志拦截器 |  * @brief 为日志添加一个filter | ||||||
|  * @param |  * @param filter 过滤器对象 | ||||||
|  * @return |  | ||||||
|  */ |  */ | ||||||
| void addInterceptor(log_Interceptor *Interceptor) { | static bool addFilter(log_filter *filter) { | ||||||
|     if (G_LOGGER == NULL) { |     if (G_LOGGER == NULL || filter == NULL) { | ||||||
|         return; |         return false; | ||||||
|     } |     } | ||||||
|     if (G_LOGGER->interceptor == NULL) { |     if (G_LOGGER->filter == NULL) { | ||||||
|         G_LOGGER->interceptor = Interceptor; |         G_LOGGER->filter       = filter; | ||||||
|         return; |         G_LOGGER->filter->next = NULL; | ||||||
|  |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     G_LOGGER->interceptor->_free(G_LOGGER->interceptor); |     log_filter *it = G_LOGGER->filter; | ||||||
|  |     while (it->next != NULL) { | ||||||
|  |         it = it->next; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     G_LOGGER->interceptor = Interceptor; |     it->next     = filter; | ||||||
|  |     filter->next = NULL; | ||||||
|  |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @description : 内置日志记录函数 |  * @brief 输出到handler | ||||||
|  |  * @param handler 处理器对象 | ||||||
|  |  * @param level 日志等级 | ||||||
|  |  * @param color 应用的颜色 | ||||||
|  |  * @param message 日志内容 | ||||||
|  */ |  */ | ||||||
| static void | static void output_to_handler(log_Handler *handler, | ||||||
| _builtin_log(char *level, const char *color, const char *message, ...) { |                               char        *level, | ||||||
|     if (G_LOGGER == NULL) { |                               const char  *color, | ||||||
|         return; |                               const char  *message) { | ||||||
|     } |  | ||||||
|     if (G_LOGGER->handler == NULL) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     char timeStr[20]; |     char timeStr[20]; | ||||||
|     getTimeStr(timeStr); |     getTimeStr(timeStr); | ||||||
|     char logStr[LOG_BUFFER_SIZE]; |     char logStr[LOG_BUFFER_SIZE * 2]; | ||||||
|  |  | ||||||
|     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) |     if (handler->apply_color) | ||||||
|         sprintf( |         snprintf(logStr, | ||||||
|             logStr, "%s %s%s%s %s\n", timeStr, color, level, RESET, message); |                  LOG_BUFFER_SIZE * 2, | ||||||
|  |                  "[%s]: %s %s%s%s %s\n", | ||||||
|  |                  G_LOGGER->name, | ||||||
|  |                  timeStr, | ||||||
|  |                  color, | ||||||
|  |                  level, | ||||||
|  |                  RESET, | ||||||
|  |                  message); | ||||||
|     else |     else | ||||||
|         sprintf(logStr, "%s %s %s\n", timeStr, level, message); |         snprintf(logStr, | ||||||
|  |                  LOG_BUFFER_SIZE * 2, | ||||||
|  |                  "[%s]: %s %s %s\n", | ||||||
|  |                  G_LOGGER->name, | ||||||
|  |                  timeStr, | ||||||
|  |                  level, | ||||||
|  |                  message); | ||||||
|  |  | ||||||
|     handler->output(handler, logStr); |     handler->output(handler, logStr); | ||||||
| } | } | ||||||
|  |  | ||||||
| //*************************记录日志******************************* */ |  | ||||||
| static void fatal(const char *message, ...) { |  | ||||||
|     if (G_LOGGER->level >= LOG_ERROR) { |  | ||||||
|         char    logStr[LOG_BUFFER_SIZE]; |  | ||||||
|         va_list args; |  | ||||||
|         va_start(args, message); |  | ||||||
|         vsprintf(logStr, message, args); |  | ||||||
|         va_end(args); |  | ||||||
|         _builtin_log("Fatal", RED, logStr, args); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void error(const char *message, ...) { |  | ||||||
|     if (G_LOGGER->level >= LOG_ERROR) { |  | ||||||
|         char    logStr[LOG_BUFFER_SIZE]; |  | ||||||
|         va_list args; |  | ||||||
|         va_start(args, message); |  | ||||||
|         vsprintf(logStr, message, args); |  | ||||||
|         va_end(args); |  | ||||||
|         _builtin_log("Error", RED, logStr, args); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void warning(const char *message, ...) { |  | ||||||
|     if (G_LOGGER->level >= LOG_WARNING) { |  | ||||||
|         char    logStr[LOG_BUFFER_SIZE]; |  | ||||||
|         va_list args; |  | ||||||
|         va_start(args, message); |  | ||||||
|         vsprintf(logStr, message, args); |  | ||||||
|         va_end(args); |  | ||||||
|         _builtin_log("Warning", YELLOW, logStr, args); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void info(const char *message, ...) { |  | ||||||
|     if (G_LOGGER->level >= LOG_INFO) { |  | ||||||
|         char    logStr[LOG_BUFFER_SIZE]; |  | ||||||
|         va_list args; |  | ||||||
|         va_start(args, message); |  | ||||||
|         vsprintf(logStr, message, args); |  | ||||||
|         va_end(args); |  | ||||||
|         _builtin_log("Info", GREEN, logStr, args); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void debug(const char *message, ...) { |  | ||||||
|     if (G_LOGGER->level >= LOG_DEBUG) { |  | ||||||
|         char    logStr[LOG_BUFFER_SIZE]; |  | ||||||
|         va_list args; |  | ||||||
|         va_start(args, message); |  | ||||||
|         vsprintf(logStr, message, args); |  | ||||||
|         va_end(args); |  | ||||||
|         _builtin_log("Debug", CYAN, logStr, args); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| //*************************记录日志******************************* */ |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @description :获取一个日志操作对象 |  * @brief 内部日志打印处理核心函数 | ||||||
|  * @param |  * @param level 日志等级 | ||||||
|  |  * @param color 应用的颜色 | ||||||
|  |  * @param message 日志内容 | ||||||
|  |  * @param ... 格式化参数列表 | ||||||
|  * @return |  * @return | ||||||
|  */ |  */ | ||||||
| static Logger *getLogger(const char *name, log_level level) { | static void _builtin_cope(log_level   level_e, | ||||||
|  |                           char       *level, | ||||||
|  |                           const char *color, | ||||||
|  |                           const char *message) { | ||||||
|  |     if (G_LOGGER == NULL) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     if (G_LOGGER->handler == NULL) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     log_filter  *it      = G_LOGGER->filter; | ||||||
|  |     log_Handler *handler = G_LOGGER->handler; | ||||||
|  |  | ||||||
|  |     while (it != NULL) { | ||||||
|  |         if (it->_dispose(it, level_e, message)) { | ||||||
|  |             output_to_handler(it->handler, level, color, message); | ||||||
|  |             if (it->jump_out) | ||||||
|  |                 return; | ||||||
|  |         } | ||||||
|  |         it = it->next; | ||||||
|  |     } | ||||||
|  |     output_to_handler(handler, level, color, message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void log_fatal(const char *file, int line, const char *message, ...) { | ||||||
|  |     if (G_LOGGER->level >= LOG_ERROR) { | ||||||
|  |         char    logStr[LOG_BUFFER_SIZE]; | ||||||
|  |         char    finalLogStr[LOG_BUFFER_SIZE * 2]; | ||||||
|  |         va_list args; | ||||||
|  |         va_start(args, message); | ||||||
|  |         vsprintf(logStr, message, args); | ||||||
|  |         va_end(args); | ||||||
|  |         snprintf( | ||||||
|  |             finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); | ||||||
|  |         _builtin_cope(LOG_FATAL, "Fatal", RED_B, finalLogStr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void log_error(const char *file, int line, const char *message, ...) { | ||||||
|  |     if (G_LOGGER->level >= LOG_ERROR) { | ||||||
|  |         char    logStr[LOG_BUFFER_SIZE]; | ||||||
|  |         char    finalLogStr[LOG_BUFFER_SIZE * 2]; | ||||||
|  |         va_list args; | ||||||
|  |         va_start(args, message); | ||||||
|  |         vsprintf(logStr, message, args); | ||||||
|  |         va_end(args); | ||||||
|  |         snprintf( | ||||||
|  |             finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); | ||||||
|  |         _builtin_cope(LOG_ERROR, "Error", RED, finalLogStr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void log_warning(const char *file, int line, const char *message, ...) { | ||||||
|  |     if (G_LOGGER->level >= LOG_WARNING) { | ||||||
|  |         char    logStr[LOG_BUFFER_SIZE]; | ||||||
|  |         char    finalLogStr[LOG_BUFFER_SIZE * 2]; | ||||||
|  |         va_list args; | ||||||
|  |         va_start(args, message); | ||||||
|  |         vsprintf(logStr, message, args); | ||||||
|  |         va_end(args); | ||||||
|  |         snprintf( | ||||||
|  |             finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); | ||||||
|  |         _builtin_cope(LOG_WARNING, "Warning", YELLOW, finalLogStr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void log_info(const char *file, int line, const char *message, ...) { | ||||||
|  |     if (G_LOGGER->level >= LOG_INFO) { | ||||||
|  |         char    logStr[LOG_BUFFER_SIZE]; | ||||||
|  |         char    finalLogStr[LOG_BUFFER_SIZE * 2]; | ||||||
|  |         va_list args; | ||||||
|  |         va_start(args, message); | ||||||
|  |         vsprintf(logStr, message, args); | ||||||
|  |         va_end(args); | ||||||
|  |         snprintf( | ||||||
|  |             finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); | ||||||
|  |         _builtin_cope(LOG_INFO, "Info", GREEN, finalLogStr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void log_debug(const char *file, int line, const char *message, ...) { | ||||||
|  |     if (G_LOGGER->level >= LOG_DEBUG) { | ||||||
|  |         char    logStr[LOG_BUFFER_SIZE]; | ||||||
|  |         char    finalLogStr[LOG_BUFFER_SIZE * 2]; | ||||||
|  |         va_list args; | ||||||
|  |         va_start(args, message); | ||||||
|  |         vsprintf(logStr, message, args); | ||||||
|  |         va_end(args); | ||||||
|  |         snprintf( | ||||||
|  |             finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); | ||||||
|  |         _builtin_cope(LOG_DEBUG, "Debug", CYAN, finalLogStr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Logger *newDefaultLogger(const char *name, log_level level) { | ||||||
|     if (G_LOGGER != NULL) { |     if (G_LOGGER != NULL) { | ||||||
|  |         G_LOGGER->name  = name; | ||||||
|  |         G_LOGGER->level = level; | ||||||
|         return G_LOGGER; |         return G_LOGGER; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Logger *logger         = (Logger *)malloc(sizeof(Logger)); |     Logger *logger     = (Logger *)malloc(sizeof(Logger)); | ||||||
|     logger->fatal          = fatal; |  | ||||||
|     logger->error          = error; |  | ||||||
|     logger->warning        = warning; |  | ||||||
|     logger->info           = info; |  | ||||||
|     logger->debug          = debug; |  | ||||||
|  |  | ||||||
|     logger->addHandler     = addHandler; |     logger->addHandler = addHandler; | ||||||
|     logger->addInterceptor = addInterceptor; |     logger->addFilter  = addFilter; | ||||||
|  |  | ||||||
|     logger->level          = level; |     logger->level      = level; | ||||||
|     logger->handler        = consoleHandler(name); |     logger->handler    = loggingHandlerConsole(); | ||||||
|     logger->name           = name; |     logger->name       = name; | ||||||
|     logger->interceptor    = NULL; |     logger->filter     = NULL; | ||||||
|  |  | ||||||
|     G_LOGGER               = logger; |     G_LOGGER           = logger; | ||||||
|     return G_LOGGER; |     return G_LOGGER; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @description :创建一个日志对象 |  * @brief 销毁日志对象 | ||||||
|  * @return :Logging* 返回一个日志对象 |  | ||||||
|  */ |  */ | ||||||
| Logging *createLogging() { | log_status destroyDefaultLogger(void) { | ||||||
|     Logging *logging   = (Logging *)malloc(sizeof(Logging)); |  | ||||||
|     logging->getLogger = getLogger; |  | ||||||
|     return logging; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @description :销毁日志对象 |  | ||||||
|  */ |  | ||||||
| log_status destroyLogging(Logging *logging) { |  | ||||||
|     if (logging == NULL) { |  | ||||||
|         return L_ERROR; |  | ||||||
|     } |  | ||||||
|     if (G_LOGGER != NULL) { |     if (G_LOGGER != NULL) { | ||||||
|         if (G_LOGGER->handler != NULL) { |         if (G_LOGGER->handler != NULL) { | ||||||
|             G_LOGGER->handler->_free(G_LOGGER->handler); |             G_LOGGER->handler->_free(G_LOGGER->handler); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (G_LOGGER->interceptor != NULL) { |         if (G_LOGGER->filter != NULL) { | ||||||
|             G_LOGGER->interceptor->_free(G_LOGGER->interceptor); |             log_filter *it   = G_LOGGER->filter; | ||||||
|  |             log_filter *next = NULL; | ||||||
|  |             while (it != NULL) { | ||||||
|  |                 next = it->next; | ||||||
|  |                 it->_free(it); | ||||||
|  |                 it = next; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         free(G_LOGGER); |         free(G_LOGGER); | ||||||
|         G_LOGGER = NULL; |         G_LOGGER = NULL; | ||||||
|     } |     } | ||||||
|     free(logging); |  | ||||||
|     return L_OK; |     return L_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | Logger *getDefaultLogger(void) { | ||||||
|  * @description :获取当前日志操作对象 |  | ||||||
|  * @return 当前唯一的日志操作对象 |  | ||||||
|  */ |  | ||||||
| Logger *getCurrentLogger(void) { |  | ||||||
|     if (G_LOGGER == NULL) { |     if (G_LOGGER == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/utils/logging-utils.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/utils/logging-utils.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | #include "logging-utils.h" | ||||||
|  | #include <string.h> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 获取当前时间字符串 | ||||||
|  |  * @param timeStr 存储时间字符串缓冲区指针 | ||||||
|  |  */ | ||||||
|  | void getTimeStr(char *timeStr) { | ||||||
|  |     time_t     t = time(NULL); | ||||||
|  |     struct tm *p = localtime(&t); | ||||||
|  |     char       _timeStr[20]; | ||||||
|  |     strftime(_timeStr, sizeof(_timeStr), "%Y-%m-%d %H:%M:%S", p); | ||||||
|  |     strcpy(timeStr, _timeStr); | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								src/utils/logging-utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/utils/logging-utils.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | #ifndef __LOGGING_UTILS_H__ | ||||||
|  | #define __LOGGING_UTILS_H__ | ||||||
|  |  | ||||||
|  | void getTimeStr(char *timeStr); | ||||||
|  | #endif // __LOGGING_UTILS_H__ | ||||||
| @@ -1,8 +1,30 @@ | |||||||
| project(test) | project(test) | ||||||
|  |  | ||||||
| add_executable(${PROJECT_NAME}simple test_simple.c) | enable_testing() | ||||||
| target_link_libraries(${PROJECT_NAME}simple Logging) |  | ||||||
|  |  | ||||||
|  | #测试简单基本应用 | ||||||
|  | add_executable(${PROJECT_NAME}simple test-simple.c) | ||||||
|  | target_link_libraries(${PROJECT_NAME}simple logging) | ||||||
|  | if(UNIX) | ||||||
|  |     add_test(test_simple ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}simple) | ||||||
|  | elseif(WIN32) | ||||||
|  |     add_test(test_simple ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}simple.exe) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| add_executable(${PROJECT_NAME}interceptor test_interceptor.c) | #测试简单基本应用 | ||||||
| target_link_libraries(${PROJECT_NAME}interceptor Logging) | add_executable(${PROJECT_NAME}file test-log-file.c) | ||||||
|  | target_link_libraries(${PROJECT_NAME}file logging) | ||||||
|  | if(UNIX) | ||||||
|  |     add_test(test_file ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}file) | ||||||
|  | elseif(WIN32) | ||||||
|  |     add_test(test_file ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}file.exe) | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | #测试拦截器 | ||||||
|  | add_executable(${PROJECT_NAME}filter test-filter.c) | ||||||
|  | target_link_libraries(${PROJECT_NAME}filter logging) | ||||||
|  | if(UNIX) | ||||||
|  |     add_test(test_filter ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}filter) | ||||||
|  | elseif(WIN32) | ||||||
|  |     add_test(test_filter ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}filter.exe) | ||||||
|  | endif() | ||||||
							
								
								
									
										49
									
								
								tests/test-filter.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								tests/test-filter.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | #include "logging.h" | ||||||
|  | #include "logging/logging-core.h" | ||||||
|  | #include "logging/logging-filter.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     char *test1[] = {"This", NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint = | ||||||
|  |         loggingFilterSubStr(test1, | ||||||
|  |                             LOG_DEBUG, | ||||||
|  |                             loggingHandlerFile("test_interceptor", 1024 * 1024), | ||||||
|  |                             false); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint); | ||||||
|  |  | ||||||
|  |     char *test2[]     = {"123", NULL}; | ||||||
|  |  | ||||||
|  |     log_filter *tint1 = loggingFilterSubStr( | ||||||
|  |         test2, | ||||||
|  |         LOG_ERROR, | ||||||
|  |         loggingHandlerFile("test_interceptor1", 1024 * 1024), | ||||||
|  |         true); | ||||||
|  |  | ||||||
|  |     logger->addFilter(tint1); | ||||||
|  |  | ||||||
|  |     printf("\n"); | ||||||
|  |     printf("filter added\n"); | ||||||
|  |     printf("\n"); | ||||||
|  |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								tests/test-log-file.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/test-log-file.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #include "logging.h" | ||||||
|  | #include "logging/logging-handler.h" | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger      *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |     log_Handler *hander = loggingHandlerFile("test_log", 1024 * 1024 * 10); | ||||||
|  |     logger->addHandler(hander); | ||||||
|  |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								tests/test-simple.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/test-simple.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | #include "logging.h" | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||||
|  |  | ||||||
|  |     Log_info("This is an info message"); | ||||||
|  |     Log_error("This is an error message%s", "123"); | ||||||
|  |     Log_fatal("This is an fatal message"); | ||||||
|  |     Log_debug("This is a debug message"); | ||||||
|  |     Log_warning("This is a warning message%s", "123"); | ||||||
|  |  | ||||||
|  |     destroyDefaultLogger(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @@ -1,29 +0,0 @@ | |||||||
| #include "logging.h" |  | ||||||
| #include <stdio.h> |  | ||||||
|  |  | ||||||
| int main() { |  | ||||||
|     Logging *log    = createLogging(); |  | ||||||
|     Logger  *logger = log->getLogger("testLogger", LOG_DEBUG); |  | ||||||
|  |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
| @@ -1,17 +0,0 @@ | |||||||
| #include "logging.h" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| int main() { |  | ||||||
|     Logging *log = createLogging(); |  | ||||||
|     Logger *logger = log->getLogger("testLogger",LOG_DEBUG); |  | ||||||
|      |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user