On Dec 9, 2004, at 1:10 AM, Barak Simon wrote:
Hi again,
I have just noticed that the LoggingEvent class contains a 'properties' map,
and provides getter and setter for it.
From a quick look at the log4j code, LoggingEvent's properties seem to be the combination of the MDC properties and the LoggerRepository properties. Could you explain why using the MDC is not workable? I don't have any experience with setting LoggerRepository properties, it seems be a recent (that is 1.3 series) addition to log4j.
Is using that (instead of deriving from LoggingEvent) a feasible solution?
What I think of is deriving a customised logger, and then overloading the forcedLog methods, such
that they can accept an extra 'properties' structure to be used for initing the newly created event
before calling callAppenders.
How would this differ from using the MDC (thread-specific) or LoggerRepository properties (all threads) which already accomplish the same things?
Hi,
If this class is not meant for extension then why does Log4j doco say:
(1) "This class is of concern to those wishing to extend log4j."
Do they mean by that log4j developers rather than users - Sounds a bit bizarre to me...
(2) Why did they not use "final"?
There seem to be very few final classes in log4j proper (Chainsaw has many more), the ones that I saw were LoggingEventFieldResolver, RootCategory, RootLogger, ListAppender and ListModelAppender. Some classes (appenders, layouts) were intentionally designed for extension, others like LoggingEvent were not. I don't know the history why some classes that would seem good candidates to be final weren't made final.
The point is that not being able to add your own customised fields, is, I think, limiting significantly what one can do.
In my case, I have derived a SyslogLayout from PatternLayout, so as to be able to prepend and append
some specific information to the syslog messages, information which is expected by our existing monitoring systems.
What type of information were you adding? Would any of them make good additions to the set of supported pattern expressions?
But at that stage I can only use the data populated in LoggingEvent (or any other data which is more or less global in its nature).
What I cannot do (but need to) is to get event-contextual data, e.g. event-id, if we want to add such data per every logged message.
log4j 1.3 has added a sequence number, but I think I see problems with it and need to investigate further. If it makes sense and we can port it into log4cxx.
If you are not multithreaded or are willing to establish a mutex for synchronization, you could pass info from your logging call site directly to your appender and/or layout.
If you want info to flow through the dispatching pipeline, then the MDC and NDC are the established ways of "extending" the event information.
If your information does change on every logging request, then you might consider adding your own macros that automatically manipulate the MDC or NDC. Something like:
#define BARAK_DEBUG(logger, msg) \
if (logger->isDebugEnabled()) { \
log4cxx::MDC::set("whatever", getWhatever()); \
logger->forcedLog(log4cxx::Level::DEBUG, msg, __FILE__, __LINE__)Subsequent versions of logger.h will not redefine LOG4CXX_DEBUG etc, so you could define your own LOG4CXX_* macros before you include <log4cxx/logger.h>.
Unless I am missing the better/intended way of doing what I want, I truly think this is a harsh limitation,
but be happy to hear differing opinions.
