8

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

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

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

记录 A、B 和 C 原来是一个性能问题,当我们将日志级别设置为调试时,日志被炸毁。查看我们的系统后,我们得出以下结论:

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

这是我们迄今为止提出的 -

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

问题是,感觉必须有一些东西已经这样做了,解决方案感觉不干净,持有这样的全局变量......

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

4

2 回答 2

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

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

于 2014-01-08T08:54:39.253 回答
1

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

它在下面仍然是一个全局变量,但至少它是类范围的全局变量(就像一个名为debugLog.logwheredebugLog是类名的类变量)。

于 2014-01-06T02:25:23.113 回答