多线程环境下的登录和测试

3

请告诉我您对以下情况中如何设计和测试日志记录的建议。

我有一个API,可以被多个线程调用。单个线程调用此API会生成50 KB的日志。

在多线程环境下,是否存在适用于日志记录的设计模式,即所有线程的一个日志文件 vs 每个线程的一个专用日志文件

而且,如何测试这个功能(是否应该测试?)

谢谢。


4
回复:“是否应该测试” 哈哈,太有趣了。 - John Dibling
您的情况的性能特征是什么?单个共享日志记录器可能会成为CPU密集型应用程序的瓶颈,而在其他情况下可能并不是问题。 - Chris Ballard
@John::) 我问这个问题是因为我不知道如何做到这一点?应该设置什么标准?输入参数?期望输出? - Azodious
@Chris:性能非常关键。但现在唯一担心的是日志的准确性和排序。 - Azodious
如果性能真的很重要,不要使用单例模式。同样地,如果良好的设计很重要,也不要使用单例模式。 - John Dibling
8个回答

1

如果您正在谈论事务活动的日志记录,其中50 KB日志中的所有数据都与线程执行的特定事务相关,则可能需要为每个线程创建一个日志,否则解开输出可能会成为一个重大问题。对于这种特殊情况,另一种解决方案实际上可能是每个事务一个单独的日志文件,而“全局”日志仅在一行上提到启动了一个事务,如果适用,还可以添加最终结果的另一个条目。第三种解决方案是确保以某种方式标记日志条目,以便确定每行与哪个事务相关,并具有后处理工具,可以过滤日志以查看特定事务。

第二种解决方案(每个事务一个文件)可能会成为问题,如果您有非常频繁的事务,因为某些文件系统操作(特别是在网络上检查文件夹)会随着目录中文件数量的增加而变慢。第三种解决方案可以很好地工作(因为您可以向过滤/查看工具添加其他功能),但这意味着需要开发和维护另一个工具。


通过为每个日志行添加线程特定的标记,可以实现解开输出。OP应该考虑将日志分散到单独的文件中,这将使得在不同线程中确定事件的相对顺序几乎不可能。例如,在协议编程领域,绝对必要的是能够从日志中可靠地挖掘出不同线程之间组件之间的控制流。 - otto

0

我不确定这是否是最佳方法,但我在我的代码中使用类似的东西

void Log( const char* msg ) {
#ifdef ENABLE_LOGGING
    boost::mutex::scoped_lock lock(m_mutex); 

    // do a fprintf or what you want
#endif
}

当您从多个线程调用时,互斥锁确保此函数仅执行一次。


0
对于高性能日志记录,请查看Microsoft Message Queue(MSMQ)。
每个线程可以写入同一个消息队列,而单独的服务/进程可以从队列中读取并将数据存储在日志存储格式中。这样可以避免线程之间的竞争,并最大化性能。

0

你很可能应该将日志记录器实例包装成Singleton,使用双重锁定创建日志记录器对象的实例以保护它免受初始化时的竞态条件。


你是指双重检查锁定吗? - BrandonZeider
在尝试双重检查锁定时要非常小心。基于语言实现细节的天真实现可能无法正常工作。为什么请看 - unholysampler

0

这取决于您的应用程序需求。如果您想轻松查看所有线程中发生事情的顺序,则需要使用单个日志文件,并在线程之间同步访问它。如果每个线程或多或少独立运行,并且您只关心单个线程中发生的事情,则请为每个线程使用单独的日志文件。


根据需要,开发人员可以选择使用单个文件或多个文件。哪种更好?如果我在每个日志中添加时间戳,我发现两者之间没有太大区别。 - Azodious
是的,您可以在不同的日志文件之间交叉引用时间戳,但是假设您的日志条目在日志文件内按时间顺序排列,那么查看事件发生的顺序会更容易。 - Joel C

0

0

我曾经创建过线程本地的记录器。可以配置多个日志池,只有当多个线程写入相同的文件池时才会出现锁定。

通过将记录器创建为线程本地,实现堆栈跟踪(在C/C++代码库中)相对容易。


0

你可以使用内存队列(在.NET 4中,System.Collections.Concurrent是线程安全的)。 然后让一个工作线程读取队列并将其记录到文件/数据库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接