Uploaded image for project: 'Log4j 2'
  1. Log4j 2
  2. LOG4J2-2025

Support Tomcat JULI's per-webapp JUL logging by implementing java.util.logging.Handler

    Details

    • Type: Improvement
    • Status: Reopened
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.8.2
    • Fix Version/s: 2.10.0
    • Component/s: JUL adapter
    • Labels:
      None
    • Environment:

      Tomcat 8.5.20, Oracle Java 1.8.0_144

      Description

      On most servlet containers, the only way to redirect JUL calls to Log4j is by setting the java.util.logging.manager=org.apache.logging.log4j.jul.LogManager system property globally. This often breaks the native logging of the container, and could also break other apps on the same container do not use Log4j 2. This also requires changing the container's settings and cannot be expressed in the app itself.

      Another approach (used by slf4j) is to implement java.util.logging.Handler and then install this handler at the root logger, either programmatically by calling LogManager.getLogManager().getLogger("").addHandler(...) or by changing logging.properties at the JRE level. This also breaks the container's native logging and other apps, but in different ways than LogManager. I do not advocate this approach, but it's useful to know about it as a background for this feature request.

      (tl;dr: It's impossible to reliably redirect JUL from a webapp without creating a mess).

      Thankfully, Tomcat has a solution for this: Tomcat JULI allows per-webapp configuration by adding a WEB-INF/classes/logging.properties file with handlers=some.custom.Handler inside it. This will redirect JUL calls from this webapp (and this webapp only) to that handler, and that handler then can redirect to Log4j.

      In short: Add a java.util.logging.Handler implementation that redirects to Log4j so that webapps can use Tomcat's per-webapp configuration and avoid the JUL mess.

        Activity

        Hide
        garydgregory Gary Gregory added a comment -

        A patch would be most welcome

        Show
        garydgregory Gary Gregory added a comment - A patch would be most welcome
        Hide
        ralph.goers@dslextreme.com Ralph Goers added a comment - - edited

        I see an issue in this design. When the isLoggable method on the logger is called it will reflect the log level in the tomcat logging system. If you set the log level in tomcat to "FINEST" so that all log events are passed to Log4j then many log events will be created only to be dropped by Log4j, thus hurting performance. OTOH, if you set the tomcat level to the desired level then the log level on the Log4j logger really should just be set to TRACE as no filtering should be performed.

        This is one place where I could see having the java.util.logging.Handler be a replacement for the Log4j-core Logger, although I haven't looked at what that would entail.

        FWIW, if we took this approach I would just add it to log4j-jul since it would just be an alternate way to wire jul to core.

        Show
        ralph.goers@dslextreme.com Ralph Goers added a comment - - edited I see an issue in this design. When the isLoggable method on the logger is called it will reflect the log level in the tomcat logging system. If you set the log level in tomcat to "FINEST" so that all log events are passed to Log4j then many log events will be created only to be dropped by Log4j, thus hurting performance. OTOH, if you set the tomcat level to the desired level then the log level on the Log4j logger really should just be set to TRACE as no filtering should be performed. This is one place where I could see having the java.util.logging.Handler be a replacement for the Log4j-core Logger, although I haven't looked at what that would entail. FWIW, if we took this approach I would just add it to log4j-jul since it would just be an alternate way to wire jul to core.
        Hide
        imgx64 Ibrahim M. Ghazal added a comment -

        Yes, performance will be an issue. We need this for some third party libraries that use JUL internally instead of using a logging abstraction, so we don't have much choice (apart from stitching together logs from two files).

        It could be worked around by calling java.util.logging.Logger.getLogger(name).setLevel(level) when setting log4j logger levels, but I'm not sure if that would apply only to the current application in Tomcat or if it would affect the global JUL state. I'll investigate.

        I don't understand what you mean by having the java.util.logging.Handler be a replacement for the Log4j-core Logger. Can you elaborate?

        Show
        imgx64 Ibrahim M. Ghazal added a comment - Yes, performance will be an issue. We need this for some third party libraries that use JUL internally instead of using a logging abstraction, so we don't have much choice (apart from stitching together logs from two files). It could be worked around by calling java.util.logging.Logger.getLogger(name).setLevel(level) when setting log4j logger levels, but I'm not sure if that would apply only to the current application in Tomcat or if it would affect the global JUL state. I'll investigate. I don't understand what you mean by having the java.util.logging.Handler be a replacement for the Log4j-core Logger . Can you elaborate?
        Hide
        jira-bot ASF subversion and git services added a comment -

        Commit 3cb6238c148f529abb97a4894e36bf7c764ee60b in logging-log4j2's branch refs/heads/master from Ralph Goers
        [ https://git-wip-us.apache.org/repos/asf?p=logging-log4j2.git;h=3cb6238 ]

        LOG4J2-2025 - Provide support for overriding the Tomcat Log class in Tomcat 8.5+.

        Show
        jira-bot ASF subversion and git services added a comment - Commit 3cb6238c148f529abb97a4894e36bf7c764ee60b in logging-log4j2's branch refs/heads/master from Ralph Goers [ https://git-wip-us.apache.org/repos/asf?p=logging-log4j2.git;h=3cb6238 ] LOG4J2-2025 - Provide support for overriding the Tomcat Log class in Tomcat 8.5+.
        Hide
        ralph.goers@dslextreme.com Ralph Goers added a comment -

        I was able to add this support using Tomcat's documented method for defining custom implementations of the Log interface. This requires that the log4j-api, log4j-core, and log4j-appserver jars be configured in the boot classpath. In addition, it will search for a configuration file named log4j2-tomcat.xml, log4j2-tomcat.json, log4j2-tomcat.yaml, log4j2-tomcat.yml, or log4j2-tomcat.properties. One of those files or a "standard" log4j2.* configuration file must be in the boot classpath.

        Please verify and close.

        Show
        ralph.goers@dslextreme.com Ralph Goers added a comment - I was able to add this support using Tomcat's documented method for defining custom implementations of the Log interface. This requires that the log4j-api, log4j-core, and log4j-appserver jars be configured in the boot classpath. In addition, it will search for a configuration file named log4j2-tomcat.xml, log4j2-tomcat.json, log4j2-tomcat.yaml, log4j2-tomcat.yml, or log4j2-tomcat.properties. One of those files or a "standard" log4j2.* configuration file must be in the boot classpath. Please verify and close.
        Hide
        ralph.goers@dslextreme.com Ralph Goers added a comment -

        Reopening since we are not going to include this in the 2.9.1 release.

        Show
        ralph.goers@dslextreme.com Ralph Goers added a comment - Reopening since we are not going to include this in the 2.9.1 release.
        Hide
        imgx64 Ibrahim M. Ghazal added a comment -

        This doesn't actually fix this issue. It's a better way to redirect Tomcat logging, but it doesn't fix this issue.

        This issue is about redirecting JUL on a single application without changing the global Tomcat settings or adding to its classpath. It can be solved by implementing java.util.logging.Handler and instructing users to add WEB-INF/classes/logging.properties file with handlers=the.handler.Implementation inside it.

        Show
        imgx64 Ibrahim M. Ghazal added a comment - This doesn't actually fix this issue. It's a better way to redirect Tomcat logging, but it doesn't fix this issue. This issue is about redirecting JUL on a single application without changing the global Tomcat settings or adding to its classpath. It can be solved by implementing java.util.logging.Handler and instructing users to add WEB-INF/classes/logging.properties file with handlers=the.handler.Implementation inside it.
        Hide
        imgx64 Ibrahim M. Ghazal added a comment -

        Also, about JUL loggers' logging levels, they can be synchronized with Log4j loggers' logging levels using java.util.logging.Logger.getLogger(name).setLevel(level) and they will only affect the current application's loggers. So this could reduce the performance impact.

        Show
        imgx64 Ibrahim M. Ghazal added a comment - Also, about JUL loggers' logging levels, they can be synchronized with Log4j loggers' logging levels using java.util.logging.Logger.getLogger(name).setLevel(level) and they will only affect the current application's loggers. So this could reduce the performance impact.

          People

          • Assignee:
            ralph.goers@dslextreme.com Ralph Goers
            Reporter:
            imgx64 Ibrahim M. Ghazal
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:

              Development