13

I'm trying to configure sl4j/logback under Weblogic12. I deploy ear file, which has war file, which has WEB-INF\classes\logback.xml
Here is the config:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<root level="debug">
    <appender-ref ref="STDOUT" />
</root>

</configuration>

My code to log :

private static final Logger logger = LoggerFactory.getLogger(FrontEndServlet.class);
//......
logger.info("info test");
logger.debug("debug test");
logger.error("error test");

What I see in the standart output is :

ьрщ 14, 2012 5:09:29 PM .....FrontEndServlet doPost
INFO: info test
ьрщ 14, 2012 5:09:29 PM .....FrontEndServlet doPost
SEVERE: error test

So, it looks like config file is not picked up. What am I doing wrong?

mik
  • 1,575
  • 6
  • 22
  • 33

5 Answers5

21

The problem is discussed here in detail: https://stagingthinking.wordpress.com/2012/06/02/annoying-slf4j-problem-in-weblogic-server-12c/

The exact package you need to put to the prefer-application-packages mechanism is org.slf4j, like this:

<?xml version='1.0' encoding='UTF-8'?>
<weblogic-application>
  <prefer-application-packages>
    <package-name>org.slf4j</package-name>
  </prefer-application-packages>
</weblogic-application>
dbrin
  • 15,525
  • 4
  • 56
  • 83
Kristof Jozsa
  • 6,612
  • 4
  • 28
  • 32
8

Note: Also this question is already answered, I want to add that you should also add prefer-application-resources.

Answer: Add a file called META-INF/weblogic-application.xml to your ear, containing both prefer-application-packages and prefer-application-resources!

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application
        xmlns="http://xmlns.oracle.com/weblogic/weblogic-application"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-application http://xmlns.oracle.com/weblogic/weblogic-application/1.5/weblogic-application.xsd"
        version="6">

    <!-- http://www.torsten-horn.de/techdocs/jee-oracleweblogic.htm -->
    <prefer-application-packages>
        <package-name>org.slf4j.*</package-name>
    </prefer-application-packages>


    <!-- if not using prefer-application-resources you will get a warning like this: -->
    <!-- Class path contains multiple SLF4J bindings -->
    <!-- SLF4J: Found binding in [jar:file:/C:/wls1211/modules/org.slf4j.jdk14_1.6.1.0.jar!/org/slf4j/impl/StaticLoggerBinder.class] -->
    <prefer-application-resources>
        <resource-name>org/slf4j/impl/StaticLoggerBinder.class</resource-name>
    </prefer-application-resources>


</weblogic-application>
Matthias B
  • 5,523
  • 3
  • 45
  • 47
6

The problem was - sl4j did not pick up logback and used Weblogic's slf4j-jdk logging instead. Can be fixed with Weblogic's config weblogic-application.xml, option prefer-application-packages

mik
  • 1,575
  • 6
  • 22
  • 33
1

Alternatively or if you have problems with more than just slf4j, you could use

<wls:container-descriptor>
    <wls:prefer-web-inf-classes>true</wls:prefer-web-inf-classes>
</wls:container-descriptor>

Instead of

<prefer-application-packages>
    <package-name>org.slf4j.*</package-name>
</prefer-application-packages>

Source: Oracle

Olivier Tonglet
  • 3,312
  • 24
  • 40
1

Environment: Weblogic 12.2.1 Logging Framework : Slf4j and Logback Requirement : Log to a file of my choosing (per application) as well as Weblogic server logs

Using the <prefer-application-packages/> or <prefer-web-inf-classes> in weblogic.xml did not satisfy the requirement. In my testing, using one or the other tags (you can't use both) will result in the application logback.xml to be picked up and logging will go to the file defined in logback.xml. However, the typical STDOUT defintion using logback's ConsoleAppender will not log to the server logs.

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

Removing the following from weblogic.xml

<wls:prefer-application-packages>
    <wls:package-name>org.slf4j.*</wls:package-name>
</wls:prefer-application-packages>

will result in using the bundled SLF4j binding, which in Weblogic 12.2.1, is Java Util logging. In this case, log statements will go to the server logs and not to the file definition in the application level logback.xml. In my research, it appears at one time, some version of Weblogic 12 allowed the internal SLF4j to be bound to Log4j but was removed in one of the minor releases. This was my case; I did not have the option of enabling Log4j as the primary logging Framework in Weblogic through the Admin console. I am fairly sure this wouldn't have helped me, but I did want to note it because several documents I read indicated this would be available.

After much research and fighting configuration with weblogic.xml, configuration of POM (exclusions etc) and trying to use different bindings and bridges, I was unable to achieve the logging configuration that I wanted. It appears that Weblogic's slf4j is bound to Java utility logging, for better or worse. If you choose your own implementation of slf4j and binding (in my case Logback), there is no way that I could find to route those messages to Weblogic server logs through configuration. There can only be one binding in slf4j, and although many frameworks can be routed to that one binding, (I found this diagram useful) Weblogic 12.2.1 only employs Java util logging binding, there is no way to (at the application configuration level) to wire Weblogic to use the Logback binding that you provide to log to its server logs. There might be some way to use log4j and bridges to accomplish this, but for me that's entirely too much bloat and configuration to accomplish a simple logging task.

Giving up on trying to conquer this by configuration, I decided to simply write my own logback appender that translates a logging event into a JUL logging event. I replaced the standard STDOUT definition seen in many Logback examples with my own implementation of Logback's AppenderBase. At this point I can now log using per application logging configuration and also log to the Weblogic Server log.

Relevant POM Dependencies:

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.2.3</version>
    </dependency>

weblogic.xml (Note here that Hibernate comes with JbossLogging which will bridge to slf4j automatically)

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/2.0/weblogic-web-app.xsd">
<jsp-descriptor>
    <keepgenerated>true</keepgenerated>
    <debug>true</debug>
</jsp-descriptor>
<context-root>YourContextRoot</context-root>
<wls:container-descriptor>
    <wls:prefer-application-packages>
        <wls:package-name>ch.qos.logback.*</wls:package-name>
        <wls:package-name>org.jboss.logging.*</wls:package-name>
        <wls:package-name>org.slf4j.*</wls:package-name>
    </wls:prefer-application-packages>
    <wls:prefer-application-resources>
        <wls:resource-name>org/slf4j/impl/StaticLoggerBinder.class</wls:resource-name>
    </wls:prefer-application-resources>
</wls:container-descriptor>

Logback AppenderBase implementation

import java.util.logging.Logger;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;

public class WeblogicAppender extends AppenderBase<ILoggingEvent> {

private final Logger logger = Logger.getLogger(WeblogicAppender.class.getName());
ILoggingEvent event = null;

@Override
protected void append(ILoggingEvent event) {
    this.event = event;
    logger.log(getJULLevel(), event.getFormattedMessage());
}

private java.util.logging.Level getJULLevel() {

    if (this.event == null) {
        return java.util.logging.Level.SEVERE;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.ALL) {
        return java.util.logging.Level.ALL;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.DEBUG) {
        return java.util.logging.Level.FINE;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.ERROR) {
        return java.util.logging.Level.SEVERE;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.INFO) {
        return java.util.logging.Level.INFO;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.TRACE) {
        return java.util.logging.Level.FINEST;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.WARN) {
        return java.util.logging.Level.WARNING;
    } else if (this.event.getLevel() == ch.qos.logback.classic.Level.OFF) {
        return java.util.logging.Level.OFF;
    } else {
        return java.util.logging.Level.INFO;
    }
}

}

Logback.xml configuration

<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
<appender name="STDOUT" class="com.your.package.WeblogicAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger: LineNumber:%L - %message%n</pattern>
    </encoder>
</appender>
<appender name="FILE"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>yourlog.log
    </file>
    <rollingPolicy
        class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>yourlog.%d{yyyy-MM-dd}.%i.log
        </fileNamePattern>
        <maxFileSize>25MB</maxFileSize>
        <maxHistory>60</maxHistory>
        <totalSizeCap>10GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger: LineNumber:%L - %message%n</pattern>
    </encoder>
</appender>

<root level="TRACE">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="FILE" />
</root>
</configuration>

Hopefully I can save others some of the pain that I went through trying to get this working the way I wanted.

Hodglem
  • 614
  • 9
  • 17
  • hi, can I ask you where to put the logback.xml file? It seems that weblogic 12c simply ignores it. The deployment descriptors are configurued correctly, in fact I can see my logs at console level, but I need to define several file appenders and wherever I put the logback.xml file, it doesn't seem to work. Unfortunately, the solution to put the config within another maven module is not applicable in my case. Any suggestion? – senape Apr 26 '18 at 07:32
  • Hi. logback.xml goes in src/main/resources. Once you build the war, explore it and validate that the logback.xml ends up in /WEB-INF/classes. If weblogic is still ignoring it, the container-descriptor and prefer-application-packages may not be syntactically correct. Make sure you have the proper wls namespace defined (like in the example I posted). You can validate that weblogic.xml is being seen by weblogic by putting some garbage strings in and deploying the war. Weblogic will choke if its can't parse weblogic.xml. Good luck! PM me if you need more help. – Hodglem Apr 26 '18 at 12:38
  • @senape Also, keep in mind if console is logging, that means that weblogic internal logging (JUL) is catching your statements OR the internal Weblogic logback is being used. Once you get your app logback working, you should see NO statements in the console log and only in the file you define in logback.xml. Then you can add the weblogic appender and class I show above to log to the console. – Hodglem Apr 26 '18 at 12:41