On May 8, 2008, at 7:12 AM, Michael Duerr wrote:
Hallo,
I'm writing a simulation application, that creates and destroys
several objects
of the same class during the simulation. I want to perform logging
for each of
these objects to a single file (i.e. I want only the output of one
object in the
corresponding object's logging file). The application is single
threaded.
Can I achieve this behaviour with log4cxx - if so - how? I tried to
implement
this behaviour by initializing a new logger for each new object. But
since there
are up to 10000 objects this seems to be inefficient. Furthermore I
could not
figure out how to delete such a logger in case the associated object
gets
destroyed (how todo this???) and hence I experienced a lot of memory
leaks. To
my best knowledge MDC is also no alternative, since it does not
allow for the
restricted object->file logging.
Is there any chance to achieve this logging behaviour with log4cxx?
Thank you!
Cheers Michael
I agree with Dale's comments, but want to add some more.
The motivation of having a logger hierarchy is so to allow the user to
control the processing of logging requests by discarding some requests
and selectively routing others to specific appenders. Having 10000
loggers with dynamic names has little value to someone who is trying
to shape logging in the configuration file.
If you really wanted 10000 output files, the best approach would be to
use something like the mythical MultiFileAppender that lies unfinished
in the log4j sandbox. One appender, but can manage multiple open
files. Search log4j-dev for MultiFileAppender for the back story if
you are interested.
However, I agree with Dale that you'd be better off writing to a
single file and then appropriately sorting or filtering.
If you were using the mythical MFA, you'd need to have something in
the logging event to determine what file the event should be routed,
some sort of identification of the object. In the single file
approach, you could write this identifier out into the log file and
then use grep to pull out only the relevant log entries.
The question is then how do you get this object identifier into the
logging event. Your options are:
1. Put the object identifier into the message. Either something like:
LOG4CXX_INFO(logger, this << "Hello, World");
You'd need to provide an insertion operator for your object that works
on a log4cxx::helpers::MessageBuffer to insert the id. If advantage
of this is that it costs nothing if logging is disabled.
A cleaner solution would be to define your own macro that handled
inserting the object ID into the message.
2. Put the object identifier in the NDC on public method entry:
void foo() {
NDC entry(getID());
}
This will add an entry to the nested diagnostic context on method
entry and remove it on method exit. However, this adds a fixed cost
to the method call even if logging is disabled.
3. Put the object identifier in the MDC on public method entry:
void foo() {
MDC entry("objID", getID());
Same disadvantage and likely slower.