Piers,
I've configured two webapps with the log4j2 configuration outside of the
*war files. The approach I'll describe is working in Tomcat 8.5 and Tomcat
9.
First I create a LogListener class for the webapp:
public class LogListener implements ServletContextListener {
private static final Logger LOGGER = LogManager.getLogger();
private Log4jServletContextListener listener = new
Log4jServletContextListener();
@Override
public void contextDestroyed(ServletContextEvent event) {
listener.contextDestroyed(event);
}
@Override
public void contextInitialized(ServletContextEvent event) {
String loggerPath = "WEB-INF/classes/log4j2.xml";
ServletContext context = event.getServletContext();
String fileString = context.getInitParameter("log4jConfiguration");
if (fileString != null && fileString.length() > 0
&& !fileString.equals("*")) {
if ((new File(fileString)).exists()) {
loggerPath = fileString;
}
}
event.getServletContext().setInitParameter(
Log4jWebSupport.LOG4J_CONFIG_LOCATION, loggerPath);
listener.contextInitialized(event);
LOGGER.info("logging properties from " + loggerPath);
}
}
I declare the LogListener in web.xml and add some filtering:
<listener>
<!-- This listener *must* be first for log4j to work. -->
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<listener>
<!-- This listener is required to set the log4jConfiguration fallback.
-->
<listener-class>com.mycorp.server.rest.listeners.LogListener</listener-class>
</listener>
<!-- See https://logging.apache.org/log4j/2.x/manual/webapp.html -->
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
<context-param>
<param-name>isLog4jAutoInitializationDisabled</param-name>
<param-value>true</param-value>
</context-param>
Finally, in the Tomcat context file, META-INF/context.xml, I add the
log4jConfiguration that LogListener wants:
<Parameter description="Configure Log4j2 logging."
name="log4jConfiguration" override="false"
value="/Users/admin/local/etc/my_logger.xml"/>
When I start Tomcat, the first entry in the log is
12:23:23.439 INFO LogListener.contextInitialized() - logging properties
from /Users/admin/local/etc/my_logger.xml
At one time I had this working in Jetty, but I no longer remember where to
set its context.
We've installed these apps on numerous servers, both Linux (of various
distros) and macOS. AFAIK, they're also running on a number of Windows
servers as well. Logging works everywhere.
On Wed, Mar 20, 2024 at 12:09 PM Piers Uso Walter <[email protected]>
wrote:
> Hi Piotr,
>
> Thanks for your email.
>
> Here is what I’m trying to do:
> The previous version of our app stores the log4j configuration within the
> war file.
> This works fine but is annoying if one wants to change any logging setting
> (unpacking the war, changing the configuration, repacking the war,
> redeploying).
>
> For the next version of our app, I would like to move the log4j
> configuration to a place outside of the war.
> For Tomcat I would like to use $catalina.home/conf/ilink/GW-log4j2.xml
> and for Wildlfy I would like to use
> $jboss.home.dir/conf/ilink/GW-log4j2.xml
> (with $catalina.home and $jboss.home.dir being system properties that are
> defined in the two servers)
>
> Since the configuration file path is only known at runtime I cannot use
> the servlet initialization parameter ‘log4jConfiguration’ in web.xml.
> So I looked at log4j's automatic configuration [1].
> This led me to the idea to use a ServletContextListener to determine if
> the app is running in WIldFly or in Tomcat and then setting the system
> property $log4j.configurationFile accordingly.
>
> But as you point out, the ServletContextListener is executed too late.
> That explains why it does not work in my case 2 (when the Tomcat service
> is restarted).
> I still don’t understand why it does work in my case 1 (when the app is
> being redeployed in a running Tomcat), but that is not so important as this
> does not seem to be the correct approach anyway.
>
> Also, thanks for pointing out what should have been obvious: that other
> web apps on the same server will be affected when I set the
> `log4j2.configurationFile` property.
> Not a good idea.
>
> Am I trying something unusual here when I attempt to make the app decide
> where the log4j configuration file is located?
> Is there any other way in which I can achieve this?
> Is there an API for this?
>
> Thanks,
> Piers
>
> [1]
> https://logging.apache.org/log4j/2.x/manual/configuration.html#automatic-configuration
>
>
>
> > Am 15.03.2024 um 07:45 schrieb Piotr P. Karwasz <[email protected]
> >:
> >
> > Hi Piers,
> >
> > On Thu, 14 Mar 2024 at 14:08, Piers Uso Walter <[email protected]>
> wrote:
> >> However, what I was trying to achieve by using a servlet context
> listener was to be able to set the location of the log4j configuration file
> at run time.
> >> I’m trying to make the app compatible with different app servers where
> configuration files are typically placed in different locations.
> >> So I’m figuring out at run time which app server the app is running in,
> and based on that I know where to expect the log4j configuration file.
> >
> > Can provide more details as to where the path to the configuration
> > file is actually stored? If you change the `log4j2.configurationFile`
> > property, other web apps on the same server will be affected, which
> > might be an unpleasant surprise to users. There are less invasive ways
> > to do that.
> >
> > I also wonder if maintaining container specific code is worth the
> > effort. Many application servers have a detailed guide to configuring
> > logging (e.g. WildFly[1]). Users might be unwilling to learn yet
> > another way to configure logging.
> >
> > Sure, Tomcat is an exception, that is why I maintain a small set of
> > Log4j Core plugins and Tomcat extensions[2] to help users
> > administering logging at a global level.
> >
> > Piotr
> >
> > [1] https://docs.wildfly.org/31/Admin_Guide.html#Logging
> > [2] https://github.com/copernik-eu/log4j-tomcat
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
>
>
--
"Hell hath no limits, nor is circumscrib'd In one self-place; but where we
are is hell, And where hell is, there must we ever be" --Christopher
Marlowe, *Doctor Faustus* (v. 111-13)