日志管理库集成指南(Integration Guide)
快速开始
文件列表
├── log_manager.h # 日志管理库头文件(公共API)
├── log_manager.c # 日志管理库实现
├── log_manager_examples.c # 使用示例和测试用例
├── LOG_STORAGE_SOLUTION.md # 详细的架构文档
└── INTEGRATION_GUIDE.md # 本文件
1️⃣ 核心 API 总结
初始化和清理
int log_manager_init(void); // 初始化日志系统
int log_manager_cleanup(void); // 关闭日志系统
日志写入
int log_manager_write(const char *log_message); // 写入简单日志
int log_manager_printf(const char *format, ...); // 格式化写入(printf风格)
int log_manager_write_level(const char *level, const char *message); // 带日志等级
日志读取
int log_manager_read(const char *filename, char *buffer, size_t max_len);
int log_manager_read_offset(const char *filename, char *buffer, size_t max_len, unsigned int offset);
文件管理
int log_manager_get_file_size(const char *filename, unsigned int *file_size);
int log_manager_list_files(log_file_info_t *files, int max_count, int *actual_count);
int log_manager_delete_file(const char *filename);
int log_manager_cleanup_old_files(int max_files);
int log_manager_clear_all(void);
文件名生成
char* log_manager_generate_filename(char *filename, size_t max_len);
int log_manager_get_current_file_info(log_file_info_t *current_file);
2️⃣ 最小化集成步骤
步骤1:添加文件到项目
将 log_manager.h 和 log_manager.c 复制到项目的 middleware 目录:
src/middleware/chips/ws63/log_manager/
├── CMakeLists.txt
├── log_manager.h
└── log_manager.c
步骤2:修改 CMakeLists.txt
在 src/middleware/CMakeLists.txt 中添加:
add_subdirectory(chips/${CONFIG_CHIP_TYPE}/log_manager)
在 src/middleware/chips/ws63/log_manager/CMakeLists.txt 中添加:
cmake_minimum_required(VERSION 3.5)
file(GLOB_RECURSE LOG_MANAGER_SOURCES "*.c")
add_library(log_manager STATIC ${LOG_MANAGER_SOURCES})
target_include_directories(log_manager PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${MIDD_DIR}/chips/${CONFIG_CHIP_TYPE}/littlefs
)
target_link_libraries(log_manager littlefs)
步骤3:在应用代码中使用
#include "log_manager.h"
void main_application(void)
{
// 初始化
log_manager_init();
// 写入日志
log_manager_write("System started");
log_manager_printf("Temperature: %d°C", 28);
log_manager_write_level("INFO", "Sensor initialized");
// 读取日志
char buffer[4096];
log_manager_read("20250206_143022.log", buffer, sizeof(buffer));
printf("%s\n", buffer);
// 清理
log_manager_cleanup();
}
3️⃣ 常见场景实现
场景A:设备启动日志
void log_device_startup(void)
{
log_manager_init();
log_manager_write_level("INFO", "=== Device Startup ===");
log_manager_write_level("INFO", "Firmware: v1.0.0");
log_manager_write_level("DEBUG", "Initializing sensors");
log_manager_write_level("INFO", "All systems online");
log_manager_cleanup();
}
场景B:周期性传感器采样
void sensor_monitoring_task(void)
{
log_manager_init();
while (1) {
int temp = read_temperature();
int humidity = read_humidity();
log_manager_printf("SENSOR: T=%dC H=%d%% Battery=85%%",
temp, humidity);
sleep(60); // 每分钟一次
}
log_manager_cleanup();
}
场景C:错误诊断
void error_handler(int error_code)
{
log_manager_init();
log_manager_printf("ERROR_CODE: 0x%04X", error_code);
log_manager_write_level("ERROR", "System error detected");
log_manager_write_level("ERROR", "Attempting recovery...");
// 记录调用栈或其他诊断信息
log_manager_printf("Error source: %s:%d", __FILE__, __LINE__);
log_manager_cleanup();
}
场景D:日志查询和导出
void export_logs_to_uart(void)
{
log_manager_init();
// 获取所有日志文件列表
log_file_info_t files[20];
int count = 0;
log_manager_list_files(files, 20, &count);
printf("=== Log Export ===\n");
printf("Total files: %d\n\n", count);
// 逐个读取并导出
for (int i = 0; i < count; i++) {
printf("--- File: %s ---\n", files[i].filename);
char buffer[4096];
log_manager_read(files[i].filename, buffer, sizeof(buffer));
uart_send(buffer, strlen(buffer));
printf("\n");
}
log_manager_cleanup();
}
4️⃣ 内存和存储考虑
内存使用
- 全局结构体
log_manager_t: ~5.5 KB- 20 个文件信息缓存
- 当前文件名缓冲区
存储使用
假设 littlefs 分区 256KB:
- 最多存储数量: ~20-25 个 1MB 级文件
- 实际可用: 根据分区大小调整
LOG_MAX_FILE_SIZE
优化建议
// 根据实际需求调整这些值
#define LOG_MAX_FILE_SIZE (512 * 1024) // 改为 512KB
#define LOG_MAX_FILES 30 // 增加文件数量
5️⃣ 线程安全性
当前实现
- 非线程安全: 适用于单线程 MCU
- 全局变量
g_log_mgr用于状态管理
多线程环境
如果需要多线程支持,执行以下步骤:
5a. 添加互斥锁
#ifdef CONFIG_OSAL_MUTEX
#include "soc_osal.h"
static uint32_t g_log_mgr_mutex;
void log_manager_lock(void)
{
osal_mutex_lock(g_log_mgr_mutex);
}
void log_manager_unlock(void)
{
osal_mutex_unlock(g_log_mgr_mutex);
}
#endif
5b. 在关键函数中加锁
int log_manager_write(const char *log_message)
{
log_manager_lock();
// ... 原有逻辑
log_manager_unlock();
return ret;
}
6️⃣ 性能优化
优化1:缓冲批量写入
// 减少 I/O 次数,而不是每条消息都同步
#define USE_LOG_BUFFER 1 // 启用缓冲
#define LOG_BUFFER_THRESHOLD 512 // 512字节后再同步
优化2:文件压缩存档
对于长期存储,可以压缩旧文件:
// 伪代码
void compress_old_logs(void)
{
log_file_info_t old_log;
// 找到最旧的文件
if (get_oldest_file(&old_log) == 0) {
// 使用 zlib 或其他压缩库
compress_file(old_log.filename);
}
}
优化3:智能文件轮转
// 不是简单的大小限制,考虑时间戳重名
// 当同一秒内多个写入触发轮转时
void rotate_with_sequence(void)
{
static int rotation_seq = 0;
char filename[256];
snprintf(filename, sizeof(filename),
"/logs/%s_%d.log",
get_timestamp(), rotation_seq++);
// ... 创建新文件
}
7️⃣ 调试和故障排除
启用调试输出
在 littlefs_config.h 中启用日志:
#define CONFIG_LFS_ADAPT_DEBUG // littlefs 调试日志
#define CONFIG_LFS_ADAPT_ERROR // littlefs 错误日志
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
fs_adapt_open 返回 -1 | 文件路径无效或目录不存在 | 检查 mkdir 是否成功 |
| 日志写入后立即读取为空 | 未调用 fs_adapt_sync | 每次写入后调用 sync |
| 文件轮转不工作 | 文件大小检查逻辑 | 验证 should_rotate_file() |
| 内存溢出 | 文件列表过多 | 增加 LOG_MAX_FILES 或清理旧文件 |
调试用函数
void debug_print_manager_state(void)
{
printf("Log Manager State:\n");
printf(" Initialized: %d\n", g_log_mgr.initialized);
printf(" Current FD: %d\n", g_log_mgr.current_fd);
printf(" Current file: %s\n", g_log_mgr.current_filename);
printf(" Current size: %u\n", g_log_mgr.current_file_size);
printf(" File count: %d\n", g_log_mgr.file_count);
for (int i = 0; i < g_log_mgr.file_count; i++) {
printf(" [%d] %s - %u bytes\n", i,
g_log_mgr.file_list[i].filename,
g_log_mgr.file_list[i].size);
}
}
8️⃣ 完整示例代码
简洁版使用
#include "log_manager.h"
int main(void)
{
// 初始化
log_manager_init();
// 写入日志
log_manager_write_level("INFO", "Application started");
log_manager_printf("Current time: %ld", time(NULL));
// 读取日志
char buffer[4096];
log_manager_read("2025020_143022.log", buffer, sizeof(buffer));
// 文件管理
unsigned int total_size;
log_manager_get_total_size(&total_size);
printf("Total log size: %u bytes\n", total_size);
// 清理
log_manager_cleanup();
return 0;
}
总结
✅ 已完成的功能
- 时间戳命名文件
- 自动文件轮转 (1MB 限制)
- 格式化日志写入
- 按文件名读取日志
- 文件管理(列表、删除、清理)
⚠️ 需要根据项目调整
- 分区大小(当前假设 256KB)
- 最大文件数量(当前 20 个)
- 文件大小限制(当前 1MB)
- 线程安全性(如需要)
📦 集成检查清单
- 复制
log_manager.h和log_manager.c - 更新 CMakeLists.txt
- 包含头文件
- 调用
log_manager_init()和log_manager_cleanup() - 测试基本写入和读取
- 验证文件轮转功能
- 性能测试和优化