Log Manager API 快速参考

4 阅读8分钟

Log Manager API 快速参考

核心 littlefs 适配层 API(项目现有)

文件系统管理

fs_adapt_mount()              // ✅ 挂载文件系统
fs_adapt_unmount()            // ✅ 卸载文件系统  
fs_adapt_mkdir(path)          // ✅ 创建目录

文件操作

fd = fs_adapt_open(path, flags)           // 打开文件,返回文件描述符 (fd)
fs_adapt_close(fd)                        // 关闭文件
bytes = fs_adapt_write(fd, buf, len)      // 写入数据
bytes = fs_adapt_read(fd, buf, len)       // 读取数据
fs_adapt_sync(fd)                         // 同步数据到 Flash
fs_adapt_delete(path)                     // 删除文件
fs_adapt_stat(path, &size)                // 获取文件大小
fs_adapt_seek(fd, offset, whence)         // 文件指针定位

文件打开标志(fcntl.h)

O_RDONLY    // 只读
O_WRONLY    // 只写
O_RDWR      // 读写
O_CREAT     // 创建(不存在时)
O_APPEND    // 追加模式
O_TRUNC     // 截断文件
O_EXCL      // 若文件存在则失败

littlefs 定位方向

LFS_SEEK_SET  // 从文件开头
LFS_SEEK_CUR  // 从当前位置
LFS_SEEK_END  // 从文件末尾

日志管理库 API(新增)

1️⃣ 初始化和清理

// ========= 初始化日志系统 =========
int log_manager_init(void);
// 返回值: 0=成功, -1=失败
// 功能: 挂载文件系统、创建日志目录、初始化管理器
// 调用时机: 应用启动时,其他日志操作前

// ========= 关闭日志系统 =========
int log_manager_cleanup(void);
// 返回值: 0=成功, -1=失败
// 功能: 同步数据、关闭当前文件、卸载文件系统
// 调用时机: 系统关闭时、不再需要日志时

示例:

if (log_manager_init() != 0) {
    printf("日志系统初始化失败\n");
    return -1;
}
// ... 使用日志 ...
log_manager_cleanup();

2️⃣ 日志写入

// ========= 写入简单日志 =========
int log_manager_write(const char *log_message);
// 参数: log_message - 日志内容(以 \0 结尾的字符串)
// 返回值: 写入字节数(含换行符), -1=失败
// 功能: 追加日志消息,自动添加换行符
// 自动功能: 检测文件大小,超过 1MB 自动轮转到新文件

// 示例:
log_manager_write("系统启动成功");
log_manager_write("传感器初始化完成");
// ========= 格式化日志(printf 风格)=========
int log_manager_printf(const char *format, ...);
// 参数: format - 格式字符串(同 printf)
// 返回值: 写入字节数, -1=失败
// 功能: 支持格式化输出

// 示例:
int temp = 28;
int humidity = 65;
log_manager_printf("温度: %d°C, 湿度: %d%%", temp, humidity);
log_manager_printf("电压: %.2fV, 电流: %.1fmA", 3.27f, 45.2f);
log_manager_printf("设备ID: %s, 版本: %s", "WS63-001", "v1.0");
// ========= 带级别的日志 =========
int log_manager_write_level(const char *level, const char *message);
// 参数: 
//   level   - 日志级别: "INFO", "WARN", "ERROR", "DEBUG"
//   message - 日志内容
// 返回值: 写入字节数, -1=失败
// 功能: 自动添加时间戳和级别前缀

// 示例:
log_manager_write_level("INFO", "系统初始化");
log_manager_write_level("WARN", "内存使用率高于 80%");
log_manager_write_level("ERROR", "连接超时,重试中");
log_manager_write_level("DEBUG", "调试信息:变量值 = 123");

// 输出格式示例:
// [14:30:22] [INFO ] 系统初始化
// [14:30:22] [WARN ] 内存使用率高于 80%
// [14:30:22] [ERROR] 连接超时,重试中

3️⃣ 日志读取

// ========= 读取整个日志文件 =========
int log_manager_read(const char *filename, char *buffer, size_t max_len);
// 参数:
//   filename - 日志文件名(不含 /logs/)
//   buffer   - 输出缓冲区
//   max_len  - 缓冲区大小
// 返回值: 读取字节数, 0=文件不存在, -1=失败
// 功能: 读取整个文件内容到缓冲区,末尾添加 \0

// 示例:
char log_content[4096];
int bytes_read = log_manager_read("20250206_143022.log", 
                                   log_content, 
                                   sizeof(log_content));
if (bytes_read > 0) {
    printf("日志内容:\n%s\n", log_content);
} else {
    printf("文件不存在或读取失败\n");
}
// ========= 读取部分日志(指定偏移) =========
int log_manager_read_offset(const char *filename, 
                           char *buffer, size_t max_len, 
                           unsigned int offset);
// 参数:
//   filename - 日志文件名
//   buffer   - 输出缓冲区
//   max_len  - 缓冲区大小
//   offset   - 文件开头的偏移字节数
// 返回值: 读取字节数, -1=失败
// 功能: 从指定位置读取数据(用于读取大文件的一部分)

// 示例:读取最后 512 字节
char last_512[512];
unsigned int file_size = 0;
log_manager_get_file_size("20250206_143022.log", &file_size);
if (file_size > 512) {
    log_manager_read_offset("20250206_143022.log", 
                           last_512, sizeof(last_512),
                           file_size - 512);
    printf("最后 512 字节:\n%s\n", last_512);
}

4️⃣ 文件管理

// ========= 获取文件大小 =========
int log_manager_get_file_size(const char *filename, unsigned int *file_size);
// 参数: 
//   filename  - 日志文件名
//   file_size - 输出参数,存储文件大小
// 返回值: 0=成功, -1=文件不存在或失败

// 示例:
unsigned int size = 0;
if (log_manager_get_file_size("20250206_143022.log", &size) == 0) {
    printf("文件大小: %u 字节\n", size);
}
// ========= 删除日志文件 =========
int log_manager_delete_file(const char *filename);
// 参数: filename - 要删除的日志文件名
// 返回值: 0=成功, -1=失败

// 示例:
if (log_manager_delete_file("20250206_143022.log") == 0) {
    printf("文件已删除\n");
} else {
    printf("删除失败\n");
}
// ========= 列出所有日志文件 =========
int log_manager_list_files(log_file_info_t *files, 
                          int max_count, 
                          int *actual_count);
// 参数:
//   files       - 文件信息数组的输出缓冲区
//   max_count   - 最多返回的文件数
//   actual_count - 实际返回的文件数(可为 NULL)
// 返回值: 0=成功, -1=失败

// log_file_info_t 结构体:
// {
//     char filename[256];      // 文件名
//     unsigned int size;       // 文件大小(字节)
//     time_t created_time;     // 创建时间戳
//     time_t last_modified;    // 最后修改时间
// }

// 示例:
log_file_info_t files[20];
int count = 0;
if (log_manager_list_files(files, 20, &count) == 0) {
    printf("找到 %d 个日志文件:\n", count);
    for (int i = 0; i < count; i++) {
        printf("  [%d] %s - %u 字节\n", i+1, 
               files[i].filename, files[i].size);
    }
}
// ========= 获取总日志大小 =========
int log_manager_get_total_size(unsigned int *total_size);
// 参数: total_size - 输出总大小(字节)
// 返回值: 0=成功, -1=失败

// 示例:
unsigned int total = 0;
if (log_manager_get_total_size(&total) == 0) {
    printf("日志总大小: %u 字节 (%.2f MB)\n", 
           total, total / 1024.0 / 1024.0);
}

5️⃣ 日志清理

// ========= 保持最新的 N 个文件,删除旧文件 =========
int log_manager_cleanup_old_files(int max_files);
// 参数: max_files - 最多保留的文件数
// 返回值: 删除的文件数, -1=失败
// 功能: 当文件数超过 max_files 时,删除最旧的文件

// 示例:只保留最新的 10 个日志文件
int deleted = log_manager_cleanup_old_files(10);
printf("删除了 %d 个旧文件\n", deleted);
// ========= 删除所有日志文件 =========
int log_manager_clear_all(void);
// 返回值: 删除的文件数, -1=失败
// 功能: 删除 /logs 目录下的所有文件,然后创建新的空日志文件
// 注意: 谨慎使用!会丢失所有日志数据

// 示例:
if (log_manager_clear_all() >= 0) {
    printf("所有日志已清空\n");
}

6️⃣ 文件名和信息

// ========= 生成时间戳文件名 =========
char* log_manager_generate_filename(char *filename, size_t max_len);
// 参数: 
//   filename - 输出缓冲区(至少 64 字节)
//   max_len  - 缓冲区大小
// 返回值: 指向 filename 的指针, NULL=失败
// 功能: 生成格式为 /logs/YYYYMMDD_HHMMSS.log 的文件名

// 示例:
char name[256];
log_manager_generate_filename(name, sizeof(name));
printf("生成的文件名: %s\n", name);
// 输出示例: /logs/20250206_143022.log
// ========= 获取当前日志文件信息 =========
int log_manager_get_current_file_info(log_file_info_t *current_file);
// 参数: current_file - 输出当前文件信息
// 返回值: 0=成功, -1=失败

// 示例:
log_file_info_t current;
if (log_manager_get_current_file_info(&current) == 0) {
    printf("当前日志文件: %s\n", current.filename);
    printf("当前文件大小: %u 字节\n", current.size);
}

使用流程图

┌─────────────────┐
│ log_manager_init()     初始化系统
└────────┬────────┘
         │
    ┌────▼────────────────────────┐
    │  选择日志操作                │
    └───┬─────────────────────────┘
        │
   ┌────┴──────────────────────────────┐
   │                                   │
   ▼                                   ▼
写日志                            读日志
├─ write()          ├─ read()
├─ printf()         └─ read_offset()
└─ write_level()    
   │
   ├─ 检查文件大小
   ├─ 超过1MB? → 自动轮转
   ├─ 调用 sync()
   └─ 返回写入字节数
   
┌─────────────────────────────────────┐
│  文件管理                           │
├─ list_files()   列出所有文件       │
├─ get_file_size()  获取文件大小    │
├─ delete_file()  删除特定文件      │
├─ cleanup_old_files()  清理旧文件  │
└─ clear_all()    删除所有文件      │
   │
   ▼
┌──────────────────────┐
│ log_manager_cleanup()   关闭系统
└──────────────────────┘

完整工作示例

#include "log_manager.h"
#include <stdio.h>
#include <time.h>

int main(void)
{
    // 1. 初始化
    if (log_manager_init() != 0) {
        printf("初始化失败\n");
        return -1;
    }
    
    // 2. 写入各种日志
    log_manager_write("日志系统启动");
    
    log_manager_printf("时间戳: %ld", time(NULL));
    
    log_manager_write_level("INFO", "传感器初始化");
    log_manager_write_level("WARN", "电池电量低");
    log_manager_write_level("ERROR", "连接失败");
    
    // 3. 获取当前文件信息
    log_file_info_t current;
    log_manager_get_current_file_info(&current);
    printf("当前日志: %s (%u 字节)\n", current.filename, current.size);
    
    // 4. 列表所有文件
    log_file_info_t files[20];
    int count = 0;
    log_manager_list_files(files, 20, &count);
    printf("共 %d 个日志文件\n", count);
    
    // 5. 读取日志
    char buffer[1024];
    log_manager_read("20250206_143022.log", buffer, sizeof(buffer));
    printf("日志内容:\n%s\n", buffer);
    
    // 6. 清理旧文件(保留 10 个)
    log_manager_cleanup_old_files(10);
    
    // 7. 关闭系统
    log_manager_cleanup();
    
    return 0;
}

常用代码片段

片段1:启动日志记录

log_manager_init();
log_manager_write_level("INFO", "=== 系统启动 ===");
log_manager_printf("固件版本: v1.0.0");
log_manager_printf("编译时间: %s %s", __DATE__, __TIME__);

片段2:周期性日志

while (1) {
    int temp = read_sensor_temp();
    log_manager_printf("温度: %d°C", temp);
    sleep(60);
}

片段3:错误记录

void on_error(int code) {
    log_manager_printf("错误代码: 0x%X", code);
    log_manager_write_level("ERROR", "发生异常");
}

片段4:日志导出

void export_all_logs_via_uart(void) {
    log_file_info_t files[20];
    int count;
    log_manager_list_files(files, 20, &count);
    
    for (int i = 0; i < count; i++) {
        char buffer[4096];
        log_manager_read(files[i].filename, buffer, sizeof(buffer));
        uart_send(buffer, strlen(buffer));
    }
}

片段5:日志查询

void search_logs_by_keyword(const char *keyword) {
    char buffer[4096];
    log_file_info_t files[20];
    int count;
    
    log_manager_list_files(files, 20, &count);
    for (int i = 0; i < count; i++) {
        log_manager_read(files[i].filename, buffer, sizeof(buffer));
        if (strstr(buffer, keyword) != NULL) {
            printf("在 %s 中找到\n", files[i].filename);
        }
    }
}