【C++】:C++聊天室后台服务器之Spdlog日志组件安装与使用
Spdlog 日志组件的安装及使用
简介
spdlog 是一个高性能、超快速、零配置的 C++ 日志库,提供简洁的 API 和丰富的功能,同时保持高性能的日志记录。
GitHub 链接: https://github.com/gabime/spdlog
主要特点
- 高性能:专为速度设计,高负载下仍保持良好性能
- 零配置:只需包含头文件即可使用
- 异步日志:支持异步记录,减少对主线程影响
- 格式化:支持自定义日志格式(时间戳、线程 ID、日志级别等)
- 多平台:支持 Windows、Linux、macOS
- 丰富的 API:提供多种日志级别和操作符重载
安装方法
1. 命令安装(Ubuntu)
sudo apt-get install libspdlog-dev
2. 源码安装
git clone https://github.com/gabime/spdlog.git
cd spdlog/
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ...
make && sudo make install
基本使用
包含头文件
#include <spdlog/spdlog.h>
日志级别
namespace level {enum level_enum : int {trace = SPDLOG_LEVEL_TRACE, // 跟踪debug = SPDLOG_LEVEL_DEBUG, // 调试info = SPDLOG_LEVEL_INFO, // 信息warn = SPDLOG_LEVEL_WARN, // 警告err = SPDLOG_LEVEL_ERROR, // 错误critical = SPDLOG_LEVEL_CRITICAL, // 严重错误off = SPDLOG_LEVEL_OFF, // 关闭n_levels};
}
自定义日志格式
logger->set_pattern("%Y-%m-%d %H:%M:%S [%t] [%-71] %v");
格式说明:
%t- 线程 ID%n- 日志器名称%l- 日志级别(INFO、DEBUG、ERROR 等)%v- 日志内容%Y- 年%m- 月%d- 日%H- 小时(24小时制)%M- 分钟%S- 秒
核心类介绍
日志记录器 (logger)
namespace spdlog {
class logger {logger(std::string name);void set_level(level::level_enum log_level);void set_formatter(std::unique_ptr<formatter> f);// 各种日志级别的输出方法template<typename... Args>void trace(fmt::format_string<Args...> fmt, Args &&...args)template<typename... Args>void debug(fmt::format_string<Args...> fmt, Args &&...args)template<typename... Args>void info(fmt::format_string<Args...> fmt, Args &&...args)template<typename... Args>void warn(fmt::format_string<Args...> fmt, Args &&...args)template<typename... Args>void error(fmt::format_string<Args...> fmt, Args &&...args)template<typename... Args>void critical(fmt::format_string<Args...> fmt, Args &&...args)void flush(); // 刷新日志void flush_on(level::level_enum log_level); // 指定级别时立即刷新
};
异步日志记录器
class async_logger final : public logger {async_logger(std::string logger_name,sinks_init_list sinks_list,std::weak_ptr<details::thread_pool> tp,async_overflow_policy overflow_policy = async_overflow_policy::block);
};// 线程池类
class SPDLOG_API thread_pool {thread_pool(size_t q_max_items, size_t threads_n);
};// 初始化线程池
inline void init_thread_pool(size_t q_size, size_t thread_count)
使用示例
1. 多输出目标示例
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>void multi_sink_example() {// 创建控制台输出auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();console_sink->set_level(spdlog::level::warn); // 只输出警告及以上级别console_sink->set_pattern("[multi_sink_example] [%^%1%$] %v");// 创建文件输出auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);file_sink->set_level(spdlog::level::trace); // 输出所有级别// 创建日志器spdlog::logger logger("multi_sink", {console_sink, file_sink});logger.set_level(spdlog::level::debug);logger.set_pattern("%Y-%m-%d %H:%M:%S [%l] %v");logger.warn("this should appear in both console and file");logger.info("this message should not appear in the console, only in the file");
}
2. 异步日志示例
#include <spdlog/spdlog.h>
#include <spdlog/async.h>void async_example() {// 初始化线程池spdlog::init_thread_pool(32768, 1);// 创建异步日志器auto async_logger = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");async_logger->set_pattern("%Y-%m-%d %H:%M:%S [%l] %v");for (int i = 1; i < 101; ++i) {// 使用 {} 作为占位符,spdlog 会自动识别数据类型async_logger->info("Async message #{} {}", i, "hello");}
}int main() {// multi_sink_example();async_example();return 0;
}
编译命令
g++ -std=c++17 main.cc -o main -lspdlog -lfmt
二次封装
为了更方便地使用 spdlog,可以进行二次封装:
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/async.h>namespace bite {std::shared_ptr<spdlog::logger> g_logger;void init_logger(const std::string &logger_name,const std::string &logger_file,spdlog::level::level_enum logger_level) {spdlog::flush_on(logger_level);spdlog::init_thread_pool(32768, 1);if (logger_file == "stdout")g_logger = spdlog::stdout_color_mt(logger_name);elseg_logger = spdlog::basic_logger_mt<spdlog::async_factory>(logger_name, logger_file);g_logger->set_pattern("%H:%M:%S [%n][%-71]%v");g_logger->set_level(logger_level);}// 封装宏,自动添加文件名和行号#define DBG(format, ...) bite::g_logger->debug(std::string("[{:>10s}:{:<4d}] ")+format, __FILE__, __LINE__, ##__VA_ARGS__);#define INF(format, ...) bite::g_logger->info(std::string("[{:>10s}:{:<4d}] ")+format, __FILE__, __LINE__, ##__VA_ARGS__);#define WRN(format, ...) bite::g_logger->warn(std::string("[{:>10s}:{:<4d}] ")+format, __FILE__, __LINE__, ##__VA_ARGS__);#define ERR(format, ...) bite::g_logger->error(std::string("[{:>10s}:{:<4d}] ")+format, __FILE__, __LINE__, ##__VA_ARGS__);
}
spdlog 与 glog 对比
glog(Google 日志库)
- 特点:功能丰富,包括条件日志记录、信号处理等
- 性能:同步调用,相对较慢
- 测试数据:处理10万条日志耗时1.027秒(低配服务器)
spdlog
- 特点:高性能,支持异步,零配置
- 性能:同步调用比 glog 快,支持异步模式
- 测试数据:
- 同步:0.135秒(低配服务器)
- 异步:0.158秒
选择建议
- 选择 spdlog:需要高性能、异步日志记录的场景
- 选择 glog:对性能要求不高,但需要特定功能(如条件日志记录)的场景
总结
spdlog 是一个功能强大且易于使用的 C++ 日志库,通过简单的 API 即可实现高性能的日志记录。无论是开发阶段还是生产环境,都能提供稳定高效的日志服务。
代码仓库链接: https://gitee.com/bitedu-tech/cpp-chatsystem
