日志管理库集成指南(Integration Guide)

3 阅读5分钟

日志管理库集成指南(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.hlog_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.hlog_manager.c
  • 更新 CMakeLists.txt
  • 包含头文件
  • 调用 log_manager_init()log_manager_cleanup()
  • 测试基本写入和读取
  • 验证文件轮转功能
  • 性能测试和优化