Compare commits
	
		
			14 Commits
		
	
	
		
			0fa6097bbf
			...
			v0.5.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6ff484fef8 | |||
|  | 8e512563e4 | ||
|  | 9d3a7bbb8d | ||
|  | 064881c0ad | ||
|  | f0c3a5d56a | ||
|  | 56e1ac52ff | ||
|  | cc53e07788 | ||
|  | a4b4ad7452 | ||
|  | f4494515ca | ||
|  | d0bfc31563 | ||
|  | 650ce0dc3f | ||
|  | 3ef229ed65 | ||
|  | b7f49188ad | ||
|  | d61f7b6fde | 
							
								
								
									
										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(ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) | ||||
| set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) | ||||
| set(CMAKE_C_STANDARD 99) | ||||
|  | ||||
| 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) | ||||
|  | ||||
| @@ -11,7 +20,7 @@ include_directories(${CMAKE_SOURCE_DIR}/include) | ||||
| add_subdirectory(src) | ||||
|  | ||||
| #测试单元 | ||||
| if (SKIPTEST) | ||||
| else() | ||||
| if (TEST) | ||||
|     enable_testing() | ||||
|     add_subdirectory(tests) | ||||
| 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; | ||||
| } | ||||
| ``` | ||||
|  | ||||
							
								
								
									
										171
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,5 +1,7 @@ | ||||
| # C语言日志库logging | ||||
|  | ||||
| [English](README.en.md) | ||||
|  | ||||
| ## 简介 | ||||
|  | ||||
| logging是一个轻量级的简单易用C语言日志库,支持日志级别、日志格式、日志输出、日志文件等功能。 | ||||
| @@ -9,25 +11,51 @@ logging是一个轻量级的简单易用C语言日志库,支持日志级别、 | ||||
| - 支持日志级别: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 | ||||
| #include "logging.h" | ||||
|  | ||||
| int main() { | ||||
|     Logging *log    = newLogging(); | ||||
|     Logger  *logger = log->getLogger("testLogger", LOG_DEBUG); | ||||
|     Logger *logger = newDefaultLogger("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"); | ||||
|     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"); | ||||
|  | ||||
|     log->destroyLogging(log); | ||||
|     destroyDefaultLogger(); | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
| @@ -35,72 +63,117 @@ int main() { | ||||
| ### 文件日志 | ||||
| ```c | ||||
| #include "logging.h" | ||||
| #include "logging/logging-handler.h" | ||||
|  | ||||
| int main() { | ||||
|     Logging *log = newLogging(); | ||||
|     Logger *logger = log->getLogger("testLogger",LOG_DEBUG); | ||||
|      | ||||
|     logger->addHandler(loggingFileHandler("test"));   //为日志对象添加文件处理器 | ||||
|     Logger *logger = newDefaultLogger("testLogger", LOG_DEBUG); | ||||
|     logger->addHandler(loggingHandlerFile("test1", 1024*1024)); | ||||
|  | ||||
|     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"); | ||||
|     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"); | ||||
|  | ||||
|     log->destroyLogging(log); | ||||
|     destroyDefaultLogger(); | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### 日志拦截器 | ||||
| > 支持添加自定义的拦截器, 目前内置了子串拦截器 | ||||
| ### 日志过滤器 | ||||
| > 支持添加自定义的过滤器, 目前内置了子串过滤器 | ||||
|  | ||||
| > 拦截器的作用:可以将拦截到的日志重定向到拦截器的专属处理器中 | ||||
| > 过滤器的作用:可以将过滤到的日志重定向到过滤器的专属处理器中 | ||||
|  | ||||
|  | ||||
| #### 例子 | ||||
| 将拦截到的日志重定向到专属文件处理器中 | ||||
| #### 单个子串过滤器 | ||||
| 将过滤到的日志重定向到专属处理器中 | ||||
| ```c | ||||
| #include "logging.h" | ||||
| #include <stdio.h> | ||||
|  | ||||
| int main() { | ||||
|     Logging *log    = newLogging(); | ||||
|     Logger  *logger = log->getLogger("testLogger", LOG_DEBUG); | ||||
|     Logger  *logger = newDefaultLogger("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"); | ||||
|     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", "你好"}; // 要拦截的字符串 | ||||
|     // 添加拦截器,将拦截到的日志重定向到拦截器的专属处理器中 | ||||
|     log_Interceptor *tint = | ||||
|         loggingSubStringInterceptor(test1, 2, LOG_DEBUG, loggingFileHandler("被拦截")); | ||||
|     char *test1[]         = {"123", "tt", NULL}; | ||||
|  | ||||
|     logger->addInterceptor(tint); | ||||
|     log_filter *tint = loggingFilterSubStr( | ||||
|         test1, | ||||
|         LOG_DEBUG, | ||||
|         loggingHandlerFile("test_interceptor", 1024 * 1024), | ||||
|         true); | ||||
|  | ||||
|     logger->addFilter(tint); | ||||
|  | ||||
|     printf("\n"); | ||||
|     printf("Interceptor added\n"); | ||||
|     printf("filter added\n"); | ||||
|     printf("\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"); | ||||
|     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"); | ||||
|  | ||||
|     log->destroyLogging(log); | ||||
|     destroyDefaultLogger(); | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
|  | ||||
|  | ||||
|  | ||||
| #### 多个子串过滤器 | ||||
| ```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; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| # build | ||||
| ```shell | ||||
| conan create . --build=missing | ||||
| ``` | ||||
							
								
								
									
										29
									
								
								conanfile.py
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								conanfile.py
									
									
									
									
									
								
							| @@ -1,14 +1,11 @@ | ||||
| from conan import ConanFile | ||||
| from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout | ||||
| from conan.tools.files import copy, get | ||||
| from conan.tools.build import check_min_cppstd | ||||
| from conan import tools | ||||
| from conan.tools.files import copy | ||||
| import os | ||||
|  | ||||
|  | ||||
| class loggingRecipe(ConanFile): | ||||
|     name = "logging" | ||||
|     version = "0.2.3" | ||||
|     version = "0.5.1" | ||||
|     license = "MIT" | ||||
|     author = "321640253@qq.com" | ||||
|     url = "https://github.com/WangZhongDian/logging.git" | ||||
| @@ -16,11 +13,11 @@ class loggingRecipe(ConanFile): | ||||
|     topics = ("logging", "C", "simple", "easy-to-use", "log","Logging") | ||||
|  | ||||
|     settings = "os", "compiler", "build_type", "arch" | ||||
|     options = {"shared": [True, False], "fPIC": [True, False]} | ||||
|     default_options = {"shared": False, "fPIC": True} | ||||
|     options = {"shared": [True, False], "fPIC": [True, False],"test":[True,False]} | ||||
|     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): | ||||
|         if self.settings.os == "Windows": | ||||
| @@ -30,8 +27,6 @@ class loggingRecipe(ConanFile): | ||||
|         if self.options.shared: | ||||
|             self.options.rm_safe("fPIC") | ||||
|  | ||||
|  | ||||
|      | ||||
|     def layout(self): | ||||
|         cmake_layout(self) | ||||
|  | ||||
| @@ -39,18 +34,16 @@ class loggingRecipe(ConanFile): | ||||
|         deps = CMakeDeps(self) | ||||
|         deps.generate() | ||||
|         tc = CMakeToolchain(self) | ||||
|         tc.variables["SKIPTEST"]=True | ||||
|         if self.options.shared: | ||||
|             tc.variables["SHARED"] = True | ||||
|         else: | ||||
|             tc.variables["SHARED"] = False | ||||
|         tc.variables["TEST"] = True if self.options.test else False | ||||
|         tc.variables["SHARED"] = True if self.options.shared else False | ||||
|         tc.generate() | ||||
|  | ||||
|     def build(self): | ||||
|         cmake = CMake(self) | ||||
|         cmake.configure() | ||||
|         cmake.build(target="Logging") | ||||
|  | ||||
|         cmake.build() | ||||
|         if self.options.test: | ||||
|             cmake.test() | ||||
|  | ||||
|     def package(self): | ||||
|         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) | ||||
|  | ||||
|     def package_info(self): | ||||
|         self.cpp_info.libs = ["Logging"] | ||||
|         self.cpp_info.libs = ["logging"] | ||||
|   | ||||
| @@ -5,33 +5,61 @@ | ||||
| #include <stdbool.h> | ||||
|  | ||||
| #include "logging/logging-core.h" | ||||
| #include "logging/logging-filter.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 { | ||||
|     log_level        level; | ||||
|     log_Handler     *handler; | ||||
|     log_Interceptor *interceptor; | ||||
|     const char      *name; | ||||
|     void (*fatal)(const char *format, ...); | ||||
|     void (*error)(const char *format, ...); | ||||
|     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); | ||||
|     log_level    level; | ||||
|     log_Handler *handler; | ||||
|     log_filter  *filter; | ||||
|     const char  *name; | ||||
|     bool (*addHandler)(log_Handler *handler); | ||||
|     bool (*addFilter)(log_filter *filter); | ||||
| } Logger; | ||||
|  | ||||
| // 日志类对象 | ||||
| typedef struct Logging { | ||||
|     Logger *(*getLogger)(const char *name, log_level level); | ||||
|     log_status (*setLevel)(Logger *logger, log_level level); | ||||
|     Logger *(*getCurrentLogger)(void); | ||||
|     log_status (*destroyLogging)(struct Logging *logging); | ||||
| } Logging; | ||||
| void log_fatal(const char *file, int line, const char *format, ...); | ||||
| void log_error(const char *file, int line, const char *format, ...); | ||||
| void log_warning(const char *file, int line, const char *format, ...); | ||||
| void log_info(const char *file, int line, const char *format, ...); | ||||
| void log_debug(const char *file, int line, const char *format, ...); | ||||
|  | ||||
| Logging *newLogging(); // 创建日志类对象 | ||||
| /** | ||||
| * @brief | ||||
| 创建默认日志对象,日志对象为单例模式,后续可通过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__ | ||||
| @@ -1,8 +1,12 @@ | ||||
| #ifndef __LOGGING_CORE_H__ | ||||
| #define __LOGGING_CORE_H__ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| typedef enum { | ||||
|     LOG_FATAL, | ||||
|     LOG_FATAL = 0, | ||||
|     LOG_ERROR, | ||||
|     LOG_WARNING, | ||||
|     LOG_INFO, | ||||
| @@ -14,5 +18,8 @@ typedef enum { | ||||
|     L_OK, | ||||
| } log_status; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #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> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| typedef struct log_Handler { | ||||
|     void* stream; | ||||
|     bool apply_color; | ||||
|     void (*_free)(struct log_Handler* handler);//释放资源 | ||||
|     void (*output)(struct log_Handler* handler,const char* message); | ||||
|     void *stream; | ||||
|     bool  apply_color; | ||||
|     void (*_free)(struct log_Handler *handler); | ||||
|     void (*output)(struct log_Handler *handler, const char *message); | ||||
| } log_Handler; | ||||
|  | ||||
| /** | ||||
|  * @brief 文件处理器 | ||||
|  * @param name 文件名 | ||||
|  * @param max_size 文件最大大小 | ||||
|  * @return | ||||
|  */ | ||||
| log_Handler *loggingHandlerFile(const char *name, unsigned int max_size); | ||||
|  | ||||
| log_Handler* loggingFileHandler(const char* name);      | ||||
| log_Handler* loggingConsoleHandler(); | ||||
| /** | ||||
|  * @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 *loggingSubStringInterceptor(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}/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) | ||||
|     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,36 +1,20 @@ | ||||
| /******************************************** | ||||
|  * @Date: 2024 09 18 | ||||
|  * @Description: 控制台日志处理器 | ||||
|  ********************************************/ | ||||
| #include "logging/logging-handler.h" | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| /** | ||||
|  * @brief 释放组件 | ||||
|  * @param handler 处理器 | ||||
|  */ | ||||
| static void __freeConsoleHandler(log_Handler *handler) { free(handler); } | ||||
| static void __freeHandlerConsole(log_Handler *handler) { free(handler); } | ||||
|  | ||||
| /** | ||||
|  * @brief 输出组件 | ||||
|  * @param handler 处理器 | ||||
|  * @param message 消息 | ||||
|  */ | ||||
| static void outputConsoleHandler(log_Handler *handler, const char *message) { | ||||
| static void __outputHandlerConsole(log_Handler *handler, const char *message) { | ||||
|     fputs(message, handler->stream); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief :控制台日志处理器 | ||||
|  */ | ||||
| log_Handler *loggingConsoleHandler() { | ||||
| log_Handler *loggingHandlerConsole() { | ||||
|     log_Handler *handler = (log_Handler *)malloc(sizeof(log_Handler)); | ||||
|  | ||||
|     handler->stream      = stdout; | ||||
|     handler->apply_color = true; | ||||
|     handler->_free       = __freeConsoleHandler; | ||||
|     handler->output      = outputConsoleHandler; | ||||
|     handler->_free       = __freeHandlerConsole; | ||||
|     handler->output      = __outputHandlerConsole; | ||||
|  | ||||
|     return handler; | ||||
| } | ||||
| @@ -1,45 +1,98 @@ | ||||
| /******************************************** | ||||
|  * @Date: 2024 09 18 | ||||
|  * @Description: 文件日志处理器 | ||||
|  ********************************************/ | ||||
| #include "logging/logging-handler.h" | ||||
| #include <stdio.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 文件日志处理器释放组件 | ||||
|  */ | ||||
| static void __freeFileHandler(log_Handler *handler) { | ||||
|     fclose(handler->stream); | ||||
|     free(Handler_file_EX_PRT(handler)->file_name); | ||||
|     free(handler); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief 文件日志处理器输出组件 | ||||
|  * @param handler 文件日志处理器 | ||||
|  * @param message 消息 | ||||
|  */ | ||||
| static void outputFileHandler(log_Handler *handler, const char *message) { | ||||
|     fputs(message, handler->stream); | ||||
| static void changeFile(log_Handler *handler) { | ||||
|     log_Handler_file_ex_t *handler_ex = Handler_file_EX_PRT(handler); | ||||
|     fclose(handler->stream); | ||||
|     char new_file_name[FILE_NAME_MAX_SIZE]; | ||||
|     sprintf(new_file_name, | ||||
|             "%s_%d.log", | ||||
|             handler_ex->file_name, | ||||
|             ++handler_ex->suffix); | ||||
|     handler->stream       = fopen(new_file_name, "at"); | ||||
|     handler_ex->file_size = getFileSize(handler->stream); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @brief 文件日志处理器 | ||||
|  * @param   name 文件名 | ||||
|  * @return  log_Handler * | ||||
|  */ | ||||
| log_Handler *loggingFileHandler(const char *name) { | ||||
|     char new_file_name[100]; | ||||
|     sprintf(new_file_name, "%s.log", name); | ||||
| static void outputFileHandler(log_Handler *handler, const char *message) { | ||||
|     fputs(message, handler->stream); | ||||
|     log_Handler_file_ex_t *handler_ex = Handler_file_EX_PRT(handler); | ||||
|     handler_ex->file_size += strlen(message); | ||||
|     if (handler_ex->file_size > handler_ex->file_size_max) | ||||
|         changeFile(handler); | ||||
| } | ||||
|  | ||||
|     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->apply_color = false; | ||||
|     handler->_free       = __freeFileHandler; | ||||
|     handler->output      = outputFileHandler; | ||||
|  | ||||
|     return handler; | ||||
|  | ||||
| ERROR: | ||||
|     if (fp) | ||||
|         fclose(fp); | ||||
|     if (handler) { | ||||
|         free(Handler_file_EX_PRT(handler)->file_name); // 直接释放,无需检查NULL | ||||
|         free(handler); | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
| @@ -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 *loggingSubStringInterceptor(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; | ||||
| } | ||||
							
								
								
									
										355
									
								
								src/logging.c
									
									
									
									
									
								
							
							
						
						
									
										355
									
								
								src/logging.c
									
									
									
									
									
								
							| @@ -1,248 +1,255 @@ | ||||
| /******************************************** | ||||
|  * @Date: 2024 08 12 | ||||
|  * @Description: 日志模块 | ||||
|  ********************************************/ | ||||
| #include "logging.h" | ||||
| #include "logging/logging-core.h" | ||||
| #include "logging/logging-handler.h" | ||||
| #include "utils/logging-utils.h" | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #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 MAGENTA "\033[0;35m" | ||||
| #define WHITE   "\033[0;37m" | ||||
| #define BLACK   "\033[0;30m" | ||||
| #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 LOG_BUFFER_SIZE 1024 | ||||
| #define LOG_BUFFER_SIZE 4096 // 日志缓冲区大小,单个日志长度不能超过该值 | ||||
|  | ||||
| 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); | ||||
| } | ||||
| static Logger *G_LOGGER = NULL; // 全局日志对象,唯一实例 | ||||
|  | ||||
| /** | ||||
|  * @description : 添加日志处理器 | ||||
|  * @brief 为日志添加一个handler | ||||
|  * @param handler 处理器对象 | ||||
|  */ | ||||
| static void addHandler(log_Handler *handler) { | ||||
|     if (G_LOGGER == NULL) { | ||||
|         return; | ||||
| static bool addHandler(log_Handler *handler) { | ||||
|     if (G_LOGGER == NULL || handler == NULL) { | ||||
|         return false; | ||||
|     } | ||||
|     if (G_LOGGER->handler == NULL) { | ||||
|         G_LOGGER->handler = handler; | ||||
|         return; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     G_LOGGER->handler->_free(G_LOGGER->handler); | ||||
|  | ||||
|     G_LOGGER->handler = handler; | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @description : 添加日志拦截器 | ||||
|  * @param | ||||
|  * @return | ||||
|  * @brief 为日志添加一个filter | ||||
|  * @param filter 过滤器对象 | ||||
|  */ | ||||
| void addInterceptor(log_Interceptor *Interceptor) { | ||||
|     if (G_LOGGER == NULL) { | ||||
|         return; | ||||
| static bool addFilter(log_filter *filter) { | ||||
|     if (G_LOGGER == NULL || filter == NULL) { | ||||
|         return false; | ||||
|     } | ||||
|     if (G_LOGGER->interceptor == NULL) { | ||||
|         G_LOGGER->interceptor = Interceptor; | ||||
|         return; | ||||
|     if (G_LOGGER->filter == NULL) { | ||||
|         G_LOGGER->filter       = filter; | ||||
|         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 | ||||
| _builtin_log(char *level, const char *color, const char *message, ...) { | ||||
|     if (G_LOGGER == NULL) { | ||||
|         return; | ||||
|     } | ||||
|     if (G_LOGGER->handler == NULL) { | ||||
|         return; | ||||
|     } | ||||
| static void output_to_handler(log_Handler *handler, | ||||
|                               char        *level, | ||||
|                               const char  *color, | ||||
|                               const char  *message) { | ||||
|     char timeStr[20]; | ||||
|     getTimeStr(timeStr); | ||||
|     char logStr[LOG_BUFFER_SIZE]; | ||||
|  | ||||
|     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; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // 判断处理器是否应用颜色 | ||||
|     char logStr[LOG_BUFFER_SIZE * 2]; | ||||
|     if (handler->apply_color) | ||||
|         sprintf(logStr, | ||||
|                 "%s: %s %s%s%s %s\n", | ||||
|                 G_LOGGER->name, | ||||
|                 timeStr, | ||||
|                 color, | ||||
|                 level, | ||||
|                 RESET, | ||||
|                 message); | ||||
|         snprintf(logStr, | ||||
|                  LOG_BUFFER_SIZE * 2, | ||||
|                  "[%s]: %s %s%s%s %s\n", | ||||
|                  G_LOGGER->name, | ||||
|                  timeStr, | ||||
|                  color, | ||||
|                  level, | ||||
|                  RESET, | ||||
|                  message); | ||||
|     else | ||||
|         sprintf( | ||||
|             logStr, "%s: %s %s %s\n", G_LOGGER->name, timeStr, level, message); | ||||
|         snprintf(logStr, | ||||
|                  LOG_BUFFER_SIZE * 2, | ||||
|                  "[%s]: %s %s %s\n", | ||||
|                  G_LOGGER->name, | ||||
|                  timeStr, | ||||
|                  level, | ||||
|                  message); | ||||
|  | ||||
|     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_B, 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 :获取一个日志操作对象 | ||||
|  * @param | ||||
|  * @brief 内部日志打印处理核心函数 | ||||
|  * @param level 日志等级 | ||||
|  * @param color 应用的颜色 | ||||
|  * @param message 日志内容 | ||||
|  * @param ... 格式化参数列表 | ||||
|  * @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) { | ||||
|         G_LOGGER->name  = name; | ||||
|         G_LOGGER->level = level; | ||||
|         return G_LOGGER; | ||||
|     } | ||||
|  | ||||
|     Logger *logger         = (Logger *)malloc(sizeof(Logger)); | ||||
|     // 方法 | ||||
|     logger->fatal          = fatal; | ||||
|     logger->error          = error; | ||||
|     logger->warning        = warning; | ||||
|     logger->info           = info; | ||||
|     logger->debug          = debug; | ||||
|     Logger *logger     = (Logger *)malloc(sizeof(Logger)); | ||||
|  | ||||
|     logger->addHandler     = addHandler; | ||||
|     logger->addInterceptor = addInterceptor; | ||||
|     logger->addHandler = addHandler; | ||||
|     logger->addFilter  = addFilter; | ||||
|  | ||||
|     // 属性 | ||||
|     logger->level          = level; | ||||
|     logger->handler        = loggingConsoleHandler(); | ||||
|     logger->name           = name; | ||||
|     logger->interceptor    = NULL; | ||||
|     logger->level      = level; | ||||
|     logger->handler    = loggingHandlerConsole(); | ||||
|     logger->name       = name; | ||||
|     logger->filter     = NULL; | ||||
|  | ||||
|     G_LOGGER               = logger; | ||||
|     G_LOGGER           = logger; | ||||
|     return G_LOGGER; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @description :销毁日志对象 | ||||
|  * @brief 销毁日志对象 | ||||
|  */ | ||||
| log_status destroyLogging(Logging *logging) { | ||||
|     if (logging == NULL) { | ||||
|         return L_ERROR; | ||||
|     } | ||||
| log_status destroyDefaultLogger(void) { | ||||
|     if (G_LOGGER != NULL) { | ||||
|         if (G_LOGGER->handler != NULL) { | ||||
|             G_LOGGER->handler->_free(G_LOGGER->handler); | ||||
|         } | ||||
|  | ||||
|         if (G_LOGGER->interceptor != NULL) { | ||||
|             G_LOGGER->interceptor->_free(G_LOGGER->interceptor); | ||||
|         if (G_LOGGER->filter != NULL) { | ||||
|             log_filter *it   = G_LOGGER->filter; | ||||
|             log_filter *next = NULL; | ||||
|             while (it != NULL) { | ||||
|                 next = it->next; | ||||
|                 it->_free(it); | ||||
|                 it = next; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         free(G_LOGGER); | ||||
|         G_LOGGER = NULL; | ||||
|     } | ||||
|     free(logging); | ||||
|     return L_OK; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @description :获取当前日志操作对象 | ||||
|  * @return 当前唯一的日志操作对象 | ||||
|  */ | ||||
| Logger *getCurrentLogger(void) { | ||||
| Logger *getDefaultLogger(void) { | ||||
|     if (G_LOGGER == NULL) { | ||||
|         return NULL; | ||||
|     } | ||||
|     return G_LOGGER; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @description :创建一个日志对象 | ||||
|  * @return :Logging* 返回一个日志对象 | ||||
|  */ | ||||
| Logging *newLogging() { | ||||
|     Logging *logging          = (Logging *)malloc(sizeof(Logging)); | ||||
|     logging->getLogger        = getLogger; | ||||
|     logging->destroyLogging   = destroyLogging; | ||||
|     logging->getCurrentLogger = getCurrentLogger; | ||||
|     return logging; | ||||
| } | ||||
							
								
								
									
										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) | ||||
|  | ||||
| add_executable(${PROJECT_NAME}simple test_simple.c) | ||||
| target_link_libraries(${PROJECT_NAME}simple Logging) | ||||
| enable_testing() | ||||
|  | ||||
| #测试简单基本应用 | ||||
| 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,33 +0,0 @@ | ||||
| #include "logging.h" | ||||
| #include <stdio.h> | ||||
|  | ||||
| int main() { | ||||
|     Logging *log    = newLogging(); | ||||
|     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 = | ||||
|         loggingSubStringInterceptor(test1, 2, LOG_DEBUG, loggingFileHandler("被拦截")); | ||||
|  | ||||
|     logger->addInterceptor(tint); | ||||
|  | ||||
|     printf("\n"); | ||||
|     printf("Interceptor added\n"); | ||||
|     printf("\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"); | ||||
|  | ||||
|     log->destroyLogging(log); | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,15 +0,0 @@ | ||||
| #include "logging.h" | ||||
|  | ||||
| int main() { | ||||
|     Logging *log    = newLogging(); | ||||
|     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"); | ||||
|  | ||||
|     log->destroyLogging(log); | ||||
|     return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user