C++ 中的异步线程安全日志记录

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

我正在寻找一种在我的 C++ 项目中进行异步和线程安全日志记录的方法(如果可能的话)到一个文件。我目前正在使用

cerr
clog
来执行任务,但由于它们是同步的,因此每次记录某些内容时执行都会短暂暂停。这是一个图形相对较多的应用程序,所以这种事情是相当烦人的。

新的记录器应该使用异步 I/O 来消除这些暂停。线程安全也是可取的,因为我打算很快添加一些基本的多线程。

我考虑过每线程一个文件的方法,但这似乎会让管理日志成为一场噩梦。有什么建议吗?

c++ logging asynchronous thread-safety
6个回答
20
投票

我注意到这个 1 年前的帖子。也许我写的异步记录器可能会让人感兴趣。

http://www.codeproject.com/KB/library/g2log.aspx

G2log 使用受保护的消息队列将日志条目转发到慢速磁盘访问的后台工作人员。

我已经尝试过使用无锁队列,这增加了 LOG 调用的平均时间,但减少了最坏情况下的时间,但是我现在使用受保护的队列,因为它是跨平台的。它在 Windows/Visual Studio 2010 和 Ubuntu 11.10/gcc4.6 上进行了测试。

它作为公共领域发布,因此您可以用它做任何您想做的事情,没有任何附加条件。


4
投票

这是非常可能和实用的。我怎么知道?我在上一份工作中正是这样写的。不幸的是(对我们来说),他们现在拥有代码。 :-) 可悲的是,他们甚至不使用它。

我打算在不久的将来编写一个开源版本。同时,我可以给你一些提示。

  1. I/O 操纵器实际上只是函数名称。您可以为自己的日志记录类实现它们,以便您的记录器与 cout/cin 兼容。
  2. 您的操纵器函数可以对操作进行标记并将其存储到队列中。
  3. 线程可能会被阻塞在该队列上,等待日志块飞过。然后它处理字符串操作并生成实际日志。

这本质上是线程兼容的,因为您正在使用队列。但是,您仍然希望在写入队列时设置一些类似互斥锁的保护,以便给定的日志<< "stuff" << "more stuff"; type operation remains line-atomic.

玩得开心!


1
投票

我认为正确的方法不是每个线程一个文件,而是每个文件一个线程。如果系统中的任何一个文件(或一般资源)仅由一个线程访问,那么线程安全编程就会变得更加容易。

那么为什么不让 Logger 成为一个专用线程(或者多个线程,每个文件一个,如果您在不同文件中记录不同的内容),并且在所有其他线程中,写入日志会将消息放在适当的输入队列中记录器线程,在写完上一条消息后会访问它。它所需要的只是一个互斥锁,用于在 Logger 读取事件时保护队列不添加事件,以及一个 condvar,供 Logger 在队列为空时等待。


1
投票

您是否考虑过使用日志库。

有几个可用的,我最近发现了Pantheios,它看起来真的很不可思议。

它更多的是一个前端记录器,您可以自定义使用哪个系统。例如,它可以与

ACE
log4cxx
交互,而且看起来非常易于使用和配置。主要优点是它使用类型安全运算符,这总是很棒的。

如果您只想要一个准系统日志库:

  • 王牌
  • log4c*
  • Boost.Log

任选一个:)

我应该注意到,可以在 C++ 中实现无锁队列,并且它们非常适合日志记录。


0
投票

我遇到了同样的问题,我相信我已经找到了完美的解决方案。我向您展示一个名为 loguru 的单头库:https://github.com/emilk/loguru

它使用简单,可移植,可配置,基于宏,并且默认情况下不

#include
任何东西(对于那个甜蜜的编译时间)。


0
投票

有一个 MIT 许可的基于 C++14 的库可以执行此操作:

https://github.com/odygrd/quill

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