Jetty 9.1+:如何使用 log4j/slf4j 获取我的 webapp 日志
Jetty 9.1+: how to get my webapp logs with log4j/slf4j
我在 ${jetty.base}
中的 Jetty 9.3.6 上有一个 Web 应用程序 运行,它设置为 /opt/mybase/
。我的 webapp 使用 slf4j
而我使用 log4j
作为实际的日志框架,所以我的 webapp 源代码中的日志语句如下所示:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SillyClass
{
private static final Logger log = LoggerFactory.getLogger (SillyClass.class.getName ());
...
public static void foo ()
{
if (error ())
{
log.error ("ERROR");
}
else
{
log.info ("NOT an error");
}
}
...
}
在我的 gradle 构建文件中,我这样做了:
dependencies {
...
compile 'org.slf4j:slf4j-api:1.7.12'
compile 'org.slf4j:slf4j-log4j12:1.7.12'
compile 'log4j:log4j:1.2.17'
...
}
此配置对于使用相同日志框架的另一个(非 Jetty、非 Web 应用程序)Java 项目非常有效;我可以用${project.home}/src/main/resources/log4j.properties
来控制日志的输出。
无论如何,当我搬到 Jetty 时,我按照说明进行了操作 here to the dot; but as soon as I did that, I hit the multiple-bindings error。为了纠正这个问题,我删除了 gradle 构建文件中的 slf4j
引用,但这导致了错误:
java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/eclipse/jetty/start/Classpath$Loader) for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
然后我删除了所有对 slf4j
和 log4j
的引用(注释掉了我在上面的 build.gradle
中显示的三行),但我看到的错误仍然相同。我究竟做错了什么?
我的 /opt/mybase/resources/log4j.properties
文件:
log4j.rootLogger=TRACE, FILE
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=/opt/mybase/logs/jetty.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern= %d{dd MMM yyyy HH:mm:ss.SSS} %l %m%n
感谢任何帮助。
好吧,这对我来说是一个真正令人尴尬的错误。我相信,主要问题不是 log4j
或 slf4j
或码头配置。我认为这很好用。此外,尽管有多个绑定,码头服务器实际上选择了码头日志中显示的某些东西:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/tmp/jetty-0.0.0.0-443-webapp.war-_webapp-any-8458003046853847474.dir/webapp/WEB-INF/lib/slf4j-log4j12- 1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/mybase/webapp/lib/logging/slf4j-log4j12- 1.6.6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
此外,如果依赖项内置了日志记录,那你就倒霉了,这取决于维护得有多好,我想你无论如何都会发生冲突。至少,我知道在那种情况下没有办法阻止这种情况。
嗯,真正的问题是 webapp 没有自己的 log4j.properties
(如果您使用的是 gradle,这将在 $(projectHome)/src/main/resources/log4j.properties)
中)。我将其添加到我的项目和我的日志记录更有意义(即,我在 /opt/mybase/logs/my-silly-webapp-log.txt
中看到它应该在的位置)。
最后,我报告的崩溃是无关的(在 12 月 29 日的评论中)并且与 Jetty 9.3.6 错误有关,它似乎尚未解决,尽管在 Jetty 错误数据库中被称为已解决对于 9.3.6。让我失望的是日志在我最初报告的 multiple_bindings
错误之后立即出现。看来,它们没有关系。当我写这篇文章时,我无法在 Jetty 错误数据库中找到确切的错误,但我最后一次检查那个错误(大约一周前),问题是 Jetty log4j.properties
(在 /opt/mybase/resources/log4j.properties
中)已将 rootLogger
设置为 DEBUG
(从对该错误的评论中获取)。当我在 Jetty log4j.properties
中的 rootLogger
设置为 DEBUG
时,我能够重现错误(websocket 应用程序本身工作正常,尽管 Jetty 日志相关崩溃)。通过将 Jetty log4j.properties
的 rootLogger
移动到 INFO 或更低级别,我可以确认问题已经解决。我会在 Jetty 的 bug DB 中提出它。
希望这对某人有所帮助。
我在 ${jetty.base}
中的 Jetty 9.3.6 上有一个 Web 应用程序 运行,它设置为 /opt/mybase/
。我的 webapp 使用 slf4j
而我使用 log4j
作为实际的日志框架,所以我的 webapp 源代码中的日志语句如下所示:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SillyClass
{
private static final Logger log = LoggerFactory.getLogger (SillyClass.class.getName ());
...
public static void foo ()
{
if (error ())
{
log.error ("ERROR");
}
else
{
log.info ("NOT an error");
}
}
...
}
在我的 gradle 构建文件中,我这样做了:
dependencies {
...
compile 'org.slf4j:slf4j-api:1.7.12'
compile 'org.slf4j:slf4j-log4j12:1.7.12'
compile 'log4j:log4j:1.2.17'
...
}
此配置对于使用相同日志框架的另一个(非 Jetty、非 Web 应用程序)Java 项目非常有效;我可以用${project.home}/src/main/resources/log4j.properties
来控制日志的输出。
无论如何,当我搬到 Jetty 时,我按照说明进行了操作 here to the dot; but as soon as I did that, I hit the multiple-bindings error。为了纠正这个问题,我删除了 gradle 构建文件中的 slf4j
引用,但这导致了错误:
java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/eclipse/jetty/start/Classpath$Loader) for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
然后我删除了所有对 slf4j
和 log4j
的引用(注释掉了我在上面的 build.gradle
中显示的三行),但我看到的错误仍然相同。我究竟做错了什么?
我的 /opt/mybase/resources/log4j.properties
文件:
log4j.rootLogger=TRACE, FILE
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=/opt/mybase/logs/jetty.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern= %d{dd MMM yyyy HH:mm:ss.SSS} %l %m%n
感谢任何帮助。
好吧,这对我来说是一个真正令人尴尬的错误。我相信,主要问题不是 log4j
或 slf4j
或码头配置。我认为这很好用。此外,尽管有多个绑定,码头服务器实际上选择了码头日志中显示的某些东西:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/tmp/jetty-0.0.0.0-443-webapp.war-_webapp-any-8458003046853847474.dir/webapp/WEB-INF/lib/slf4j-log4j12- 1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/mybase/webapp/lib/logging/slf4j-log4j12- 1.6.6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
此外,如果依赖项内置了日志记录,那你就倒霉了,这取决于维护得有多好,我想你无论如何都会发生冲突。至少,我知道在那种情况下没有办法阻止这种情况。
嗯,真正的问题是 webapp 没有自己的 log4j.properties
(如果您使用的是 gradle,这将在 $(projectHome)/src/main/resources/log4j.properties)
中)。我将其添加到我的项目和我的日志记录更有意义(即,我在 /opt/mybase/logs/my-silly-webapp-log.txt
中看到它应该在的位置)。
最后,我报告的崩溃是无关的(在 12 月 29 日的评论中)并且与 Jetty 9.3.6 错误有关,它似乎尚未解决,尽管在 Jetty 错误数据库中被称为已解决对于 9.3.6。让我失望的是日志在我最初报告的 multiple_bindings
错误之后立即出现。看来,它们没有关系。当我写这篇文章时,我无法在 Jetty 错误数据库中找到确切的错误,但我最后一次检查那个错误(大约一周前),问题是 Jetty log4j.properties
(在 /opt/mybase/resources/log4j.properties
中)已将 rootLogger
设置为 DEBUG
(从对该错误的评论中获取)。当我在 Jetty log4j.properties
中的 rootLogger
设置为 DEBUG
时,我能够重现错误(websocket 应用程序本身工作正常,尽管 Jetty 日志相关崩溃)。通过将 Jetty log4j.properties
的 rootLogger
移动到 INFO 或更低级别,我可以确认问题已经解决。我会在 Jetty 的 bug DB 中提出它。
希望这对某人有所帮助。