Log4J Custom Fields
Introduction:
I'm trying to get additional fields to log with log4j, and its working but only when I create an appender in code and not in the log4j.properties
Progress:
- Used this article Adding Conversion Characters to PatternLayout for log4j 1.1.3
- Made a sample app for log4j 1.2
Problem:
using the properties file it will run but won't use AppServerPatternLayout so the custom fields aren't displayed.
Download Code
customlog.properties
log4j.rootLogger=FATAL
log4j.logger.some.log=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=logging.AppServerPatternLayout
log4j.appender.stdout.layout.ConversionPattern=-----------------using log file------------------------%nTime: %d%nHost: %h%nServer: %s%nComponent: %b%nVersion: %v%nPriority: %p%nThread Id: %t%nContext: %x%nMessage: %m%n
Main.java logging without a log4j properties file
AppServerLoggerFactory factory;
factory = new AppServerLoggerFactory("MyServer", "MyComponent", "1.0");
AppServerLogger.setFactory(factory);
Logger logger = AppServerLogger.getLogger("some.log");
PatternLayout layout = new AppServerPatternLayout( formatString );
logger.addAppender( new ConsoleAppender(layout) );
logger.info("Hello");
Main.java logging with a log4j properties file
PropertyConfigurator.configure("customlog.properties");
AppServerLoggerFactory factory;
factory = new AppServerLoggerFactory("MyServer", "MyComponent", "1.0");
AppServerLogger.setFactory(factory);
Logger logger = AppServerLogger.getLogger("some.log");
logger.info("Hello");
Expected output
----------------using in code appender----------------------
Time: 2009-11-06 12:55:05,785
Host: M1330
Server: MyServer
Component: MyComponent
Version: 1.0
Priority: INFO
Thread Id: main
Context:
Message: logging config from code
Actual output
-----------------using log file------------------------
Time: 2009-11-06 12:56:17,983
Host:
Server:
Component:
Version:
Priority: INFO
Thread Id: main
Context:
Message: logging config from customlog.properties
Solution
Using MDC you can add custom fields like
MDC.put("Version", versionName);
Logger log = LogManager.getLogger("some.log");
log.info("Hello");
and pull it out in the log4j.properties with a UPPER case X
log4j.appender.stdout.lay开发者_如何学运维out.ConversionPattern=%X{Version}
From the example you posted, I can only guess that AppServerPatternLayout
is not in the package logging
. Everything else looks find. Add
log4j.DEBUG=true
to your properties file. log4j will then dump what it does while reading the properties. Maybe that gives you an idea what's wrong.
If that doesn't help, consider to use Nested Diagnostic Contexts.
Can it be that when you load via properties the AppServerPatternLayout
is instantiated before the AppServerLoggerFactory
is created? If you pick up the values of your custom fields at creation as opposed to at first use that could be an explanation.
I'm not sure that you will achieve this with properties configuration, but I think you can do this with XML, which gives you a lot of customization options:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="true"
reset="true"
>
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="your.package.AppServerPatternLayout">
<param name="ConversionPattern" value="YOUR CONVERSION PATTERN"/>
</layout>
</appender>
<root>
<level value="info"/>
<appender-ref ref="stdout" />
</root>
<loggerFactory class="your.package.AppServerLoggerFactory">
<param name="server" value="MyServer"/>
<param name="component" value="MyComponent"/>
<param name="version" value="1.0r"/>
</loggerFactory>
</log4j:configuration>
You will need to define setters on AppServerLoggerFactory
for server, component and version. Also, read log4j.dtd
on general layout of xml configuration file.
Save this file as log4j.xml and define -Dlog4j.configuration=/path/to/log4j.xml in your startup script, or replace log4j.properties with log4j.xml in your web-app.
I've never tried a custom LoggerFactory before, but it may be that because it is installed by the configurator you can use standard getLogger
factory calls, e.g.
//Logger logger = AppServerLogger.getLogger("some.log");
Logger logger = Logger.getLogger("some.log");
精彩评论