[C++项目框架]Spdlog的简单介绍
一. Spdlog的介绍和使用
1.Spdlog的介绍
spdlog 是一个高性能、超快速、零配置的 C++ 日志库,它旨在提供简洁的 API 和丰富的功能,同时保持高性能的日志记录。它支持多种输出目标、格式化选项、线程安全以及异步日志记录。以下是对 spdlog 的详细介绍和使用方法。
特点
- 高性能:spdlog 专为速度而设计,即使在高负载情况下也能保持良好的性能。
- 零配置:无需复杂的配置,只需包含头文件即可在项目中使用。
- 异步日志:支持异步日志记录,减少对主线程的影响。
- 格式化:支持自定义日志消息的格式化,包括时间戳、线程 ID、日志级别等。
- 多平台:跨平台兼容,支持 Windows、Linux、macOS 等操作系统。
- 丰富的 API:提供丰富的日志级别和操作符重载,方便记录各种类型的日志。
2.Spdlog的使用
1.包含头文件
#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] [%-7l] %v");
%t - 线程 ID(Thread ID)。
%n - 日志器名称(Logger name)。
%l - 日志级别名称(Level name),如 INFO、DEBUG、ERROR 等。
%v - 日志内容(message)。
%Y - 年(Year)。
%m - 月(Month)。
%d - 日(Day)。
%H - 小时(24-hour format)。
%M - 分钟(Minute)。
%S - 秒(Second)。
全局接口
//输出等级设置接口
void set_level(level::level_enum log_level);
//日志刷新策略-每隔N秒刷新一次
void flush_every(std::chrono::seconds interval)
//日志刷新策略-触发指定等级立即刷新
void flush_on(level::level_enum log_level);
记录日志
使用日志记录器记录不同级别的日志:
logger->trace("This is a trace message");
logger->debug("This is a debug message");
logger->info("This is an info message");
logger->warn("This is a warning message");
logger->error("This is an error message");
logger->critical("This is a critical message");
3.使用样例
sync.cc
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/async.h>
#include <iostream>
using namespace std;
int main()
{
// 1.设置全局的刷新策略
spdlog::flush_every(std::chrono::seconds(1)); // 日志刷新策略-每隔1秒刷新一次
spdlog::flush_on(spdlog::level::level_enum::debug); // 日志刷新策略-触发debug等级立即刷新
// 2.设置全局的日志输出等级
spdlog::set_level(spdlog::level::level_enum::debug);
// 3.创建同步日志器(标准输出/文件)--默认创建的就是同步日志器
// auto logger=spdlog::stdout_color_mt("default-logger");
auto logger=spdlog::basic_logger_mt("file-logger","sync.log");
// 4.设置日志器的刷新策略,以及输出等级(上面已经设置过了)
// spdlog::flush_on(spdlog::level::level_enum::debug);
// spdlog::set_level(spdlog::level::level_enum::debug);
// 4.1设置日志输出格式
//logger->set_pattern("[%H:%M:%S][%t][%-10l - %v]");
logger->set_pattern("[%Y-%m-%d][%H:%M:%S][%t][%-8l - %v]");
// 5.进行简单的日志输出
logger->trace("hello {}","小康");
logger->debug("hello {}","小康");
logger->info("hello {}","小康");
logger->warn("hello {}","小康");
logger->error("hello {}","小康");
logger->critical("hello {}","小康");
cout<<"日志输出演示完毕"<<endl;
return 0;
}
async.cc
#include <iostream>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/async.h>
int main()
{
// 设置全局的刷新策略
// 每秒刷新
spdlog::flush_every(std::chrono::seconds(1));
spdlog::flush_on(spdlog::level::level_enum::debug);
spdlog::set_level(spdlog::level::level_enum::debug);
// 初始化异步日志输出线程配置
// void init_thread_pool(size_t q_size, size_t thread_count)
spdlog::init_thread_pool(3072, 1);
// 创建异步日志器(标准输出 / 文件) -- 工厂接口默认创建的就是同步日志器 工厂不同所以创建出来的日志器也不同
auto logger = spdlog::stdout_color_mt<spdlog::async_factory>("async-logger");
// 设置日志输出格式
logger->set_pattern("[%n][%H:%M:%S][%t][%-8l] %v");
// 进行简单的日志输出
logger->trace("你好! {}", "小明");
logger->debug("你好! {}", "小明");
logger->info("你好! {}", "小明");
logger->warn("你好! {}", "小明");
logger->error("你好! {}", "小明");
logger->critical("你好! {}", "小明");
std::cout << "日志输出演示完毕!" << std::endl;
return 0;
}
二次封装
因为spdlog的日志输出对文件名和行号并不是很友好,以及因为spdlog本身实现了线程安全,如果使用默认日志器每次进行单例获取,效率会有降低,因此进行二次封装,简化使用。
封装的接口为:
- 日志初始化封装接口
- 日志的输出接口封装宏
#pragma once
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/async.h>
#include <iostream>
using namespace std;
namespace yjt_im
{
std::shared_ptr<spdlog::logger> g_default_logger;
// mode -运行模式 true-表示发布模式 false-表示调试模式
void init_logger(bool mode, const string &file, int level)
{
if (mode == false) // 如果是调试模式,则创建标准输出日志器,输出等级为最低
{
g_default_logger = spdlog::stdout_color_mt("default-logger");
g_default_logger->set_level(spdlog::level::level_enum::trace);
g_default_logger->flush_on(spdlog::level::level_enum::trace);
}
else // 否则是发布模式,创建文件输出日志器,输出等级根据参数而定
{
g_default_logger = spdlog::basic_logger_mt("default-logger", file);
g_default_logger->set_level((spdlog::level::level_enum)level);
g_default_logger->flush_on((spdlog::level::level_enum)level);
}
g_default_logger->set_pattern("[%n][%H:%M:%S][%t][%-8l]%v");
}
#define LOG_TRACE(format, ...) yjt_im::g_default_logger->trace(std::string("[{}:{}] ") + format, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_DEBUG(format, ...) yjt_im::g_default_logger->debug(std::string("[{}:{}] ") + format, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(format, ...) yjt_im::g_default_logger->info(std::string("[{}:{}] ") + format, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_WARN(format, ...) yjt_im::g_default_logger->warn(std::string("[{}:{}] ") + format, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) yjt_im::g_default_logger->error(std::string("[{}:{}] ") + format, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_FATAL(format, ...) yjt_im::g_default_logger->critical(std::string("[{}:{}] ") + format, __FILE__, __LINE__, ##__VA_ARGS__)
}
main.cc
#include "logger.hpp"
#include <gflags/gflags.h>
DEFINE_bool(run_mode, false, "程序的运行模式, false-调试, true-运行");
DEFINE_string(log_file, "", "发布模式下用于指定日志的输出文件");
DEFINE_int32(log_levle, 0, "发布模式下用于指定日志的输出等级");
int main(int argc, char *argv[])
{
google::ParseCommandLineFlags(&argc, &argv, true);
init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_levle);
LOG_DEBUG("你好: {}", "康");
LOG_INFO("你好: {}", "康");
LOG_WARN("你好: {}", "康");
LOG_ERROR("你好: {}", "康");
LOG_FATAL("你好: {}", "康");
return -1;
}
二. Spdlog和glog的对比
glog 和 spdlog 都是流行的 C++ 日志库,它们各自具有不同的特点和优势。
glog
glog 是由 Google 开发的一个开源 C++ 日志库,它提供了丰富的日志功能,包括多种日志级别、条件日志记录、日志文件管理、信号处理、自定义日志格式等。glog 默认情况下是同步记录日志的,这意味着每次写日志操作都会阻塞直到日志数据被写入磁盘。
对比总结
- 性能:从性能测试结果来看,spdlog 在同步调用场景下的性能优于 glog。当涉及到大量日志数据时,spdlog 显示出更快的处理速度。
- 异步日志:spdlog 支持异步日志记录,这在处理高负载应用程序时非常有用,可以减少日志操作对主线程的影响。
- 易用性:spdlog 提供了更简单的集成和配置方式,只需包含头文件即可使用,而 glog 可能需要额外的编译和配置步骤。
- 功能:glog 提供了一些特定的功能,如条件日志记录和信号处理,这些在某些场景下可能非常有用。
- 使用场景:glog 可能更适合那些对日志性能要求不是特别高,但需要一些特定功能的场景。而 spdlog 则适合需要高性能日志记录和异步日志能力的应用程序。
在选择日志库时,开发者应根据项目的具体需求和性能要求来决定使用哪个库。如果项目对日志性能有较高要求,或者需要异步日志记录来避免阻塞主线程,spdlog 可能是更好的选择。如果项目需要一些特定的日志功能,或者已经在使用 glog 且没有显著的性能问题,那么继续使用 glog 也是合理的。
spdlog 是一个功能强大且易于使用的 C++ 日志库,它提供了丰富的功能和高性能的日志记录能力。通过简单的
API,开发者可以快速地在项目中实现日志记录,同时保持代码的清晰和可维护性。无论是在开发阶段还是生产环境中,spdlog
都能提供稳定和高效的日志服务。
更多推荐
所有评论(0)