feat(school_stm32): 添加基础的 STM32F103RCT6 项目结构
- 创建了项目的基本目录结构和文件 - 添加了 CMakeLists.txt 和 Makefile 构建配置 - 创建了 main.c 文件,实现了简单的 LED 闪烁和按键检测功能 - 集成了 SEGGER RTT 库 - 添加了 .gitignore 文件,排除了不必要的生成文件
This commit is contained in:
212
libs/pynic_log/README.md
Normal file
212
libs/pynic_log/README.md
Normal file
@ -0,0 +1,212 @@
|
||||
# Pythonic_log
|
||||
|
||||
纯头文件的轻量化日志库,模仿 Python `logging` 标准库的设计,支持终端彩色输出,不依赖任何标准库。
|
||||
|
||||
## 特性亮点
|
||||
|
||||
- 🚀 **纯头文件实现** - 单文件集成,无需编译
|
||||
- 🧩 **零依赖** - 不依赖标准库(可通过宏配置)
|
||||
- 🌈 **终端彩色输出** - 内置 ANSI 颜色支持
|
||||
- ⚙️ **多级日志系统** - 支持 DEBUG/INFO/WARN/ERROR/FATAL/TRACE
|
||||
- 🧪 **高级断言工具** - 包含 Assert, Panie, TODO 等实用宏
|
||||
- 📦 **模块化设计** - 支持多模块独立日志配置
|
||||
- 🔧 **高度可配置** - 自定义输出、格式化和退出行为
|
||||
|
||||
## 快速入门
|
||||
|
||||
### 基础使用
|
||||
|
||||
```c
|
||||
#include "pylike_log.h"
|
||||
|
||||
int main() {
|
||||
// 基础日志输出
|
||||
LOG_INFO("Application started");
|
||||
LOG_DEBUG("Debug value: %d", 42);
|
||||
LOG_WARN("This is a warning");
|
||||
LOG_ERROR("Something went wrong!");
|
||||
|
||||
// 断言工具
|
||||
int value = 10;
|
||||
Assert(value > 5); // 条件断言
|
||||
AssertFmt(value != 0, "Value cannot be zero");
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 输出示例
|
||||
|
||||
```shell
|
||||
[INFO ] - root - main.c:8 | Application started
|
||||
[DEBUG] - root - main.c:9 | Debug value: 42
|
||||
[WARN ] - root - main.c:10 | This is a warning
|
||||
[ERROR] - root - main.c:11 | Something went wrong!
|
||||
```
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 日志级别控制
|
||||
|
||||
```c
|
||||
// 获取日志器实例
|
||||
logger_t* logger = log_get("my_module");
|
||||
|
||||
// 设置日志级别(只显示 WARN 及以上)
|
||||
log_set_level(logger, LOG_LEVEL_WARN | LOG_LEVEL_ERROR | LOG_LEVEL_FATAL);
|
||||
|
||||
// 模块化日志
|
||||
MLOG_WARN(logger, "Module-specific warning: %s", "Low memory");
|
||||
```
|
||||
|
||||
### 自定义日志处理器
|
||||
|
||||
```c
|
||||
void custom_handler(
|
||||
log_level_t level,
|
||||
const char* module,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* message
|
||||
) {
|
||||
// 自定义处理逻辑(如写入文件/网络)
|
||||
printf("[CUSTOM] %s:%d - %s\n", file, line, message);
|
||||
}
|
||||
|
||||
int main() {
|
||||
logger_t* logger = log_get(NULL);
|
||||
log_set_handler(logger, custom_handler);
|
||||
|
||||
LOG_INFO("This will use custom handler");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 断言系统
|
||||
|
||||
```c
|
||||
void critical_function(int* ptr) {
|
||||
// 空指针检查
|
||||
AssertFmt(ptr != NULL, "Received NULL pointer");
|
||||
|
||||
// 范围检查
|
||||
AssertFmt(*ptr >= 0 && *ptr <= 100, "Value %d out of range", *ptr);
|
||||
|
||||
// 标记未实现功能
|
||||
TODO(); // 触发致命错误
|
||||
}
|
||||
```
|
||||
|
||||
## 配置选项
|
||||
|
||||
### 基本配置宏
|
||||
|
||||
| 宏名称 | 默认值 | 描述 |
|
||||
| :-------------------- | :----- | :--------------- |
|
||||
| `LOGGER_MAX_BUF_SIZE` | 512 | 单条日志最大长度 |
|
||||
| `__LOG_NO_COLOR__` | - | 禁用彩色输出 |
|
||||
| `__NO_STDIO__` | - | 禁用标准库依赖 |
|
||||
|
||||
|
||||
### 标准库替代(嵌入式环境)
|
||||
```c
|
||||
// 在包含头文件前定义这些宏
|
||||
#define _pylike_logout_printf(fmt, ...) my_printf(fmt, ##__VA_ARGS__)
|
||||
#define _pylike_snprintf my_snprintf
|
||||
#define _pylike_exit my_exit
|
||||
|
||||
#include "pylike_log.h"
|
||||
```
|
||||
|
||||
### 颜色自定义
|
||||
编辑 `pylike_color.h` 修改 ANSI 颜色代码,或定义 `__NO_PYLIKE_COLOR__` 完全禁用颜色。
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 性能追踪
|
||||
|
||||
```c
|
||||
void complex_operation() {
|
||||
LOG_TRACE("Entering complex_operation");
|
||||
|
||||
// ... 复杂计算 ...
|
||||
|
||||
LOG_TRACE("Exiting complex_operation");
|
||||
}
|
||||
```
|
||||
|
||||
### 致命错误处理
|
||||
|
||||
```c
|
||||
void load_config() {
|
||||
if (!config_valid) {
|
||||
LOG_FATAL("Invalid configuration - aborting");
|
||||
// 此处会自动调用 exit(-1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 模块化日志系统
|
||||
|
||||
```c
|
||||
// 创建模块专用日志器
|
||||
logger_t network_logger;
|
||||
init_logger(&network_logger, "NETWORK");
|
||||
|
||||
// 设置模块日志级别
|
||||
log_set_level(&network_logger, LOG_LEVEL_DEBUG | LOG_LEVEL_ERROR);
|
||||
|
||||
// 使用模块日志
|
||||
MLOG_DEBUG(&network_logger, "Connecting to %s", "192.168.1.1");
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
### 日志级别
|
||||
|
||||
```c
|
||||
typedef enum log_level {
|
||||
LOG_LEVEL_NOTSET = 0, // 未设置级别(继承默认配置)
|
||||
LOG_LEVEL_DEBUG = 1 << 0, // 调试信息(开发阶段详细信息)
|
||||
LOG_LEVEL_INFO = 1 << 1, // 常规信息(系统运行状态)
|
||||
LOG_LEVEL_WARN = 1 << 2, // 警告信息(潜在问题提示)
|
||||
LOG_LEVEL_ERROR = 1 << 3, // 错误信息(可恢复的错误)
|
||||
LOG_LEVEL_FATAL = 1 << 4, // 致命错误(导致程序终止的严重错误)
|
||||
LOG_LEVEL_TRACE = 1 << 5, // 追踪(性能追踪或者栈帧追踪)
|
||||
LOG_LEVEL_ALL = 0xFF, // 全级别标志(组合所有日志级别)
|
||||
} log_level_t;
|
||||
```
|
||||
|
||||
### 日志器结构
|
||||
|
||||
```c
|
||||
typedef struct logger {
|
||||
const char* name; // 日志器名称(用于模块区分)
|
||||
log_level_t level; // 当前设置的日志级别
|
||||
log_handler handler; // 日志处理回调函数
|
||||
char buf[LOGGER_MAX_BUF_SIZE]; // 格式化缓冲区
|
||||
} logger_t;
|
||||
```
|
||||
|
||||
### 核心函数
|
||||
|
||||
| 函数 | 描述 |
|
||||
| :---------------------------------------- | :------------------- |
|
||||
| `init_logger(logger_t*, const char*)` | 初始化日志器实例 |
|
||||
| `log_get(const char*)` | 获取或创建日志器实例 |
|
||||
| `log_set_level(logger_t*, log_level_t)` | 设置日志级别 |
|
||||
| `log_set_handler(logger_t*, log_handler)` | 设置自定义日志处理器 |
|
||||
|
||||
## 集成指南
|
||||
|
||||
1. 将 `pylike_log.h` 和 `pylike_color.h` 添加到项目
|
||||
2. 在需要日志的源文件中包含头文件
|
||||
3. (可选)配置自定义输出函数(嵌入式系统)
|
||||
4. 使用提供的日志宏记录信息
|
||||
|
||||
## 设计理念
|
||||
|
||||
- **极简主义**:单头文件实现核心功能
|
||||
- **灵活性**:通过宏配置适应各种环境
|
||||
- **Pythonic API**:借鉴 Python logging 的优秀设计
|
||||
- **安全第一**:所有宏都使用 `do {...} while(0)` 包装
|
59
libs/pynic_log/pynic_color.h
Normal file
59
libs/pynic_log/pynic_color.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file color.h
|
||||
* @brief ANSI终端颜色控制码定义
|
||||
*
|
||||
* 提供跨平台的终端文本颜色和样式控制支持
|
||||
*/
|
||||
|
||||
#ifndef __PYNIC_TERMINAL_COLOR_H__
|
||||
#define __PYNIC_TERMINAL_COLOR_H__
|
||||
|
||||
/// @name 前景色控制码
|
||||
/// @{
|
||||
#define ANSI_FG_BLACK "\33[30m" ///< 黑色前景
|
||||
#define ANSI_FG_RED "\33[31m" ///< 红色前景
|
||||
#define ANSI_FG_GREEN "\33[32m" ///< 绿色前景
|
||||
#define ANSI_FG_YELLOW "\33[33m" ///< 黄色前景
|
||||
#define ANSI_FG_BLUE "\33[34m" ///< 蓝色前景
|
||||
#define ANSI_FG_MAGENTA "\33[35m" ///< 品红色前景
|
||||
#define ANSI_FG_CYAN "\33[36m" ///< 青色前景
|
||||
#define ANSI_FG_WHITE "\33[37m" ///< 白色前景
|
||||
/// @}
|
||||
|
||||
/// @name 背景色控制码
|
||||
/// @{
|
||||
#define ANSI_BG_BLACK "\33[40m" ///< 黑色背景
|
||||
#define ANSI_BG_RED "\33[41m" ///< 红色背景
|
||||
#define ANSI_BG_GREEN "\33[42m" ///< 绿色背景
|
||||
#define ANSI_BG_YELLOW "\33[43m" ///< 黄色背景
|
||||
#define ANSI_BG_BLUE "\33[44m" ///< 蓝色背景
|
||||
#define ANSI_BG_MAGENTA "\33[45m" ///< 品红色背景(注:原始代码此处应为45m)
|
||||
#define ANSI_BG_CYAN "\33[46m" ///< 青色背景
|
||||
#define ANSI_BG_WHITE "\33[47m" ///< 白色背景
|
||||
/// @}
|
||||
|
||||
/// @name 文字样式控制码
|
||||
/// @{
|
||||
#define ANSI_UNDERLINED "\33[4m" ///< 下划线样式
|
||||
#define ANSI_BOLD "\33[1m" ///< 粗体样式
|
||||
#define ANSI_NONE "\33[0m" ///< 重置所有样式
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* @def ANSI_FMT
|
||||
* @brief 安全文本格式化宏
|
||||
* @param str 目标字符串
|
||||
* @param fmt ANSI格式序列(可组合多个样式)
|
||||
*
|
||||
* @note 当定义ANSI_FMT_DISABLE时自动禁用颜色输出
|
||||
* @code
|
||||
* printf(ANSI_FMT("Warning!", ANSI_FG_YELLOW ANSI_BOLD));
|
||||
* @endcode
|
||||
*/
|
||||
#ifndef ANSI_FMT_DISABLE
|
||||
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE ///< 启用样式包裹
|
||||
#else
|
||||
#define ANSI_FMT(str, fmt) str ///< 禁用样式输出
|
||||
#endif
|
||||
|
||||
#endif // __PYNIC_TERMINAL_COLOR_H__
|
288
libs/pynic_log/pynic_log.h
Normal file
288
libs/pynic_log/pynic_log.h
Normal file
@ -0,0 +1,288 @@
|
||||
/**
|
||||
* @file pythonic_log.h
|
||||
* @brief 模仿python标准库logger的日志系统核心模块(支持多级日志、断言和异常处理)
|
||||
*/
|
||||
|
||||
#ifndef __PYNIC_LOG_H__
|
||||
#define __PYNIC_LOG_H__
|
||||
|
||||
#ifndef __PYNIC_NO_STDIO__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef _pynic_logout_printf
|
||||
#define _pynic_logout_printf(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef _pynic_snprintf
|
||||
#define _pynic_snprintf snprintf
|
||||
#endif
|
||||
#ifndef _pynic_exit
|
||||
#define _pynic_exit exit
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PYNIC_NO_COLOR__
|
||||
#include "pynic_color.h"
|
||||
#else
|
||||
#ifndef __PYNIC_LOG_NO_COLOR__
|
||||
#define __PYNIC_LOG_NO_COLOR__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PYNIC_LOGGER_MAX_BUF_SIZE
|
||||
#define PYNIC_LOGGER_MAX_BUF_SIZE 512 ///< 单条日志最大缓冲区尺寸
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
// #define __PYNIC_LOG_IMPLIMENT__
|
||||
|
||||
#ifndef _pynic_exit
|
||||
#warning _pynic_exit not defined, it will make some exit not triggered
|
||||
#endif
|
||||
#ifndef _pynic_logout_printf
|
||||
#error _pynic_logout_printf not defined so log will not work
|
||||
#endif
|
||||
#ifndef _pynic_snprintf
|
||||
#error _pynic_logout_printf not defined so log will not work
|
||||
#endif
|
||||
|
||||
#define _PYNIC_STR(str) #str
|
||||
#define PYNIC_STR(str) _PYNIC_STR(str)
|
||||
|
||||
/**
|
||||
* @brief 日志级别枚举
|
||||
*
|
||||
* 定义日志系统的输出级别和组合标志位
|
||||
*/
|
||||
typedef enum log_level {
|
||||
LOG_LEVEL_NOTSET = 0, ///< 未设置级别(继承默认配置)
|
||||
LOG_LEVEL_DEBUG = 1 << 0, ///< 调试信息(开发阶段详细信息)
|
||||
LOG_LEVEL_INFO = 1 << 1, ///< 常规信息(系统运行状态)
|
||||
LOG_LEVEL_WARN = 1 << 2, ///< 警告信息(潜在问题提示)
|
||||
LOG_LEVEL_ERROR = 1 << 3, ///< 错误信息(可恢复的错误)
|
||||
LOG_LEVEL_FATAL = 1 << 4, ///< 致命错误(导致程序终止的严重错误)
|
||||
LOG_LEVEL_TRACE = 1 << 5, ///< 追踪(性能追踪或者栈帧追踪)
|
||||
LOG_LEVEL_ALL = 0xFF, ///< 全级别标志(组合所有日志级别)
|
||||
} log_level_t;
|
||||
|
||||
/**
|
||||
* @brief 日志处理回调函数类型
|
||||
* @param level 日志级别
|
||||
* @param module 模块名称(可为NULL)
|
||||
* @param file 源文件名
|
||||
* @param line 代码行号
|
||||
* @param message 格式化后的日志消息
|
||||
* @todo 待实现模块名称,输入的模块名称,都将被忽略
|
||||
*/
|
||||
typedef void (*pynic_log_handler)(
|
||||
log_level_t level,
|
||||
const char* module,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* message
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 日志器实例结构体
|
||||
*
|
||||
* 每个日志器实例维护独立的配置和缓冲区
|
||||
*/
|
||||
typedef struct logger {
|
||||
const char* name; ///< 日志器名称(用于模块区分)
|
||||
log_level_t level; ///< 当前设置的日志级别
|
||||
pynic_log_handler handler; ///< 日志处理回调函数
|
||||
char buf[PYNIC_LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
|
||||
} logger_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化日志实例 其余参数设置为默认值
|
||||
* @param[in] logger 日志器实例指针
|
||||
* @param[in] name 日志器名称(NULL表示获取默认日志器名称)
|
||||
*/
|
||||
void init_logger(logger_t* logger, const char* name);
|
||||
|
||||
/**
|
||||
* @brief 初始化日志实例
|
||||
* @param[in] logger 日志器实例指针
|
||||
* @param[in] name 日志器名称(NULL表示获取默认日志器名称)
|
||||
* @param[in] handler 日志处理回调函数
|
||||
*/
|
||||
void init_logger_ex(logger_t* logger, const char* name, pynic_log_handler hander);
|
||||
|
||||
// TODO log_set(); 暂未实现 日志注册
|
||||
|
||||
/**
|
||||
* @brief 获取或创建日志器实例
|
||||
* @param[in] name 日志器名称(NULL表示获取默认日志器)
|
||||
* @return 日志器实例指针
|
||||
* @warning 若没有找到相应日志器则会返回根日志器
|
||||
*/
|
||||
logger_t* log_get(const char* name);
|
||||
|
||||
/**
|
||||
* @brief 设置日志级别
|
||||
* @param[in] logger 目标日志器实例
|
||||
* @param[in] level 要设置的日志级别(可组合多个级别)
|
||||
*/
|
||||
void log_set_level(logger_t* logger, log_level_t level);
|
||||
|
||||
/**
|
||||
* @brief 设置自定义日志处理器
|
||||
* @param[in] logger 目标日志器实例
|
||||
* @param[in] handler 自定义处理函数(NULL恢复默认处理)
|
||||
*/
|
||||
void log_set_handler(logger_t* logger, pynic_log_handler handler);
|
||||
|
||||
#ifndef LOG_MAX_MAROC_BUF_SIZE
|
||||
#define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE ///< 宏展开缓冲区尺寸
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def _LOG
|
||||
* @brief 内部日志宏(供其他日志宏调用)
|
||||
* @param _module_ 模块实例(NULL表示使用默认日志器)
|
||||
* @param _level_ 日志级别
|
||||
* @param _msg_ 格式字符串
|
||||
* @param ... 可变参数列表
|
||||
*/
|
||||
#define _LOG(_module_, _level_, _msg_, ...) \
|
||||
do { \
|
||||
logger_t* _logger; \
|
||||
if (_module_ == NULL) _logger = log_get(NULL); \
|
||||
else _logger = _module_; \
|
||||
if (_logger && _logger->handler && (_logger->level & (_level_))) { \
|
||||
_pynic_snprintf(_logger->buf, sizeof(_logger->buf), (_msg_), ##__VA_ARGS__); \
|
||||
_logger->handler((_level_), _logger->name, __FILE__, __LINE__, _logger->buf); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/// @name 模块日志宏
|
||||
/// @{
|
||||
#define MLOG_NOTSET(module, ...) _LOG(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
|
||||
#define MLOG_DEBUG( module, ...) _LOG(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别)
|
||||
#define MLOG_INFO( module, ...) _LOG(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
|
||||
#define MLOG_WARN( module, ...) _LOG(module, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
|
||||
#define MLOG_ERROR( module, ...) _LOG(module, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
|
||||
#define MLOG_FATAL( module, ...) _LOG(module, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
|
||||
#define MLOG_TRACE( module, ...) _LOG(module, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
|
||||
/// @}
|
||||
|
||||
/// @name 快捷日志宏
|
||||
/// @{
|
||||
#define LOG_NOTSET(...) _LOG(NULL, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
|
||||
#define LOG_DEBUG(...) _LOG(NULL, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别)
|
||||
#define LOG_INFO(...) _LOG(NULL, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
|
||||
#define LOG_WARN(...) _LOG(NULL, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
|
||||
#define LOG_ERROR(...) _LOG(NULL, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
|
||||
#define LOG_FATAL(...) _LOG(NULL, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
|
||||
#define LOG_TRACE(...) _LOG(NULL, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* @def _Assert
|
||||
* @brief 断言检查内部宏
|
||||
* @param cond 检查条件表达式
|
||||
* @param ... 错误信息参数(格式字符串+参数)
|
||||
*/
|
||||
#define _Assert(cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
LOG_FATAL(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/// @name 断言工具宏
|
||||
/// @{
|
||||
#define AssertFmt(cond, format, ...) _Assert(cond, "Assertion Failure: " format, ## __VA_ARGS__) ///< 带格式的断言检查
|
||||
#define PanicFmt(format, ...) _Assert(0, "Panic: " format, ## __VA_ARGS__) ///< 立即触发致命错误
|
||||
#ifndef Assert
|
||||
#define Assert(cond) AssertFmt(cond, "cond is `" PYNIC_STR(cond) "`") ///< 基础断言检查
|
||||
#endif
|
||||
#define Panic(...) PanicFmt(__VA_ARGS__) ///< 触发致命错误(带自定义消息)
|
||||
#define TODO() PanicFmt("TODO please implement me") ///< 标记未实现代码(触发致命错误)
|
||||
/// @}
|
||||
|
||||
static inline const char* pynic_level_str(log_level_t level) {
|
||||
const char* level_str;
|
||||
switch (level) {
|
||||
case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break;
|
||||
case LOG_LEVEL_INFO: level_str = "INFO "; break;
|
||||
case LOG_LEVEL_WARN: level_str = "WARN "; break;
|
||||
case LOG_LEVEL_ERROR: level_str = "ERROR"; break;
|
||||
case LOG_LEVEL_FATAL: level_str = "FATAL"; break;
|
||||
case LOG_LEVEL_TRACE: level_str = "TRACE"; break;
|
||||
default: level_str = "NOTSET"; break;
|
||||
}
|
||||
return level_str;
|
||||
}
|
||||
|
||||
#ifdef __PYNIC_TERMINAL_COLOR_H__
|
||||
static inline const char* pynic_level_color(log_level_t level) {
|
||||
const char* color_code = ANSI_NONE;
|
||||
switch (level) {
|
||||
case LOG_LEVEL_DEBUG: color_code = ANSI_FG_CYAN; break;
|
||||
case LOG_LEVEL_INFO: color_code = ANSI_FG_GREEN; break;
|
||||
case LOG_LEVEL_TRACE: color_code = ANSI_FG_BLUE; break;
|
||||
case LOG_LEVEL_WARN: color_code = ANSI_FG_YELLOW; break;
|
||||
case LOG_LEVEL_ERROR: color_code = ANSI_FG_RED; break;
|
||||
case LOG_LEVEL_FATAL: color_code = ANSI_FG_RED ANSI_UNDERLINED; break; // 增强对比度
|
||||
default: color_code = ANSI_NONE;
|
||||
}
|
||||
return color_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __PYNIC_LOG_IMPLIMENT__
|
||||
|
||||
static void __pynic_log_default_handler(log_level_t level, const char* module, const char* file, int line, const char* message) {
|
||||
const char* level_str = pynic_level_str(level);
|
||||
|
||||
/// @note: 定义 __PYNIC_LOG_NO_COLOR__ 会取消颜色输出
|
||||
#ifndef __PYNIC_LOG_NO_COLOR__
|
||||
_pynic_logout_printf(ANSI_BOLD "%s[%s] - %s - %s:%d | %s" ANSI_NONE "\n",
|
||||
pynic_level_color(level), level_str, module, file, line, message);
|
||||
#else
|
||||
_pynic_logout_printf("[%s] %s:%d | %s: %s\n",
|
||||
level_str, file, line, module, message);
|
||||
#endif
|
||||
if (level & LOG_LEVEL_FATAL) {
|
||||
_pynic_exit(-LOG_LEVEL_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
static logger_t __pynic_root_logger = {
|
||||
.name = "root",
|
||||
.level = LOG_LEVEL_ALL,
|
||||
.handler = __pynic_log_default_handler,
|
||||
};
|
||||
|
||||
void init_logger(logger_t* logger, const char* name) {
|
||||
init_logger_ex(logger, name, NULL);
|
||||
}
|
||||
|
||||
void init_logger_ex(logger_t* logger, const char* name, pynic_log_handler hander) {
|
||||
logger->name = name;
|
||||
logger->handler = hander ? hander : __pynic_log_default_handler;
|
||||
log_set_level(logger, LOG_LEVEL_ALL);
|
||||
}
|
||||
|
||||
logger_t* log_get(const char* name) {
|
||||
if (name == NULL) return &__pynic_root_logger;
|
||||
return &__pynic_root_logger;
|
||||
}
|
||||
|
||||
void log_set_level(logger_t* logger, log_level_t level) {
|
||||
if (logger) logger->level = level;
|
||||
else __pynic_root_logger.level = level;
|
||||
}
|
||||
|
||||
void log_set_handler(logger_t* logger, pynic_log_handler handler) {
|
||||
if (logger) logger->handler = handler;
|
||||
else __pynic_root_logger.handler = handler;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __PYNIC_LOG_H__
|
Reference in New Issue
Block a user