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时,日志会被破坏。在查看我们的系统后,我们得出以下结论:

  • 我们希望一次只能更改其中一个类的调试级别(或者使用root更改所有类)
  • 当所有类型的
    foo
    打印到日志时,我们需要查看哪个实体将其命名为A、B或C
  • 由于有许多
    foo
    我们希望能够分别更改每个
    foo
  • A
    foo
    应被视为一个公共库,它不能直接依赖于A、B或C
  • A、 B和C可能使用同一个
    foo
    实例(例如,我们的资源处理类的同一个实例用于A、B和C),在日志中,我们希望看到哪个类使用了
    foo
  • A可以使用B(或C),但我们不必在日志中看到它
  • 这就是我们到目前为止得出的结论-

    A、 B和C将有单独的记录器。全局变量(与所有日志帮助程序和包装器一起保存在不同的库中)将始终保持当前日志报告。每次实体开始处理其逻辑时,它都会将全局变量设置为正确的记录器。当
    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);