refactor(logging): implement get_logger and set_logger functions
- Add get_logger and set_logger functions to manage global logger - Update Logger class to use unique_ptr for child loggers - Modify get_child method to use template and transfer ownership - Update logging initialization and shutdown processes - Adjust test cases to use new logger management functions
This commit is contained in:
parent
610a7e4008
commit
ccaa4908b5
|
@ -31,38 +31,17 @@ if (CMAKE_CROSSCOMPILING)
|
|||
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
include_directories(./include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src SRC_LIST)
|
||||
|
||||
aux_source_directory(./src SRC_LIST)
|
||||
|
||||
add_library(exint_static STATIC ${SRC_LIST})
|
||||
add_library(exint SHARED ${SRC_LIST})
|
||||
add_library(exint_static STATIC ${SRC_LIST})
|
||||
set_target_properties(exint_static PROPERTIES OUTPUT_NAME exint)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_compile_options(exint PRIVATE -Wno-nonnull -fvisibility=hidden)
|
||||
endif()
|
||||
|
||||
# 设置测试文件和公共源文件
|
||||
set(TESTS_DIR "${CMAKE_SOURCE_DIR}/tests")
|
||||
set(TEST_COMMON_SOURCE "${TESTS_DIR}/c_testcase.cpp")
|
||||
link_libraries(pthread)
|
||||
|
||||
# 查找所有以 test_ 开头的文件
|
||||
file(GLOB_RECURSE TEST_FILES "${TESTS_DIR}/test_*.cpp")
|
||||
|
||||
# 循环遍历每个测试文件并创建可执行文件
|
||||
foreach(TEST_FILE ${TEST_FILES})
|
||||
# 获取文件名(不带路径和扩展名)
|
||||
get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)
|
||||
|
||||
# 创建可执行文件
|
||||
add_executable(${TEST_NAME} ${TEST_FILE} ${TEST_COMMON_SOURCE} ${SRC_LIST})
|
||||
|
||||
# 将可执行文件路径添加到列表中
|
||||
list(APPEND TEST_EXECUTABLES "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}")
|
||||
endforeach()
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_test(NAME test
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/unittest.py ${TEST_EXECUTABLES}
|
||||
)
|
||||
subdirs(tests)
|
||||
|
|
|
@ -12,7 +12,7 @@ cmake . -B build
|
|||
cmake --build build -j6
|
||||
```
|
||||
|
||||
使用cmake及ctest进行测试:
|
||||
使用cmake调用测试脚本进行测试:
|
||||
|
||||
```bash
|
||||
cmake . -B build
|
||||
|
|
|
@ -158,11 +158,11 @@ extern "C"{
|
|||
if (memcmp((expr1), (expr2), (size)) != 0) { \
|
||||
printf("assertion failed: %s == %s\n", #expr1, #expr2); \
|
||||
printf("\t#0: "); \
|
||||
for (int i = 0; i < (size); i++) { \
|
||||
for (size_t i = 0; i < (size); i++) { \
|
||||
printf("%02X", ((uint8_t*)(expr1))[i]); \
|
||||
} \
|
||||
printf("\n\t#1: "); \
|
||||
for (int i = 0; i < (size); i++) { \
|
||||
for (size_t i = 0; i < (size); i++) { \
|
||||
printf("%02X", ((uint8_t*)(expr2))[i]); \
|
||||
} \
|
||||
printf("\nfile: \"%s\", line %d, in %s\n", __FILE__, __LINE__, __ASSERT_FUNCTION);\
|
||||
|
|
|
@ -74,7 +74,38 @@ public:
|
|||
LoggerOStream operator[](Level level);
|
||||
LoggerOStream operator[](int level);
|
||||
|
||||
Logger* get_child(const std::string& name, Level level = Level::UNKNOWN);
|
||||
void move_children_to(Logger& other);
|
||||
|
||||
template<class T_Logger = Logger>
|
||||
Logger* get_child(const std::string& name, Level level)
|
||||
{
|
||||
Logger* logger;
|
||||
auto sep_pos = name.find(namesep);
|
||||
do {
|
||||
if (name.empty() || sep_pos == 0) {
|
||||
logger = this;
|
||||
break;
|
||||
}
|
||||
std::string base_name;
|
||||
if (sep_pos == std::string::npos) {
|
||||
base_name = name;
|
||||
} else {
|
||||
base_name = name.substr(0, sep_pos);
|
||||
}
|
||||
auto iter = logger_cache.find(base_name);
|
||||
|
||||
if (iter != logger_cache.end()) {
|
||||
logger = iter->second.get();
|
||||
break;
|
||||
}
|
||||
logger = new T_Logger(base_name, level, this);
|
||||
logger_cache[base_name] = std::unique_ptr<Logger>(logger);
|
||||
} while (0);
|
||||
auto seqlen = strlen(namesep);
|
||||
if (sep_pos == std::string::npos || sep_pos + seqlen >= name.size())
|
||||
return logger;
|
||||
return logger->get_child(name.substr(sep_pos + seqlen), level);
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit Logger(const std::string& name, Level level = Level::INFO, Logger* parent = nullptr);
|
||||
|
@ -132,16 +163,18 @@ struct Record
|
|||
Record(const std::string& name, Logger::Level level, const std::string& msg);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Logger::Level level);
|
||||
Logger::Level str2level(const char* level);
|
||||
|
||||
extern std::unique_ptr<Logger> global_logger;
|
||||
|
||||
using LogLevel = Logger::Level;
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Logger::Level level);
|
||||
Logger::Level str2level(const char* level);
|
||||
std::unique_ptr<Logger>& _get_global_logger();
|
||||
Logger& get_global_logger();
|
||||
void set_global_logger(std::unique_ptr<Logger>&& logger);
|
||||
|
||||
template<class T_Logger = Logger>
|
||||
static inline Logger* get_logger(const std::string& name, LogLevel level = LogLevel::UNKNOWN)
|
||||
{
|
||||
return global_logger->get_child(name, level);
|
||||
return _get_global_logger()->get_child<T_Logger>(name, level);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
mkdir -p dist
|
||||
|
||||
zip -r "dist/exint-build-$(date +%Y%m%d-%H%M%S).zip" bin/ lib/ config/\
|
||||
scripts/ README.md
|
||||
scripts/ README.md include/external_interface.h
|
|
@ -2,4 +2,4 @@
|
|||
mkdir -p dist
|
||||
|
||||
tar -czvf "dist/exint-$(date +%Y%m%d-%H%M%S).tar.gz" src/ include/ tests/ config/\
|
||||
scripts/ toolchains/ tools/ README.md CMakeLists.txt mak .gitignore
|
||||
scripts/ toolchains/ README.md CMakeLists.txt mak .gitignore
|
||||
|
|
|
@ -70,7 +70,7 @@ void exint_send(uint32_t type, size_t len, void* data) {
|
|||
event_name = "send_audio";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return;
|
||||
}
|
||||
exint_event(event_name, len, data);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,23 @@
|
|||
|
||||
using namespace logging;
|
||||
|
||||
__attribute__((__init_priority__(8192)))
|
||||
std::unique_ptr<Logger> logging::global_logger(new Logger(LogLevel::WARN));
|
||||
std::unique_ptr<Logger>& logging::_get_global_logger()
|
||||
{
|
||||
static std::unique_ptr<Logger> global_logger(new Logger(LogLevel::WARN));
|
||||
return global_logger;
|
||||
}
|
||||
|
||||
Logger& logging::get_global_logger()
|
||||
{
|
||||
return *_get_global_logger();
|
||||
}
|
||||
|
||||
void logging::set_global_logger(std::unique_ptr<Logger>&& logger)
|
||||
{
|
||||
auto& global_logger = _get_global_logger();
|
||||
global_logger->move_children_to(*logger);
|
||||
global_logger = std::move(logger);
|
||||
}
|
||||
|
||||
Logger::Logger(Level level) : _parent(nullptr), _level(level)
|
||||
{}
|
||||
|
@ -186,35 +201,15 @@ LoggerOStream Logger::operator[](int level)
|
|||
return (*this)[static_cast<Logger::Level>(level)];
|
||||
}
|
||||
|
||||
Logger* Logger::get_child(const std::string& name, Level level)
|
||||
void Logger::move_children_to(Logger& target_logger)
|
||||
{
|
||||
Logger* logger;
|
||||
auto sep_pos = name.find(namesep);
|
||||
do {
|
||||
if (name.empty() || sep_pos == 0) {
|
||||
logger = this;
|
||||
break;
|
||||
if (logger_cache.empty()) return;
|
||||
for (auto it = logger_cache.begin(); it != logger_cache.end(); ) {
|
||||
// Transfer ownership of the child logger to the target_logger
|
||||
it->second->_parent = &target_logger;
|
||||
target_logger.logger_cache.insert(std::move(*it));
|
||||
it = logger_cache.erase(it); // Remove from current logger's cache
|
||||
}
|
||||
std::string base_name;
|
||||
if (sep_pos == std::string::npos) {
|
||||
base_name = name;
|
||||
} else {
|
||||
base_name = name.substr(0, sep_pos);
|
||||
}
|
||||
auto iter = logger_cache.find(base_name);
|
||||
|
||||
if (iter != logger_cache.end()) {
|
||||
logger = iter->second.get();
|
||||
break;
|
||||
}
|
||||
logger = new Logger(base_name, level, this);
|
||||
(*global_logger)[Level::DEBUG] << "created logger" << logger->_name << std::endl;
|
||||
logger_cache[base_name] = std::unique_ptr<Logger>(logger);
|
||||
} while (0);
|
||||
auto seqlen = strlen(namesep);
|
||||
if (sep_pos == std::string::npos || sep_pos + seqlen >= name.size())
|
||||
return logger;
|
||||
return logger->get_child(name.substr(sep_pos + seqlen), level);
|
||||
}
|
||||
|
||||
LoggerOStream::LoggerOStream(Logger& logger, Logger::Level level)
|
||||
|
@ -311,20 +306,17 @@ void log_init(const char* level)
|
|||
} else if (strcasecmp(level, "env") == 0 || strcasecmp(level, "auto") == 0) {
|
||||
level = getenv("LOG_LEVEL");
|
||||
}
|
||||
if (global_logger->children_count()) {
|
||||
global_logger->warn("reseting logger with children");
|
||||
}
|
||||
global_logger = std::unique_ptr<Logger>(new Logger(str2level(level)));
|
||||
set_global_logger(std::unique_ptr<Logger>(new Logger(str2level(level))));
|
||||
}
|
||||
|
||||
int log_level()
|
||||
{
|
||||
return static_cast<int>(global_logger->level());
|
||||
return static_cast<int>(_get_global_logger()->level());
|
||||
}
|
||||
|
||||
void log_set_level(int level)
|
||||
{
|
||||
global_logger->set_level(static_cast<Logger::Level>(level));
|
||||
_get_global_logger()->set_level(static_cast<Logger::Level>(level));
|
||||
}
|
||||
|
||||
void log_log(int level, const char* fmt, ...)
|
||||
|
@ -337,10 +329,5 @@ void log_log(int level, const char* fmt, ...)
|
|||
|
||||
void log_vlog(int level, const char* fmt, va_list args)
|
||||
{
|
||||
if (!global_logger) {
|
||||
vfprintf(stderr, fmt, args);
|
||||
fputc('\n', stderr);
|
||||
return;
|
||||
}
|
||||
global_logger->vlog(static_cast<Logger::Level>(level), fmt, args);
|
||||
_get_global_logger()->vlog(static_cast<Logger::Level>(level), fmt, args);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
project(test)
|
||||
|
||||
set(TESTS_DIR .)
|
||||
set(TEST_COMMON_SOURCE "${TESTS_DIR}/c_testcase.cpp")
|
||||
|
||||
file(GLOB_RECURSE TEST_FILES "${TESTS_DIR}/test_*.cpp")
|
||||
|
||||
foreach(TEST_FILE ${TEST_FILES})
|
||||
get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)
|
||||
add_executable(${TEST_NAME} ${TEST_FILE} ${TEST_COMMON_SOURCE} ${SRC_LIST})
|
||||
list(APPEND TEST_EXECUTABLES "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}")
|
||||
endforeach()
|
||||
|
||||
add_custom_target(test
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/unittest.py ${TEST_EXECUTABLES}
|
||||
DEPENDS ${TEST_EXECUTABLES}
|
||||
)
|
|
@ -132,9 +132,7 @@ static __inline void print_separator_ex(char lc, const char* str, const char* co
|
|||
static int collect_testcase() {
|
||||
for (int i = 0; i < test_case_total; ++i) {
|
||||
puts(test_cases[i].name);
|
||||
// putchar(' ');
|
||||
}
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -197,6 +195,15 @@ static int unittest_testcase(TestCase* tc) {
|
|||
int main(int argc, const char** argv) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
const char* arg = argv[i];
|
||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||
printf("usage: %s [-c] [-u NAME] [-h]\n", argv[0]);
|
||||
printf("\nOptions:\n");
|
||||
printf(" -i, --interactive: run in interactive mode.\n");
|
||||
printf(" -c, --collect: list all test cases.\n");
|
||||
printf(" -u, --unittest: run a single test case.\n");
|
||||
printf(" -h, --help: show the help text.\n");
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(arg, "-i") == 0 || strcmp(arg, "--interactive") == 0) {
|
||||
if (interactive)
|
||||
return interactive(argc, argv);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
using namespace logging;
|
||||
|
||||
static auto& module_logger = *get_logger("test_logging");
|
||||
|
||||
TEST_CASE(test_init) {
|
||||
log_info("test_init before");
|
||||
log_init(NULL);
|
||||
|
@ -23,10 +25,18 @@ TEST_CASE(test_init) {
|
|||
END_TEST;
|
||||
}
|
||||
|
||||
TEST_CASE(test_module_logger)
|
||||
{
|
||||
module_logger.info("test_module_logger1");
|
||||
log_init("debug");
|
||||
module_logger.info("test_module_logger2");
|
||||
END_TEST;
|
||||
}
|
||||
|
||||
TEST_CASE(test_add_stream) {
|
||||
std::stringstream ss;
|
||||
log_init(NULL);
|
||||
logging::global_logger->add_stream(ss);
|
||||
get_global_logger().add_stream(ss);
|
||||
|
||||
log_info("test_stream");
|
||||
auto s = ss.str();
|
||||
|
@ -60,7 +70,7 @@ TEST_CASE(test_add_stream) {
|
|||
assert_str_eq(s.c_str() + (s.length() - 26), "[FATAL] test_stream fatal\n");
|
||||
ss.str("");
|
||||
|
||||
logging::global_logger->log<logging::Logger::Level::DEBUG>("test_stream debug");
|
||||
get_global_logger().log<logging::Logger::Level::DEBUG>("test_stream debug");
|
||||
s = ss.str();
|
||||
assert_str_eq(s.c_str() + (s.length() - 26), "[DEBUG] test_stream debug\n");
|
||||
|
||||
|
@ -69,7 +79,7 @@ TEST_CASE(test_add_stream) {
|
|||
|
||||
TEST_CASE(test_log_stream) {
|
||||
log_init(NULL);
|
||||
auto& logger = *logging::global_logger;
|
||||
auto& logger = get_global_logger();
|
||||
|
||||
std::stringstream ss;
|
||||
logger.add_stream(ss);
|
||||
|
@ -91,7 +101,7 @@ TEST_CASE(test_sub_logger) {
|
|||
auto sublogger = get_logger("sublogger");
|
||||
assert_eq(sublogger->level(), LogLevel::INFO);
|
||||
assert_eq(sublogger->name(), "sublogger");
|
||||
assert_eq(sublogger->parent(), logging::global_logger.get());
|
||||
assert_eq(sublogger->parent(), &get_global_logger());
|
||||
|
||||
auto subsublogger = get_logger("sublogger::subsublogger");
|
||||
assert_eq(subsublogger->level(), LogLevel::INFO);
|
||||
|
@ -104,11 +114,11 @@ TEST_CASE(test_sub_logger) {
|
|||
auto sub1logger = get_logger("sublogger1");
|
||||
assert_eq(sub1logger->level(), LogLevel::INFO);
|
||||
assert_eq(sub1logger->name(), "sublogger1");
|
||||
assert_eq(sub1logger->parent(), logging::global_logger.get());
|
||||
assert_eq(sub1logger->parent(), &get_global_logger());
|
||||
assert_eq(sub1sub1logger->parent(), sub1logger);
|
||||
|
||||
auto root_logger = get_logger("");
|
||||
assert_eq(root_logger, logging::global_logger.get());
|
||||
assert_eq(root_logger, &get_global_logger());
|
||||
auto root_logger1 = get_logger("::");
|
||||
assert_eq(root_logger1, root_logger);
|
||||
auto subsublogger1 = get_logger("sublogger::subsublogger");
|
||||
|
@ -120,12 +130,12 @@ TEST_CASE(test_sub_logger) {
|
|||
auto subsublogger4 = get_logger("sublogger::::::subsublogger");
|
||||
assert_eq(subsublogger4, subsublogger);
|
||||
|
||||
global_logger->set_level(LogLevel::DEBUG);
|
||||
assert_eq(global_logger->level(), LogLevel::DEBUG);
|
||||
get_global_logger().set_level(LogLevel::DEBUG);
|
||||
assert_eq(get_global_logger().level(), LogLevel::DEBUG);
|
||||
assert_eq(sublogger->level(), LogLevel::DEBUG);
|
||||
assert_eq(subsublogger->level(), LogLevel::DEBUG);
|
||||
sublogger->set_level(LogLevel::WARN);
|
||||
assert_eq(global_logger->level(), LogLevel::DEBUG);
|
||||
assert_eq(get_global_logger().level(), LogLevel::DEBUG);
|
||||
assert_eq(sublogger->level(), LogLevel::WARN);
|
||||
assert_eq(subsublogger->level(), LogLevel::WARN);
|
||||
END_TEST;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc-9)
|
||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++-9)
|
||||
|
|
Loading…
Reference in New Issue