记录器如何在不向日志消息添加行尾的情况下进行刷新?

问题描述 投票:0回答:1

我看到许多记录器使用

operator<<
来读取日志消息并将其写入文件:

template<typename T>
Logger& Logger::operator<<(Logger& l, const T& s) {
    l.logStream << s;
    return l;
}

...

Logger log;
log << "Test message " << 123;

我希望在

"Test message"
123
写入流后刷新日志。但是,我希望记录器在到达
;
时刷新流,而不是由用户控制刷新。

我该怎么做?

我想到了两种解决方案,但我发现两者都不可接受:

我可以将新行放在每个日志消息的开头,以便刷新先前的日志,并且在发生崩溃时我们丢失的只是当前日志。

operator<<
可以冲水。但是,由于磁盘上的写入操作数量(磨损),每次调用
<<
时的刷新都会带来很大的性能损失。我希望同花包含整个消息。

c++ logging flush eol endl
1个回答
1
投票

我想要“测试消息”<< 123 to be flushed all together, in a single operation.

您可以通过从

log::operator<<
返回一个代理对象来做到这一点,该对象有自己的
proxy::operator<<
,转发到
log::operator<<
,并在其析构函数中刷新。

类似这样的东西(未经测试):

struct ProxyLogger {
      Logger& l;
      ProxyLogger(Logger& l) : l(l) {}
      template <typename T>
      ProxyLogger& operator<<(const T& s) {
           l << s; 
           return *this;
      }
      ~ProxyLogger() { l << std::flush; }
};

template<typename T>
ProxyLogger Logger::operator<<(Logger& l, const T& s) {
    l.logStream << s;
    return l;
}

用法如前:

Logger log;
log << "Test message " << 123;
//  ^^ creates the proxy     ^^ here it is destroyed

为了进一步阅读,我建议您参考有关 RAII 的文章(资源获取就是初始化)。

© www.soinside.com 2019 - 2024. All rights reserved.