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

时间:2013-12-29 22:13:48

标签: java c++ logging log4j log4cxx

我的问题是关于库类的记录(库内部使用的类), 我们目前正在使用log4cxx,但log4j库实现了相同的概念。

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

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

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

  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),但我们不必在日志中看到它......
  7. 这是我们到目前为止所提出的 -

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

    问题是,感觉必须有一些东西可以做到这一点,解决方案感觉不干净,持有像这样的全局变量......

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

2 个答案:

答案 0 :(得分:5)

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

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);
    ...
};

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

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

不确定这样的界面是否符合您的目的。无论如何,我总是认为接口是一个很好的方法。一旦你有了一个清晰的界面,实现它应该是一件容易的事。

答案 1 :(得分:1)

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

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