日志系统是软件开发的"黑匣子",在调试跟踪、问题定位、运行监控等方面发挥关键作用。一个优秀的日志模块应具备:
精准的问题定位能力
灵活的输出控制
最小的性能损耗
可靠的运行稳定性
灵活性
支持多日志等级(DEBUG/INFO/WARNING等)
多种输出目标(控制台/文件/网络)
动态配置能力
性能优化
异步日志机制
缓冲技术应用
零拷贝设计
线程安全
原子操作
互斥锁策略
无锁队列
可扩展性
插件式架构
自定义格式化
过滤器机制
enum class LogLevel {
DEBUG,
INFO,
WARNING,
ERROR,
FATAL
};
class LogLevelControl {
public:
static void SetGlobalLevel(LogLevel level);
static bool ShouldLog(LogLevel msgLevel);
private:
static std::atomic globalLevel_;
};
class LogSink {
public:
virtual ~LogSink() = default;
virtual void Write(const std::string& message) = 0;
virtual void Flush() = 0;
};
class FileSink : public LogSink {
public:
explicit FileSink(const std::string& filename);
// 实现Write和Flush
};
class ConsoleSink : public LogSink {
// 实现标准输出
};
class Formatter {
public:
virtual std::string Format(LogLevel level,
const std::string& message,
const std::source_location& loc) = 0;
};
class PatternFormatter : public Formatter {
public:
void SetPattern(const std::string& pattern);
// 实现格式解析和构造
};
class AsyncLogger {
public:
AsyncLogger(std::unique_ptr sink, size_t bufferSize = 4*1024*1024)
: sink_(std::move(sink)),
currentBuffer_(new Buffer(bufferSize)),
backgroundThread_(&AsyncLogger::ThreadFunc, this) {}
~AsyncLogger() {
stop_.store(true);
cond_.notify_all();
backgroundThread_.join();
}
void Append(const std::string& msg) {
std::lock_guard lock(mutex_);
if (currentBuffer_->Available() > msg.size()) {
currentBuffer_->Append(msg);
} else {
buffersToWrite_.push_back(std::move(currentBuffer_));
currentBuffer_.reset(new Buffer(bufferSize_));
currentBuffer_->Append(msg);
cond_.notify_one();
}
}
private:
void ThreadFunc() {
BufferPtr newBuffer1(new Buffer(bufferSize_));
BufferPtr newBuffer2(new Buffer(bufferSize_));
BufferVector buffersToWrite;
while (!stop_.load()) {
{
std::unique_lock lock(mutex_);
cond_.wait_for(lock, std::chrono::seconds(3));
buffersToWrite.swap(buffersToWrite_);
buffersToWrite.push_back(std::move(currentBuffer_));
currentBuffer_ = std::move(newBuffer1);
}
for (const auto& buffer : buffersToWrite) {
sink_->Write(buffer->Data());
}
if (!newBuffer1) {
newBuffer1 = std::move(buffersToWrite[0]);
newBuffer1->Reset();
}
if (!newBuffer2) {
newBuffer2 = std::move(buffersToWrite[1]);
newBuffer2->Reset();
}
buffersToWrite.clear();
sink_->Flush();
}
}
};
双缓冲技术
前台缓冲用于接收日志
后台缓冲用于写入
减少锁竞争
批量写入
合并小量日志为批量操作
减少I/O系统调用次数
内存管理
预分配内存池
避免频繁内存分配
时间戳缓存
缓存时间到毫秒级
每秒更新一次
class RollingFileSink : public LogSink {
public:
explicit RollingFileSink(const std::string& baseName,
size_t maxSize = 100*1024*1024,
int maxFiles = 10);
// 实现大小检查和文件滚动
};
class LogConfig {
public:
static void FromJson(const std::string& configFile);
static void WatchConfigChanges();
};
class LogFilter {
public:
void AddDomainFilter(const std::string& domain);
void AddTagFilter(const std::string& tag);
bool ShouldFilter(const LogContext& context);
};
// 简单同步日志示例
#include
#include
#include
#include
#include
#include
enum class LogLevel { DEBUG, INFO, WARNING, ERROR, FATAL };
class Logger {
public:
static Logger& Instance() {
static Logger instance;
return instance;
}
void Init(LogLevel level = LogLevel::INFO,
const std::string& filename = "") {
level_.store(level);
if (!filename.empty()) {
sinks_.emplace_back(std::make_unique(filename));
}
sinks_.emplace_back(std::make_unique());
}
template
void Log(LogLevel level, const std::string& format, Args&&... args) {
if (level < level_.load()) return;
std::string message = FormatMessage(level, format,
std::forward(args)...);
std::lock_guard lock(mutex_);
for (auto& sink : sinks_) {
sink->Write(message);
}
}
private:
// 实现格式化函数和Sink类
};
// 使用示例
int main() {
Logger::Instance().Init(LogLevel::DEBUG, "app.log");
Logger::Instance().Log(LogLevel::INFO, "System started, version: %s", "1.0.0");
return 0;
}
单元测试要点:
日志等级过滤
多线程压力测试
文件完整性检查
异常情况处理
性能测试指标:
每秒日志吞吐量
内存占用峰值
延迟分布
网络日志传输(TCP/UDP)
结构化日志(JSON格式)
日志采样机制
跨平台支持
堆栈跟踪集成
一个优秀的日志模块需要平衡功能、性能和易用性。建议根据实际需求进行裁剪,核心注意:
生产环境使用异步日志
合理控制日志粒度
定期进行日志审计
注意敏感信息过滤