I have logback deployed in my war file lib folder and I have the following logback.xml in the classes folder.
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<property name="destination" value="${catalina.base:-./temp}/logs/${appName:-myapp}" />
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${destination}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${destination}-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- Keep logs for 7 days -->
<maxHistory>7</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="error">
<appender-ref ref="ROLLING" />
</root>
</configuration>
On line 3 I have some variable substitutions that create the path for my log file.
<property name="destination" value="${catalina.base:-./temp}/logs/${appName:-myapp}" />
I want to make it so ${appName}
evaluates to the current name of the war file as deployed.
So if my web apps folder looked like so
webapps
- myapp.war
- myapp-dev.war
The ${destination}
property for myapp.war would evaluate to .../logs/myapp
and myapp-dev.war would evaluate to .../logs/myapp-dev
. Is there a JNDI property or something I can access to access the appName ?
I would like to avoid having to manually reconfigure the logger.
Thanks!
In a Spring Boot application, you can put the Logback. xml file in the resources folder. If your Logback. xml file is outside the classpath, you need to point to its location using the Logback.
By default, LogbackValve looks for a configuration file called logback-access. xml, in the same folder where server. xml is located, that is in $TOMCAT_HOME/conf/. This configuration file contains directives for configuring logback-access components.
Logback is one of the most widely used logging frameworks in the Java Community. It's a replacement for its predecessor, Log4j. Logback offers a faster implementation, provides more options for configuration, and more flexibility in archiving old log files.
EDIT 2013-06: I have made this Listener
available as OSS on Maven Central. Check out the project homepage.
Yes, this is feasible. First of all, you can always rely on catalina.base
because without it Tomcat won't run. In order to inject the context name as property. Write a context listener which will put the context name into the JNDI context and remove at shutdown. After you have done that, You can retrieve the value with JNDI directly with logback. There is direct support for that. Write that in the the contextName element and you're done.
I have implemented this on my own already and it works for all of my projects. I can share the entire code on monday if you or someone else is interested.
Edit, here is the code:
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.deploy.ContextEnvironment;
import org.apache.commons.lang.StringUtils;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class LogbackContextNameListener implements LifecycleListener {
private static final Log logger = LogFactory
.getLog(LogbackContextNameListener.class);
private Context context;
private String name = "logback/contextName";
@Override
public void lifecycleEvent(LifecycleEvent le) {
if (le.getLifecycle() instanceof Context)
context = (Context) le.getLifecycle();
else
return;
if (le.getType().equals(Lifecycle.START_EVENT)) {
ContextEnvironment ce = new ContextEnvironment();
ce.setName(getName());
ce.setOverride(false);
ce.setType("java.lang.String");
String value = StringUtils.remove(context.getServletContext()
.getContextPath(), '/');
ce.setValue(value);
logger.debug(String.format("Adding env entry '%s' with value '%s'",
getName(), value));
context.getNamingResources().addEnvironment(ce);
}
if (le.getType().equals(Lifecycle.STOP_EVENT)) {
logger.debug(String.format("Removing env entry '%s'", getName()));
context.getNamingResources().removeEnvironment(name);
}
}
public String getName() {
return name;
}
public void setName(String name) {
if (StringUtils.isEmpty(name))
throw new IllegalArgumentException(
"Parameter 'name' cannot be empty");
this.name = name;
}
}
A suitable config looks like this:
<configuration scan="true" scanPeriod="30 minutes">
<insertFromJNDI env-entry-name="java:comp/env/logback/contextName" as="contextName" />
<contextName>${contextName}</contextName>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/logs/${CONTEXT_NAME}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${catalina.base}/logs/${CONTEXT_NAME}.log.%d.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-27(%d{HH:mm:ss.SSS} [%.-12thread]) %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO"><!-- WARN -->
<appender-ref ref="FILE" />
</root>
</configuration>
This works flawlessly in Tomcat 6. I guess, it will run on Tomcat 7 w/o changes.
This builds on Michael-O's answer. Considering that catalina.base
is always a defined system property when running under Tomcat, we only have to worry about defining appName
. Logback offers support for retrieving variables from JNDI. If appName is defined in JNDI, your configuration file becomes:
<configuration>
<!-- retrieve appName from JNDI to set the variable appName -->
<insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
<!-- let the context name be the applicaiton name -->
<contextName>${appName}</contextName>
<property name="destination"
value="${catalina.base:-./temp}/logs/${CONTEXT_NAME:-myapp}" />
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${destination}.log</file>
... remainder of config file omitted for brevity
</appender>
</configuration>
I'd like to mention that you could also just define appName directly in logback.xml instead of in JNDI. (After all, the logback.xml file ships with your web-app where its name is already established. However, your question explicitly excludes this hypothesis.) Thus, you logback.xml file could be simplified to:
<configuration>
<contextName>the_name_of_your_webapp</contextName>
<property name="destination"
value="${catalina.base:-./temp}/logs/${CONTEXT_NAME:-myapp}" />
... the rest omitted for brevity
</configuration?
BTW, once you find a satisfactory solution, do not hesitate to share it by posting on logback-user list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With