不同的记录器与库一起使用 [英] different loggers used with libraries

查看:144
本文介绍了不同的记录器与库一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



假设我有一个进程有几个实体A,B和C.他们使用许多不同的



A,B和C使用许多库类,函数,对象,资源,有时甚至是全局变量可以做到...) - 让我们称它们为 foo



记录A,B和C出现为性能问题,当我们将日志级别设置为调试时,日志会被炸毁。查看我们的系统后,我们得出这些结论:


  1. 我们希望能够一次只更改一个类的调试级别(或全部,使用root)

  2. 当所有 foo 打印到日志时,我们需要看到哪个实体,A,B或C。

  3. 由于许多 foo 我们希望能够分别更改每个 foo

  4. A foo 应视为公共库,

  5. A,B和C可能使用 foo 的相同实例(例如,我们的资源处理类的同一个实例使用A,B和C),在日志中我们想看看哪个类使用 foo

  6. A可以使用B(或C),但我们不必在日志中看到它。

我们到目前为止 -



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

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



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

解决方案

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

  class Logger {
public:
enum级别{
...
};
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通过实体A具有DEBUG日志级别
Logger :: Instance() - > AddModuleFilter(A,foo,Logger :: DEBUG);
//实体B的foo调用具有WARNING日志级别
Logger :: Instance() - > AddModuleFilter(B,foo,Logger :: WARNING);

然后,呼叫流程将如下所示:

  //在实体A 
Logger :: Instance() - > SetThreadLocalContext(A);
//调用函数foo
Logger :: Instance() - > Log(log_level,foo,log_msg);

不确定这样的界面是否符合您的目的。反正,我总是认为界面第一好方法。一旦你有一个清晰的界面,实施它应该是一个容易的工作。


My problem concerns logging of library classes (classes that are used inside libraries), We are currently using log4cxx but the log4j library implements the same concepts.

Say i have a process that have several entities, A,B and C. Each of them use many different classes and functions, clearly separated in the code.

A,B and C use many library classes, functions, objects, resources and sometimes even globals (legacy code, nothing i can do about it...) - let us call them all foo

Logging A,B and C turned out to be a performance issue, the log gets blasted when we set the log level to debug. After viewing our system we came to these conclusions:

  1. We want to be able to change debug level for only one of the classes at a time (or all of them, using root)
  2. When all kind of foo print to log, we need to see which entity called it, A, B or C.
  3. As there are many foo we want to be able to change the debug level separately for each foo
  4. A foo should be treated as a common library, it can not depend directly on A,B or C.
  5. A,B and C might use the same instance of foo (for example, the same instance of our resource handling class is used A,B and C), in the log we would like to see which class used foo.
  6. A could use B (or C), but we dont have to see it in the log...

This is what we came up with so far -

A, B and C will have separate loggers. A global variable(kept in a different library with all of our logging helpers and wrappers) will always keep the current log reporting. Every time an entity starts handling it's logic, it sets the global variable to the proper logger. When a foo wants to report to the log, it reports through the global variable and adding it's name (and context) to the log message.

Problem is, it feels like there must be something that does this already, the solution does not feel clean, holding a global variable like that...

Are we doing something wrong here? Is there a better solution to this?

解决方案

I do not know of an existing solution. I would probably come up with a logger with an interface like the following (whether it is a standalone implementation or just a wrapper on your existing one):

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

The main deviation from common log libraries are the context-sensitive module filter. We may have setups like the following to set different levels according to who makes the call (the 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);

Then, the call flow will be like:

// In entity A
Logger::Instance()->SetThreadLocalContext("A");
// Call function foo
Logger::Instance()->Log(log_level, "foo", log_msg);

Not sure whether such an interface meets your purpose. Anyway, I always regard interface first a good approach. Once you have a clear interface, implementing it should be an easy job.

这篇关于不同的记录器与库一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆