跳到主要内容gflags 与 spdlog 实战:C++ 命令行参数与高性能日志搭配 | 极客日志C++
gflags 与 spdlog 实战:C++ 命令行参数与高性能日志搭配
综述由AI生成介绍 gflags 命令行参数解析库与 spdlog 高性能日志库在 C++ 项目中的集成应用。涵盖 gflags 的参数定义、解析方式(命令行、配置文件)及 spdlog 的同步/异步模式配置。通过二次封装示例展示了如何结合两者实现灵活的运行模式切换与日志管理,并提供了 grep 文本查询技巧辅助开发。
DevOpsTeam28 浏览 一、gflags 介绍及简单使用
简单介绍
Google 开源的命令行参数解析库,用于高效管理程序启动参数(如 --flag=value)。
核心功能:
- 定义参数:通过宏(如
DEFINE_int32、DEFINE_string)声明参数名、默认值和帮助信息。
- 解析参数:调用
ParseCommandLineFlags 解析 argc/argv,将命令行参数映射到全局变量(如 FLAGS_<name>)。
- 快速访问:通过全局变量
FLAGS_<flag_name> 直接获取解析后的值。
特点:
- 轻量高效:专为命令行参数设计,解析速度快,适合 C++ 项目。
- 类型安全:支持多种数据类型(整型、字符串等),编译期检查。
- 自动生成帮助:通过
--help 自动输出参数说明(依赖定义时的描述信息)。
对比其他工具:
类似功能库:Boost.Program_options(C++)、Python 的 argparse;
gflags 优势:与 Google 生态兼容,API 简洁,适合高性能场景。
安装过程
用源码装 gflags 库步骤:
- 下载源码:
git clone https://github.com/gflags/gflags.git
- 进入目录:
cd gflags/
- 新建并进入 build 文件夹:
mkdir build; cd build/
- 生成 Makefile:
cmake ..
- 编译:
make
- 安装:
make install
- 可以看到对应安装在 include 目录里,以及动态库在
/usr/lib/x86_64-linux-gnu 目录下。
gflags 简单使用
gflags 支持的常见宏类型:
DEFINE_bool DEFINE_int32 DEFINE_int64 DEFINE_uint64 DEFINE_double DEFINE_string
简单使用格式:
#include <gflags/gflags.h>
#include <iostream>
DEFINE_string(ip, "127.0.0.1", "服务端 ip");
DEFINE_int32(port, 8080, );
(debug_enable, , );
{
google::(&argc, &argv, );
std::cout << FLAGS_ip << std::endl;
std::cout << FLAGS_port << std::endl;
std::cout << FLAGS_debug_enable << std::endl;
;
}
"服务端监听端口"
DEFINE_bool
true
"是否启用调试模式,格式:true/false"
int main(int argc, char* argv[])
ParseCommandLineFlags
true
return
0
google::ParseCommandLineFlags 介绍:
google::ParseCommandLineFlags 是 Google 工具库里的函数,用来处理程序启动时输入的命令行参数。
它接收 main 函数里的 argc(参数个数)和 argv(参数数组),还有个 remove_flags 参数控制后续行为:
- 若
remove_flags 为 true,解析后会从 argv 里删除已识别的'标志和参数',同时 argc 也会变小;
- 若为
false,argc 不变,但会把所有'标志'移到 argv 最前面重新排好。
一句话:帮你自动解析命令行里的各种选项/开关,让程序能读懂用户输的参数。
- 输入在对应 gflags 定义在宏里参数(通过命令行或者配置文件指定或者默认输进去的),此时 gflags 会内部把它解析出来,对用户提供对应的 GFLAGS_变量名访问接口,方便用户获取。
- 也就是这样做可以不用每次都手动修改代码对应参数变量等,而是通过程序参数方式进行输入,避免了重复编译带来的消耗。
使用方式
1·直接使用默认的参数
这里就直接拿宏函数中默认的值进行输入到 main 的参数中解析(这里会把 -- 将会终止标识的处理)。
2·使用命令行参数
3·使用配置文件输入
使用参考
- –help:显示文件中所有标识的帮助信息。
- –helpfull:与–help 功能类似,但帮助信息更全面。
- –helpshort:仅显示当前执行文件里的标志。
- –helpxml:以 xml 格式打印,便于处理。
- –version:打印版本信息,由 google::SetVersionString() 设定。
- –flagfile:从指定的文件 f 中读取命令行参数。
比如这里可以使用对应 - -help 选项查看对应的 gflags 设置的对应输入参数如何使用。
二、Spdlog 组件介绍及简单使用
简单介绍
spdlog 是一个高性能、超快速、零配置的 C++ 日志库,旨在提供简洁 API 和丰富功能,同时保持高性能的日志记录,支持多种输出目标、格式化选项、线程安全及异步日志记录。(也就是类似之前实现的日志系统项目,同时对比 glog 是功能更加多的,比如前者支持异步模式但后者不支持等等)
- 特点 - 高性能:spdlog 专为速度设计,高负载时也能保持良好性能。
- 特点 - 零配置:无需复杂配置,包含头文件就可在项目中使用。
- 特点 - 异步日志:支持异步日志记录,减少对主线程影响。
- 特点 - 格式化:支持自定义日志消息格式化,如时间戳、线程 ID、日志级别等。
- 特点 - 多平台:跨平台兼容,支持 Windows、Linux、macOS 等操作系统。
- 特点 - 丰富的 API:提供丰富日志级别和操作符重载,方便记录各类日志。
安装过程
对应命令进行安装即可(保证 apt 或者 yum 源是最新的):
sudo apt-get install libspdlog-dev
- 以及动态库在
/usr/lib/x86_64-linux-gnu 目录下。
spdlog 简单使用
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <iostream>
#include <chrono>
int main() {
using namespace std::literals;
spdlog::flush_every(1s);
spdlog::flush_on(spdlog::level::trace);
spdlog::set_level(spdlog::level::debug);
auto logger1 = spdlog::stdout_color_mt("test_log1");
auto logger2 = spdlog::basic_logger_mt("test_log2", "sync.log", true);
logger1->set_pattern("[%n][%H:%M:%S][%t][%-8l] %v");
logger2->set_pattern("[%n][%H:%M:%S][%t][%-8l] %v");
logger1->trace("halo {}", 1111);
logger1->debug("halo {}", 1111);
logger1->info("halo {}", 1111);
logger1->warn("halo {}", 1111);
logger1->error("halo {}", 1111);
logger1->critical("halo {}", 1111);
logger2->trace("halo {}", 1111);
logger2->debug("halo {}", 1111);
logger2->info("halo {}", 1111);
logger2->warn("halo {}", 1111);
logger2->error("halo {}", 1111);
logger2->critical("halo {}", 1111);
std::cout << "完成日志输出" << std::endl;
return 0;
}
- 上面包含了对应同步日志器的控制条输出与文件输出日志器,还有对应的初始化设置。
对应的异步模式仅仅是修改对应的创建日志器的模版函数的模版即可(默认模版是同步日志器):
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/async.h>
#include <iostream>
#include <chrono>
int main() {
using namespace std::literals;
spdlog::flush_every(1s);
spdlog::flush_on(spdlog::level::trace);
spdlog::set_level(spdlog::level::debug);
auto logger1 = spdlog::stdout_color_mt<spdlog::async_factory>("test_log1");
auto logger2 = spdlog::basic_logger_mt<spdlog::async_factory>("test_log2", "async.log", true);
logger1->set_pattern("[%n][%H:%M:%S][%t][%-8l] %v");
logger2->set_pattern("[%n][%H:%M:%S][%t][%-8l] %v");
logger1->trace("halo {}", 1111);
logger1->debug("halo {}", 1111);
logger1->info("halo {}", 1111);
logger1->warn("halo {}", 1111);
logger1->error("halo {}", 1111);
logger1->critical("halo {}", 1111);
logger2->trace("halo {}", 1111);
logger2->debug("halo {}", 1111);
logger2->info("halo {}", 1111);
logger2->warn("halo {}", 1111);
logger2->error("halo {}", 1111);
logger2->critical("halo {}", 1111);
std::cout << "完成日志输出" << std::endl;
return 0;
}
- 这里使用的时候除了手动链接对应的 spdlog 库还需要链接对应的格式库即 fmt。
基于 spdlog 使用的二次封装(默认同步日志器)
- 避免单例锁冲突,创建全局线程安全日志器。
- 日志输出无文件名行号,用宏二次封装输出相关信息。
- 封装初始化接口,调试模式输出到标准输出,否则输出到文件。
封装全局接口供用户创建与初始化日志器,用户只需要对对应函数根据输入参数的不同模式完成调用即可,包含初始化接口接收运行模式、输出文件名、输出日志等级等参数,用宏封装日志输出接口,加入文件名行号输出。
#pragma once
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/async.h>
#include <iostream>
#include <chrono>
#include <string>
std::shared_ptr<spdlog::logger> logger;
void init_logger(bool mode, const std::string &filename, int32_t level) {
if (mode == 1) {
logger = spdlog::basic_logger_mt("default_logger", filename.c_str());
logger->flush_on((spdlog::level::level_enum)level);
logger->set_level((spdlog::level::level_enum)level);
} else {
logger = spdlog::stdout_color_mt("default_logger");
logger->flush_on(spdlog::level::trace);
logger->set_level(spdlog::level::trace);
}
logger->set_pattern("[%n][%H:%M:%S][%t][%-8l] %v");
}
#define LOG_TRACE(fmt,...) logger->trace(std::string("[{}:{}]") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_DEBUG(fmt,...) logger->debug(std::string("[{}:{}]") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(fmt ,...) logger->info(std::string("[{}:{}]") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_WARN(fmt ,...) logger->warn(std::string("[{}:{}]") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_ERROR(fmt,...) logger->error(std::string("[{}:{}]") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_FATAL(fmt,...) logger->critical(std::string("[{}:{}]") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
此时可以配合对应的 gflags 一起使用,让用户能灵活在运行程序时候通过参数进行选择:
#include "log.hpp"
#include <gflags/gflags.h>
DEFINE_bool(run_mode, false, "程序的运行模式,false-调试;true-发布;");
DEFINE_string(log_file, "", "发布模式下,用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下,用于指定日志输出等级");
int main(int argc, char* argv[]) {
google::ParseCommandLineFlags(&argc, &argv, 1);
init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);
LOG_DEBUG("你好:{}", "1");
LOG_INFO("你好:{}", "2");
LOG_WARN("你好:{}", "3");
LOG_ERROR("你好:{}", "4");
LOG_FATAL("你好:{}", "5");
LOG_DEBUG("这是一个测试");
}
基于 spdlog 总结
- 功能强大:提供丰富日志功能,满足多样需求。
- 使用简单:API 简单,开发者易上手,快速实现日志记录。
- 性能高效:具备高性能日志记录能力。
- 代码友好:保持代码清晰,利于维护。
- 环境适用:开发和生产环境都能稳定高效服务。
总结文本查询小技巧
- grep:是一个强大的文本搜索工具,用于在文件中查找匹配指定模式的行。
- -R:是 grep 命令的一个选项,代表'递归(recursive)'。使用该选项时,grep 会递归地搜索指定目录及其所有子目录中的文件内容。
- 要查的文本内容:是你要搜索的模式,意味着 grep 会在文件/目录中查找包含 这个文本内容的行。
- 路径/文件:要查找的路径或者文件范围。
- 这里会按照指定的当前目录进行查询,然后递归式的把
当前目录的文件指定包含'sync'这个文本的行打印出来(包括文件名 + 对应行,然后把对应文本标记出来)。
三、gtest 介绍使用
gtest 作为单元测试框架,其详细用法可参考官方文档或相关技术社区资源。
四、本篇小结
本文带你了解了 gflags(解析命令行参数,支持多类型、自动生成帮助)与 spdlog(高性能日志,支持同步/异步、多输出目标),通过安装、基础用法及封装示例,展示两者在 C++ 项目中的价值。
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online