Different registrars used with libraries

My problem is with registering library classes (classes that are used inside libraries). Currently we use log4cxx , but the log4j library implements the same concepts.

Let's say I have a process that has several entities, A, B, and C. Each of them uses many different classes and functions, clearly separated in the code.

A, B and C use many classes, functions, objects, resources, and sometimes global variables (outdated code, I can not do anything about it ...) - let's call them all foo

Writing A, B, and C turned out to be a performance issue, the log exploded when we set the log level for debugging. After viewing our system, we came to the following conclusions:

  • We want to be able to change the debugging level for only one of the classes at a time (or all of them using root)
  • When all kinds of foo are printed to the log, we need to see which object named it, A, B or C.
  • Since there are many foo , we want to be able to change the debug level separately for each foo
  • A foo should be considered as a shared library; it cannot directly depend on A, B or C.
  • A, B and C can use the same instance of foo (for example, the same instance of our resource handling class is used by A, B and C), in the log we would like to see which class was used by foo .
  • A can use B (or C), but we should not see it in the log ...

This is what we have come up with so far -

A, B and C will have separate registrars. A global variable (stored in another library with all our helpers and journal wrappers) will always keep current journal reporting. Each time an object begins to process it logically, it sets a global variable to the corresponding registrar. When foo wants to report to the log, it reports through a global variable and adds its name (and context) to the log message .

The problem is that there seems to be something that does this already, the solution doesn't feel clean, having such a global variable ...

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

+8
java c ++ logging log4j log4cxx
source share
2 answers

I do not know about the existing solution. I would probably come up with a registrar with an interface like the following (whether it be a standalone implementation or just a shell on an 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 shared log libraries is a filter for context-sensitive modules. We can have settings like the following to set different levels depending on who is making the call (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 look like this:

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

Not sure if this interface fits your purpose. Anyway, I always consider the interface to be the first good approach. Once you have an intuitive interface, its implementation should be an easy task.

+5
source share

If the individual library itself is a class, you can use the class level variable in the library to store the link to the journal instance. I don't often program in C ++ or Java, but I think the class level variable is β€œstatic” in C ++ and Java.

It is still a global variable, but at least a global class variable (for example, a class variable named debugLog.log , where debugLog is the class name).

+1
source share

All Articles