环境:Weblogic 12.2.1 日志框架:Slf4j 和 Logback 要求:记录到我选择的文件(每个应用程序)以及 Weblogic 服务器日志
在 weblogic.xml 中使用<prefer-application-packages/>
or <prefer-web-inf-classes>
不满足要求。在我的测试中,使用一个或其他标签(不能同时使用两者)将导致应用程序 logback.xml 被拾取,并且日志记录将转到 logback.xml 中定义的文件。但是,使用 logback 的 ConsoleAppender 的典型 STDOUT 定义不会记录到服务器日志。
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
从 weblogic.xml 中删除以下内容
<wls:prefer-application-packages>
<wls:package-name>org.slf4j.*</wls:package-name>
</wls:prefer-application-packages>
将导致使用捆绑的 SLF4j 绑定,在 Weblogic 12.2.1 中,它是 Java Util 日志记录。在这种情况下,日志语句将转到服务器日志,而不是应用程序级别 logback.xml 中的文件定义。在我的研究中,有时 Weblogic 12 的某些版本允许内部 SLF4j 绑定到 Log4j,但在其中一个次要版本中被删除。这是我的情况;我没有通过管理控制台启用 Log4j 作为 Weblogic 中的主要日志框架的选项。我很确定这对我没有帮助,但我确实想指出它,因为我阅读的几份文件表明这是可用的。
经过大量研究和使用 weblogic.xml 进行配置、POM 配置(排除等)并尝试使用不同的绑定和桥接后,我无法实现我想要的日志记录配置。似乎 Weblogic 的 slf4j 绑定到 Java 实用程序日志记录,无论好坏。如果您选择自己的 slf4j 和绑定实现(在我的情况下为 Logback),我无法通过配置将这些消息路由到 Weblogic 服务器日志。slf4j 中只能有一个绑定,虽然很多框架都可以路由到那个绑定,(我发现这个图有用)Weblogic 12.2.1 仅使用 Java util 日志绑定,没有办法(在应用程序配置级别)连接 Weblogic 以使用您提供的 Logback 绑定来记录到其服务器日志。可能有一些方法可以使用 log4j 和 bridges 来完成此任务,但对我来说,完成一个简单的日志记录任务完全过于臃肿和配置。
放弃尝试通过配置来解决这个问题,我决定简单地编写自己的 logback appender,将日志事件转换为 JUL 日志事件。我用我自己实现的 Logback 的 AppenderBase 替换了在许多 Logback 示例中看到的标准 STDOUT 定义。此时,我现在可以使用每个应用程序日志配置进行日志记录,也可以记录到 Weblogic Server 日志。
相关POM依赖:
<!-- 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(请注意,Hibernate 带有 JbossLogging,它会自动桥接到 slf4j)
<?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 实现
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 配置
<?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>
希望我可以为其他人节省一些我在尝试以我想要的方式工作时所经历的痛苦。