重新部署后log4j不记录
log4j don't log after redeploy
我们在 catalina
基目录下有 log4j2.xml
的通用配置。所以 webapps
下的所有模块都使用这个配置。 log4j-core
、log4j-web
和 log4j-api
库位于 tomcat 的共享库下。当我们重新启动 tomcat 时,所有模块都写入了它们的日志。但是,当重新部署其中任何一个时,只有该模块不会记录其他模块。例如,我们在 webapps 文件夹下有 A
、B
和 C
模块。如果我们在重启后重新部署 C
模块,那么我们只会看到 C
模块日志。我怎么解决这个问题?我找不到发生这种情况的任何原因
我启用了 log4j
日志以查看发生了什么。重新部署后log4j
打印这种日志
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02,component=StatusLogger
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02,component=ContextSelector
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02,component=Loggers,name=
457e2f02
这应该是我们的模块名称但是为什么 log4j
打印随机文本
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG" monitoring="10">
<Properties>
<Property name="log.level">ALL</Property>
<Property name="framework.log.level">WARN</Property>
<Property name="file.pattern">%d{DEFAULT}: [%level{WARN=WAR, DEBUG=DBG, ERROR=ERR, TRACE=TRC, INFO=INF, FATAL=FTL}] %-c.%M[%L] - %m%n</Property>
<Property name="console.pattern">%highlight{%d{DEFAULT}: [%level{WARN=WAR, DEBUG=DBG, ERROR=ERR, TRACE=TRC, INFO=INF, FATAL=FTL}] %-c.%M[%L] - %m%n \n}{FATAL=red blink, ERROR=red bold, WARN=yellow bold, INFO=green bold, DEBUG=white bold, TRACE=cyan}</Property>
<Property name="logs.dir">logs</Property>
<Property name="app.name">magus</Property>
<Property name="script.test.mode">false</Property>
</Properties>
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="${console.pattern}"/>
</Console>
<Socket name="GELF" protocol="tcp" host="graylog.host" port="12201">
<!-- gelf tcp does not support compression-->
<GelfLayout includeStackTrace="true" host="${hostName}" includeThreadContext="true" includeNullDelimiter="true"
compressionType="OFF">
<KeyValuePair key="host" value="${hostName}"/>
<KeyValuePair key="version" value="1.1"/>
<!--<KeyValuePair key="short_message" value="$${event:Message}"/>--><!-- not required -->
<!--<KeyValuePair key="application_name" value="$${ctx:application}"/>-->
<KeyValuePair key="thread_id" value="$${event:ThreadId}"/>
<KeyValuePair key="thread_name" value="$${event:ThreadName}"/>
<KeyValuePair key="timestamp" value="$${event:Timestamp}"/>
<!--<KeyValuePair key="level" value="1"/>--><!-- default level type is number so we don't use-->
<KeyValuePair key="log_level" value="$${event:Level}"/><!-- for readabilty and filtering-->
</GelfLayout>
</Socket>
<RollingFile name="LOG" fileName="${logs.dir}/${app.name}.log"
filePattern="${logs.dir}/$${date:yyyy-MM}/${app.name}-%d{yyyy-MM-dd}.log.gz">
<PatternLayout pattern="${file.pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
</Policies>
<DefaultRolloverStrategy max="3">
<!--
Nested conditions: the inner condition is only evaluated on files
for which the outer conditions are true.
-->
<Delete basePath="${logs.dir}" maxDepth="2" testMode="${script.test.mode}">
<IfFileName glob="*/${app.name}*.log.gz">
<IfLastModified age="90d">
<IfAny>
<IfAccumulatedFileCount exceeds="10"/>
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="LOG"/>
<AppenderRef ref='GELF' />
</Root>
<Logger name="xxx.project" level="${log.level}"/>
<Logger name="org.hibernate" level="${framework.log.level}"/>
<Logger name="com.zaxxer" level="${framework.log.level}"/>
<!--<Logger name="org.hibernate" level="ALL"/>-->
<Logger name="org.reflections" level="OFF"/>
<!-- show executed queries -->
<!--<Logger name="org.hibernate.SQL" level="DEBUG"/>-->
<!-- show query params -->
<!--
<Logger name="org.hibernate.type.descriptor.sql" level="TRACE"/> -->
<!--
<AsyncLogger name="az.sanco.projects.ais.server.filter" additivity="false" level="${log.level}">
<AppenderRef ref="AUDITOR"/>
</AsyncLogger> -->
</Loggers>
</Configuration>
Tomcat版本:9.0
Java版本:1.8
log4j2 版本:2.14.0
您的 LoggerContext
suggests that all your applications are using a single context. When one of your applications is stopped, the stop
方法的随机名称 457e2f02
已在上下文中调用,无法记录更多消息。同时,重新加载的应用程序会为自己创建一个上下文。
如果您直接在您的应用程序中使用 Log4j API,但您没有使用 log4j-api
的副本发布应用程序,则可能会发生这种情况:在这种情况下 LogManager
class 共享 Tomcat classloader 将被所有应用程序使用。
尝试将 log4j-api.jar
添加到您的应用程序中。
实际上@PiotrP.Karwasz 的回答解决了 log4j
的问题。但是不要解决我们的问题。如果我们应用他的答案,那么我们应该将所有 log4j-core
、log4j-api
和 log4j-web
jar 移动到我们的每个应用程序 WEB-INF\lib
文件夹,这不是有效的方法。因为我们有将近 20 个模块,在这种情况下我们将 jar 复制到所有这些模块并占用更多资源。根据 log seperation 文档,我们不应该为此要求做任何进一步的配置。 Log4j 上下文选择器应该为每个 war
模块选择上下文自动。但在实践中我们发现它不能正常工作。可能是错误,也可能是我们没有正确配置。我从文档中选择了第三个选项 org.apache.logging.log4j.core.selector.JndiContextSelector
。这解决了我们的问题。我们将 log4j-core
、log4j-api
和 log4j-web
jar 保存在公共路径中,并且我们的每个模块都使用这些 jar。现在,当我们重新部署我们的模块之一时,log4j
可以正常工作。
我们在 catalina
基目录下有 log4j2.xml
的通用配置。所以 webapps
下的所有模块都使用这个配置。 log4j-core
、log4j-web
和 log4j-api
库位于 tomcat 的共享库下。当我们重新启动 tomcat 时,所有模块都写入了它们的日志。但是,当重新部署其中任何一个时,只有该模块不会记录其他模块。例如,我们在 webapps 文件夹下有 A
、B
和 C
模块。如果我们在重启后重新部署 C
模块,那么我们只会看到 C
模块日志。我怎么解决这个问题?我找不到发生这种情况的任何原因
我启用了 log4j
日志以查看发生了什么。重新部署后log4j
打印这种日志
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02,component=StatusLogger
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02,component=ContextSelector
2021-04-13 17:40:56,930 Catalina-utility-1 DEBUG Registering MBean org.apache.logging.log4j2:type=457e2f02,component=Loggers,name=
457e2f02
这应该是我们的模块名称但是为什么 log4j
打印随机文本
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG" monitoring="10">
<Properties>
<Property name="log.level">ALL</Property>
<Property name="framework.log.level">WARN</Property>
<Property name="file.pattern">%d{DEFAULT}: [%level{WARN=WAR, DEBUG=DBG, ERROR=ERR, TRACE=TRC, INFO=INF, FATAL=FTL}] %-c.%M[%L] - %m%n</Property>
<Property name="console.pattern">%highlight{%d{DEFAULT}: [%level{WARN=WAR, DEBUG=DBG, ERROR=ERR, TRACE=TRC, INFO=INF, FATAL=FTL}] %-c.%M[%L] - %m%n \n}{FATAL=red blink, ERROR=red bold, WARN=yellow bold, INFO=green bold, DEBUG=white bold, TRACE=cyan}</Property>
<Property name="logs.dir">logs</Property>
<Property name="app.name">magus</Property>
<Property name="script.test.mode">false</Property>
</Properties>
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="${console.pattern}"/>
</Console>
<Socket name="GELF" protocol="tcp" host="graylog.host" port="12201">
<!-- gelf tcp does not support compression-->
<GelfLayout includeStackTrace="true" host="${hostName}" includeThreadContext="true" includeNullDelimiter="true"
compressionType="OFF">
<KeyValuePair key="host" value="${hostName}"/>
<KeyValuePair key="version" value="1.1"/>
<!--<KeyValuePair key="short_message" value="$${event:Message}"/>--><!-- not required -->
<!--<KeyValuePair key="application_name" value="$${ctx:application}"/>-->
<KeyValuePair key="thread_id" value="$${event:ThreadId}"/>
<KeyValuePair key="thread_name" value="$${event:ThreadName}"/>
<KeyValuePair key="timestamp" value="$${event:Timestamp}"/>
<!--<KeyValuePair key="level" value="1"/>--><!-- default level type is number so we don't use-->
<KeyValuePair key="log_level" value="$${event:Level}"/><!-- for readabilty and filtering-->
</GelfLayout>
</Socket>
<RollingFile name="LOG" fileName="${logs.dir}/${app.name}.log"
filePattern="${logs.dir}/$${date:yyyy-MM}/${app.name}-%d{yyyy-MM-dd}.log.gz">
<PatternLayout pattern="${file.pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
</Policies>
<DefaultRolloverStrategy max="3">
<!--
Nested conditions: the inner condition is only evaluated on files
for which the outer conditions are true.
-->
<Delete basePath="${logs.dir}" maxDepth="2" testMode="${script.test.mode}">
<IfFileName glob="*/${app.name}*.log.gz">
<IfLastModified age="90d">
<IfAny>
<IfAccumulatedFileCount exceeds="10"/>
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="LOG"/>
<AppenderRef ref='GELF' />
</Root>
<Logger name="xxx.project" level="${log.level}"/>
<Logger name="org.hibernate" level="${framework.log.level}"/>
<Logger name="com.zaxxer" level="${framework.log.level}"/>
<!--<Logger name="org.hibernate" level="ALL"/>-->
<Logger name="org.reflections" level="OFF"/>
<!-- show executed queries -->
<!--<Logger name="org.hibernate.SQL" level="DEBUG"/>-->
<!-- show query params -->
<!--
<Logger name="org.hibernate.type.descriptor.sql" level="TRACE"/> -->
<!--
<AsyncLogger name="az.sanco.projects.ais.server.filter" additivity="false" level="${log.level}">
<AppenderRef ref="AUDITOR"/>
</AsyncLogger> -->
</Loggers>
</Configuration>
Tomcat版本:9.0
Java版本:1.8
log4j2 版本:2.14.0
您的 LoggerContext
suggests that all your applications are using a single context. When one of your applications is stopped, the stop
方法的随机名称 457e2f02
已在上下文中调用,无法记录更多消息。同时,重新加载的应用程序会为自己创建一个上下文。
如果您直接在您的应用程序中使用 Log4j API,但您没有使用 log4j-api
的副本发布应用程序,则可能会发生这种情况:在这种情况下 LogManager
class 共享 Tomcat classloader 将被所有应用程序使用。
尝试将 log4j-api.jar
添加到您的应用程序中。
实际上@PiotrP.Karwasz 的回答解决了 log4j
的问题。但是不要解决我们的问题。如果我们应用他的答案,那么我们应该将所有 log4j-core
、log4j-api
和 log4j-web
jar 移动到我们的每个应用程序 WEB-INF\lib
文件夹,这不是有效的方法。因为我们有将近 20 个模块,在这种情况下我们将 jar 复制到所有这些模块并占用更多资源。根据 log seperation 文档,我们不应该为此要求做任何进一步的配置。 Log4j 上下文选择器应该为每个 war
模块选择上下文自动。但在实践中我们发现它不能正常工作。可能是错误,也可能是我们没有正确配置。我从文档中选择了第三个选项 org.apache.logging.log4j.core.selector.JndiContextSelector
。这解决了我们的问题。我们将 log4j-core
、log4j-api
和 log4j-web
jar 保存在公共路径中,并且我们的每个模块都使用这些 jar。现在,当我们重新部署我们的模块之一时,log4j
可以正常工作。