Reputation: 5997
I'm writing a Java web application to deploy in Tomcat and i'm using log4j for logging. I like to insert automatically the web application's folder name in the generated log file's name.
Currently the filename setting looks like this in log4j.properties:
log4j.appender.R.File=${catalina.home}/logs/mywebapp.log
and i need something like this:
log4j.appender.R.File=${catalina.home}/logs/${current.webapp.folder}.log
Is there some kind of environment variable for this to specify in the properties file, or i have to instantiate the logger from code?
Upvotes: 11
Views: 5810
Reputation: 41
It's really easy to use Log4j2 Web Lookup feature, so you can just set your log filename to something like
fileName="${sys:catalina.base}/logs/${web:contextPathName}.log"
See https://logging.apache.org/log4j/2.x/manual/lookups.html#WebLookup for details. Do not forget to add log4j-web-x.y.z.jar file to your WEB-INF/lib for this feature to start working.
Upvotes: 1
Reputation: 30119
You can achieve that using a context listener to set up a system property, and then use the property in your log4j configuration.
You can first set a system property (e.g., contextPath
) to the value of the application's Tomcat context path. You could do this in a context listener.
package my.package.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent event) {
defineContextPath(event);
}
private void defineContextPath(ServletContextEvent event) {
ServletContext context = event.getServletContext();
String contextPath = context.getContextPath();
if (contextPath != null) {
String pattern = ".*/(.*)";
String contex = contextPath.replaceAll(pattern, "$1");
System.setProperty("contextPath", contex);
System.out.println("contextPath: " + contex);
} else {
System.out.println("contextPath not found");
}
}
}
Declare the listener in your web.xml:
<!-- Be sure to keep my.package.ContextListener as the first listener
if you have more listeners as below -->
<listener>
<listener-class>my.package.ContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Then in your log4j configuration file, you can use the system property contextPath
to set your log4j filename.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %5p %c{1}:%L - %m%n" />
</Console>
<RollingFile name="RollingFile" fileName="${catalina.base}/logs/${tomcat.hostname}/${contextPath}.log"
filePattern="${catalina.base}/logs/${tomcat.hostname}/$${date:yyyy-MM}/${contextPath}-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n" />
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="500 MB" />
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="info" />
<Root level="info">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
Upvotes: 5
Reputation: 5997
It's not a configuration file only solution, so i keep the question open for a while.
I've renamed the log4j.properties
to myapp-log4j.properties
and modified the log file name property like this:
log4j.appender.R.File=${catalina.base}/logs/#{context.name}.log
Because i have a servlet which is loaded at startup, i'm initializing log4j in the init() function.
String contextPath = getServletContext().getContextPath();
// First reconfigure log4j
String contextName = contextPath.substring(1);
if (!configureLog4J(contextName)) {
return;
}
The function for this:
public static final String LOG4JAPPENDERRFILE = "log4j.appender.R.File";
private boolean configureLog4J(String contextName) {
Properties props = new Properties();
try {
InputStream configStream = getClass().getResourceAsStream("/myapp-log4j.properties");
props.load(configStream);
configStream.close();
} catch(IOException e) {
System.out.println("FATAL! Cannot load log4j configuration file from classpath.");
e.printStackTrace(System.out);
return false;
}
String logFile = props.getProperty(LOG4JAPPENDERRFILE);
logFile=logFile.replace("#{context.name}", contextName);
props.setProperty(LOG4JAPPENDERRFILE, logFile);
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
return true;
}
It seems like to work fine, but i don't really like that i have to modify the properties file in code.
Upvotes: 2
Reputation: 532
First try to append your "log4j.properties".
current.webapp.folder=myapp
Second, If you used "PropertyConfigurator"...
Properties props = new Property();
/* Read "log4j.properties" */
Properties webappProps = new Property();
/* Read setting ex."current.webapp.folder=myapp" */
Enumeration<Object> e = props.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
// used org.apache.log4j.helpers.OptionConverter
props.setProperty(
key,
OptionConverter.substVars(props.getProperty(key), webappProps));
}
PropertyConfigurator.configure(props);
Upvotes: 1