C++应用程序中的日志记录:最佳实践与工具

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么C++中的正确日志记录很重要

日志记录不仅仅是把消息写入文件。在生产环境中,它是您进行监控、调试和审计的主要工具。配置不当的日志记录可能导致关键数据丢失、性能下降(I/O密集型),或者反过来导致磁盘"噪音"堵塞。在本文中,我们将介绍C++中日志记录的最佳实践,帮助您避免常见错误并构建可靠的日志收集系统。



1. 选择库:spdlog vs glog vs std::clog

C++标准库仅提供基础的流std::clog和std::cerr,不适合严肃项目。让我们考虑三种流行方案:



1.1. spdlog —— 现代标准

spdlog是一个仅头文件的库,支持异步日志记录、文件轮转、格式化(类似fmtlib)和多种接收端(文件、控制台、syslog、Kafka)。

主要优势:

  • 高性能(得益于异步线程)
  • 灵活的级别和格式配置
  • 支持结构化日志记录(JSON)
#include <spdlog/spdlog.h>#include <spdlog/sinks/rotating_file_sink.h>

int main() { // 创建轮转文件日志记录器(5个文件,每个10 MB) auto logger = spdlog::rotating_logger_mt("file_logger", "logs/app.log", 1048576 * 10, 5); logger->set_level(spdlog::level::info); logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] %v");

logger->info("Application started"); logger->warn("Low memory: {} MB", free_memory); logger->error("Database connection error: {}", err.what()); return 0;}


1.2. Google glog —— 成熟的解决方案

来自Google的glog库使用简单,内建支持条件日志记录和堆栈转储。缺点是格式化不够灵活且缺乏异步支持。

#include <glog/logging.h>

int main(int argc, char* argv[]) { google::InitGoogleLogging(argv[0]); FLAGS_log_dir = "./logs"; FLAGS_stderrthreshold = google::WARNING; // 将WARNING+级别同时输出到stderr

LOG(INFO) << "Server started on port " << port; LOG_IF(WARNING, memory_usage > 0.9) << "Memory almost exhausted"; LOG(FATAL) << "Critical error, terminating"; return 0;}


1.3. 使用std::clog的自定义日志记录器

仅在调试或非常小的工具中使用std::clog。它不支持轮转、级别或多线程。

#define LOG(level, msg) std::clog << "[" << level << "] " << msg << std::endl;LOG("INFO", "Starting");LOG("ERROR", "Error: " + std::to_string(errno));


2. 配置和架构的最佳实践

如果日志记录架构设计不当,即使是最好的库也无济于事。请遵循以下原则:



2.1. 使用日志级别

定义5-6个级别并严格遵守:

  • TRACE —— 详细调试(函数进入/退出)
  • DEBUG —— 供开发人员使用的调试信息
  • INFO —— 正常应用程序运行(启动、关闭)
  • WARN —— 潜在问题(磁盘空间不足、负载过高)
  • ERROR —— 不会中断运行的错误(异常)
  • FATAL —— 导致应用程序终止的严重错误
// 在生产环境中,设置为WARN以避免INFO消息充斥日志logger->set_level(spdlog::level::warn);


2.2. 结构化日志记录 (JSON)

为了

博客

书籍推荐