如果把 C/C 程序比作一间 24 小时运转的地下工厂没有日志就等于工厂里没装监控、没记值班本 —— 一旦程序崩了、数据错了、接口卡了你只能对着一堆汇编和 core 文件盲猜堪比 “案发现场没线索全靠脑补破案”。很多 C/C 新手写日志只会满屏printf(我到这里了\n)就像用粉笔在墙上随手乱画既没级别、没时间、没行号还会在多线程里乱序刷屏线上出问题根本派不上用场。一份好的日志就是程序的「侦探笔录 黑匣子」精准记录 “什么时间、哪个线程、哪行代码、发生了什么事”排错效率直接提升 10 倍。二、日志核心分级像奶茶甜度一样好记日志不是随便打分级就像奶茶甜度不同场景用不同级别既不齁得慌也不没味道表格日志级别趣味类比C/C 典型使用场景线上是否开启TRACE碎碎念流水账函数进入退出、循环每一步细节仅开发调试用❌ 关闭DEBUG日常工作记录变量值打印、中间结果输出、分支逻辑判断❌ 开发环境开INFO重要事件打卡程序启动 / 退出、模块初始化、核心业务执行成功✅ 常开WARN黄色预警提醒参数非法、重试操作、资源不足但不影响主流程✅ 常开ERROR红色故障报警函数调用失败、内存分配失败、业务逻辑异常✅ 常开FATAL致命灾难现场程序无法继续运行直接终止如段错误前置记录✅ 常开趣味口诀追踪细节用 TRACE调试变量开 DEBUG正常流程打 INFO有惊无险记 WARN功能报错写 ERROR程序凉凉打 FATAL。三、C/C 日志设计黄金准则必带定位信息文件名、行号、函数名出问题一键定位到代码行告别 “大海捞针”必带时间戳精确到毫秒方便按时间排查问题时序多线程安全加锁保护输出避免多线程日志乱码、穿插支持分级开关编译期 / 运行期可关闭低级日志不影响性能支持文件 控制台双输出控制台方便调试文件方便留存排查四、C 语言实战从零实现一个轻量日志库完整可运行 C 语言日志模块支持分级、时间戳、行号、文件输出、线程安全直接嵌入项目即可用。c运行// logger.h #ifndef LOGGER_H #define LOGGER_H #include stdio.h #include pthread.h // 日志级别定义 typedef enum { LOG_LEVEL_TRACE 0, LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARN, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL } LogLevel; // 全局日志配置 typedef struct { LogLevel level; // 最低输出级别 FILE* file; // 输出文件 pthread_mutex_t lock; // 多线程锁 } Logger; extern Logger g_logger; // 初始化日志 void log_init(LogLevel level, const char* filename); // 销毁日志 void log_destroy(); // 核心日志输出函数 void log_write(LogLevel level, const char* file, int line, const char* func, const char* fmt, ...); // 便捷宏封装自动带入文件名、行号、函数名 #define LOG_TRACE(fmt, ...) log_write(LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define LOG_DEBUG(fmt, ...) log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define LOG_INFO(fmt, ...) log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define LOG_WARN(fmt, ...) log_write(LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) log_write(LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define LOG_FATAL(fmt, ...) log_write(LOG_LEVEL_FATAL, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #endifc运行// logger.c #include logger.h #include stdarg.h #include time.h #include string.h #include stdlib.h Logger g_logger; // 获取级别名称 static const char* get_level_name(LogLevel level) { switch(level) { case LOG_LEVEL_TRACE: return TRACE; case LOG_LEVEL_DEBUG: return DEBUG; case LOG_LEVEL_INFO: return INFO ; case LOG_LEVEL_WARN: return WARN ; case LOG_LEVEL_ERROR: return ERROR; case LOG_LEVEL_FATAL: return FATAL; default: return UNKNOWN; } } void log_init(LogLevel level, const char* filename) { g_logger.level level; g_logger.file stdout; // 默认输出到控制台 if (filename ! NULL) { g_logger.file fopen(filename, a); if (g_logger.file NULL) { fprintf(stderr, 日志文件打开失败使用控制台输出\n); g_logger.file stdout; } } pthread_mutex_init(g_logger.lock, NULL); } void log_destroy() { if (g_logger.file ! stdout) { fclose(g_logger.file); } pthread_mutex_destroy(g_logger.lock); } void log_write(LogLevel level, const char* file, int line, const char* func, const char* fmt, ...) { if (level g_logger.level) return; // 获取当前时间 time_t now time(NULL); struct tm* tm_info localtime(now); char time_buf[32]; strftime(time_buf, sizeof(time_buf), %Y-%m-%d %H:%M:%S, tm_info); pthread_mutex_lock(g_logger.lock); // 输出日志头时间 级别 线程ID 文件:行号 函数 fprintf(g_logger.file, [%s] [%s] [tid:%lu] [%s:%d %s] , time_buf, get_level_name(level), (unsigned long)pthread_self(), file, line, func); // 输出自定义内容 va_list args; va_start(args, fmt); vfprintf(g_logger.file, fmt, args); va_end(args); fprintf(g_logger.file, \n); fflush(g_logger.file); pthread_mutex_unlock(g_logger.lock); // FATAL级别直接终止程序 if (level LOG_LEVEL_FATAL) { exit(EXIT_FAILURE); } }c运行// main.c 测试示例 #include logger.h #include unistd.h void test_func(int num) { LOG_DEBUG(进入测试函数参数num%d, num); if (num 0) { LOG_WARN(参数为负数num%d, num); } LOG_INFO(测试函数执行完成); } int main() { // 初始化日志INFO级别以上输出写入app.log文件 log_init(LOG_LEVEL_INFO, app.log); LOG_INFO(程序启动成功); test_func(10); test_func(-5); LOG_ERROR(模拟一个错误数据库连接失败); LOG_INFO(程序运行结束); log_destroy(); return 0; }编译运行后控制台 日志文件的输出展示带时间、级别、行号的规范日志效果。五、日志设计思维导图【思维导图插入位置】 思维导图核心分支日志核心价值排错溯源、运行监控、性能分析、审计留痕6 级日志体系TRACE→DEBUG→INFO→WARN→ERROR→FATAL设计规范信息完整、分级可控、线程安全、滚动存储、数据脱敏C/C 实现宏封装技巧、时间戳实现、线程锁保护、文件 IO 操作进阶优化异步日志、日志滚动、结构化日志、日志分级编译六、C/C 日志避坑趣味清单❌ 满屏printf无差别打印线上全是废话找报错像大海捞针❌ 不加锁多线程输出日志穿插乱码看日志像看打乱的拼图❌ 不打文件名行号只知道报错不知道哪行错了等于白打❌ 线上开 DEBUG/TRACE日志量爆炸不仅拖慢程序还能写满磁盘❌ 敏感信息直接打密码、密钥明文输出直接留下安全漏洞谢谢