1. glog基础入门与编译安装
第一次接触glog时,我被它的简洁API惊艳到了。这个由Google开源的C++日志库,用起来就像cout一样自然,却能自动处理多线程、日志分级等复杂问题。先说说怎么把它装到你的项目里。
最省心的方式是使用vcpkg:
vcpkg install glog
如果你习惯源码编译,这里有个小技巧:在CMakeLists.txt里加上这两行能避免常见的链接问题:
find_package(glog REQUIRED)
target_link_libraries(your_target PRIVATE glog::glog)
我最近在Windows上实测时发现,用VS2019编译x64版本特别顺畅。记得勾选"动态链接运行时库"选项,否则容易遇到运行时冲突。编译完成后你会得到:
- include/glog/ 头文件目录
- libglog.lib 静态库
- libglog.dll 动态库
2. 日志级别与基础用法
glog的日志分级设计非常实用,就像给日志消息贴上了紧急程度标签:
LOG(INFO) << "用户登录成功"; // 蓝色提示
LOG(WARNING) << "内存使用超过80%"; // 黄色警告
LOG(ERROR) << "数据库连接失败"; // 红色错误
但要注意FATAL级别的小陷阱:
LOG(FATAL) << "核心组件崩溃"; // 记录日志后会终止程序!
实际项目中我推荐这样初始化:
google::InitGoogleLogging(argv[0]);
FLAGS_logtostderr = 1; // 开发阶段先输出到控制台
3. 高级封装实战:线程安全日志助手
直接使用原生API在多线程环境下不够优雅。下面这个封装类是我在金融项目中验证过的方案,解决了三个痛点:
- 线程安全问题
- 日志文件自动分割
- 跨平台路径处理
核心代码结构:
class ThreadSafeLogger {
public:
static ThreadSafeLogger& GetInstance() {
static ThreadSafeLogger instance;
return instance;
}
void Init(const std::string& log_dir,
bool daily_rotate = true,
int max_size_mb = 1024);
template<typename T>
void Log(LogLevel level, const T& message) {
std::lock_guard<std::mutex> lock(mutex_);
LOG(level) << "[Thread:" << std::this_thread::get_id() << "] "
<< message;
}
private:
std::mutex mutex_;
//...其他私有成员
};
使用示例:
auto& logger = ThreadSafeLogger::GetInstance();
logger.Init("/var/log/myapp");
logger.Log(INFO, "交易处理开始 amount=" + std::to_string(amount));
4. 自定义日志格式与输出控制
glog默认格式是这样的:
I20240715 14:25:03.123456 7890 main.cpp:15] 消息内容
通过修改FLAGS可以调整显示效果:
FLAGS_log_prefix = false; // 去掉前缀
FLAGS_colorlogtostderr = true; // 彩色输出
更高级的定制需要继承LogSink类。比如我们需要JSON格式日志:
class JsonLogSink : public google::LogSink {
public:
void send(google::LogSeverity severity,
const char* full_filename,
const char* base_filename,
int line,
const tm* tm_time,
const char* message,
size_t message_len) override {
json log = {
{"timestamp", FormatTime(tm_time)},
{"level", GetLevelString(severity)},
{"file", base_filename},
{"line", line},
{"message", std::string(message, message_len)}
};
std::cout << log.dump() << std::endl;
}
};
5. 性能优化技巧
在大流量场景下,我总结出这些优化经验:
- 异步日志:使用
google::base::Logger派生类实现后台写入
class AsyncLogger : public google::base::Logger {
void Write(bool force_flush, time_t timestamp,
const char* message, int length) override {
queue_.Push(LogItem{timestamp, std::string(message, length)});
if (force_flush) Flush();
}
//... 实现队列处理逻辑
};
- 避免频繁的磁盘IO:
FLAGS_logbuflevel = google::GLOG_WARNING; // INFO级日志缓冲
FLAGS_logbufsecs = 5; // 最多缓冲5秒
- 日志文件管理:
FLAGS_max_log_size = 100; // 单个文件最大100MB
FLAGS_stop_logging_if_full_disk = true;
6. 跨平台问题解决方案
在Linux和Windows混合环境中,这几个坑我帮你踩过了:
路径分隔符问题:
std::string path =
#ifdef _WIN32
"logs\\app_";
#else
"logs/app_";
#endif
UTF-8编码处理:
#ifdef _WIN32
#include <windows.h>
std::wstring Utf8ToWide(const std::string& utf8) {
// Windows下的宽字符转换
}
#endif
信号安全日志:
void SignalHandler(const char* data, int size) {
RAW_LOG(ERROR, "Crash detected: %.*s", size, data);
}
google::InstallFailureSignalHandler();
7. 实战案例:微服务日志系统
去年我们给电商系统设计的日志方案是这样的:
- 架构设计:
- 每个服务实例本地写日志文件
- 通过Filebeat收集到ELK集群
- 关键错误触发企业微信告警
- 关键配置:
// 服务启动时
logger.Init("/data/logs/order_service",
/* daily_rotate */ true,
/* max_size_mb */ 2048);
// 关键路径添加追踪ID
LOG(INFO) << "[TraceID:" << trace_id << "] 订单创建开始";
- 异常处理:
try {
ProcessPayment();
} catch (const std::exception& e) {
LOG(ERROR) << "支付处理异常: " << e.what()
<< "\n堆栈:\n" << GetStackTrace();
NotifyAlertSystem();
}
这套系统每天处理超过200GB日志,平均延迟小于50ms,通过合理的日志分级和采样策略,既保证了可观测性,又没有影响系统性能。
366



被折叠的 条评论
为什么被折叠?



