Java 与库一起使用的不同记录器
我的问题与库类(库中使用的类)的日志记录有关, 我们目前使用的是Java 与库一起使用的不同记录器,java,c++,logging,log4j,log4cxx,Java,C++,Logging,Log4j,Log4cxx,我的问题与库类(库中使用的类)的日志记录有关, 我们目前使用的是log4cxx,但是log4j库实现了相同的概念 假设我有一个进程,它有几个实体,a、B和C。每个实体使用许多不同的类和函数,在代码中明确分开 A、 B和C使用许多库类、函数、对象、资源,有时甚至全局(遗留代码,对此我无能为力…)-让我们把它们都称为foo 日志记录A、B和C被证明是一个性能问题,当我们将日志级别设置为debug时,日志会被破坏。在查看我们的系统后,我们得出以下结论: 我们希望一次只能更改其中一个类的调试级别(或者使
log4cxx
,但是log4j
库实现了相同的概念
假设我有一个进程,它有几个实体,a、B和C。每个实体使用许多不同的类和函数,在代码中明确分开
A、 B和C使用许多库类、函数、对象、资源,有时甚至全局(遗留代码,对此我无能为力…)-让我们把它们都称为foo
日志记录A、B和C被证明是一个性能问题,当我们将日志级别设置为debug时,日志会被破坏。在查看我们的系统后,我们得出以下结论:
foo
打印到日志时,我们需要查看哪个实体将其命名为A、B或Cfoo
我们希望能够分别更改每个foo
foo
应被视为一个公共库,它不能直接依赖于A、B或Cfoo
实例(例如,我们的资源处理类的同一个实例用于A、B和C),在日志中,我们希望看到哪个类使用了foo
foo
想要向日志报告时,它通过全局变量进行报告,并将其名称(和上下文)添加到日志消息中
问题是,它感觉一定有什么东西已经做到了,解决方案感觉不干净,持有这样一个全局变量
我们做错什么了吗?
有更好的解决办法吗 如果单独的库本身是类,则可以使用库中的类级别变量来保存记录器实例引用。我不经常用C++或java编程,但是我认为C++和java中的类级变量是“static”。
它下面仍然是一个全局变量,但至少它是类范围的全局变量(比如名为
debugLog.log
的类变量,其中debugLog
是类名)。我不知道现有的解决方案。我可能会设计一个具有如下接口的记录器(无论是独立实现还是现有实现的包装器):
与常见日志库的主要区别是上下文敏感模块过滤器。我们可能有如下设置,以根据拨打电话的人(上下文)设置不同的级别:
然后,调用流将如下所示:
// In entity A
Logger::Instance()->SetThreadLocalContext("A");
// Call function foo
Logger::Instance()->Log(log_level, "foo", log_msg);
不确定这样的接口是否符合您的目的。不管怎样,我总是认为界面优先是一个好方法。一旦你有了一个清晰的接口,实现它应该是一件容易的事情。这听起来不是线程安全的我们不需要它线程安全的,通过使全局变量对每个线程都是唯一的,使它线程安全是相当容易的。我相信分离可以通过logback中的标记来完成,而不需要你描述的hack。slf4j项目有必要的粘合剂。为什么要全局启用调试?除非你想看到你的行为(例如在开发过程中),如果不使用C++,就将Apache库设置为<代码>信息>代码>如果不是代码>警告>代码>或代码>错误 >,语言是一个问题,我们实际上使用C++,但是因为Log4Cxx和Log4J等非常相似,并且实现了相同的概念,我想直接问更常用的语言。。。至于获取日志记录者,到目前为止,我们的库不向日志报告,或者使用cout(比如说System.out.print)报告。我们的大多数类通过指定的单例获取记录器由于多线程,明智的做法是(读:强制)将
SetThreadLocalContext
组合并登录到一个函数中。当操作系统暂停线程“A”时,另一个记录器可以调用SetThreadLocalContext(…)
…@M.Mimpen,因为这是线程本地上下文,切换到另一个线程不会影响前一个线程的上下文。在实现中,需要在C/C++中使用thread\u local
、\u thread
或\u declspec(thread)
,在Java中使用ThreadLocal
。
// foo calls by entity A have the DEBUG log level
Logger::Instance()->AddModuleFilter("A", "foo", Logger::DEBUG);
// foo calls by entity B have the WARNING log level
Logger::Instance()->AddModuleFilter("B", "foo", Logger::WARNING);
// In entity A
Logger::Instance()->SetThreadLocalContext("A");
// Call function foo
Logger::Instance()->Log(log_level, "foo", log_msg);