与库一起使用的不同记录器

我的问题涉及到库类的记录(库中使用的类),我们目前正在使用log4cxxlog4j库实现了相同的概念。

假设我有一个包含多个实体A,B和C的进程。它们中的每一个都使用许多不同的类和函数,在代码中明确分开。

A,B和C使用许多库类,函数,对象,资源,有时甚至是全局变量(遗留代码,我无能为力……) – 让我们称之为foo

记录A,B和C结果是性能问题 ,当我们将日志级别设置为调试时,日志会被破坏。 查看我们的系统后,我们得出了以下结论:

  1. 我们希望能够一次只更改其中一个类的调试级别(或者所有类,使用root)
  2. 当所有类型的foo打印到日志时,我们需要查看哪个实体称为A,B或C.
  3. 因为有很多foo我们希望能够为每个foo单独更改调试级别
  4. foo应该被视为一个公共库,它不能直接依赖于A,B或C.
  5. A,B和C可能使用相同的foo实例(例如,我们的资源处理类的相同实例使用A,B和C),在日志中我们希望看到哪个类使用了foo
  6. A可以使用B(或C),但我们不必在日志中看到它…

这是我们到目前为止所提出的 –

A,B和C将有单独的记录器。 全局变量(保存在包含所有日志记录助手和包装器的不同库中)将始终保持当前日志报告。 每次实体开始处理它的逻辑时,它都会将全局变量设置为正确的记录器。 当foo想要向日志报告时,它会通过全局变量进行报告, 并将其名称(和上下文)添加到日志消息中

问题是,感觉必须有一些事情已经做到这一点,解决方案不会感觉干净,持有像这样的全局变量……

我们在这里做错了吗? 有更好的解决方案吗?

我不知道现有的解决方案。 我可能会想出一个带有如下界面的记录器(无论是独立实现还是现有的包装):

 class Logger { public: enum Level { ... }; static Logger* Instance(); void Log(Level level, const char* module, const char* msg); void AddModuleFilter(const char* context, const char* module, Level level); void SetThreadLocalContext(const char* context); ... }; 

与常见日志库的主要偏差是上下文相关模块filter。 我们可能有如下设置,根据谁进行调用(上下文)设置不同的级别:

 // 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); 

不确定这样的界面是否符合您的目的。 无论如何,我总是认为界面是一个很好的方法。 一旦你有一个清晰的界面,实现它应该是一个简单的工作。

如果单独的库本身是一个类,则可以使用库中的类级变量来保存记录器实例引用。 我不经常使用C ++或Java编程,但我认为类级变量在C ++和Java中是“静态的”。

它仍然是一个全局变量,但至少它是类范围的全局变量(就像一个名为debugLog.log的类变量,其中debugLog是类名)。