【问题标题】:Strange behaviors with Spring Boot and Log4J2Spring Boot 和 Log4J2 的奇怪行为
【发布时间】:2019-10-23 14:47:06
【问题描述】:

我在运行我的 Spring Boot 应用程序时遇到了一些奇怪的问题。它已被配置为使用 Log4J2 作为其记录器(Logback 记录器已被禁用)。

log4j2.xml:

<Configuration status="WARN" monitorInterval="30">
  <Properties>
    <Property name="serviceName">$${sys:service.name}</Property>
    <Property name="serviceId">$${sys:service.id}</Property>

    <Property name="LOG_PATTERN">
      [%d{yyyy-MM-dd HH:mm:ss.SSS}] %t %-5p: %c{2}:%L - %m%n
    </Property>

    <Property name="STATS_PATTERN">
      %m%n
    </Property>

    <Property name="logFile">logs/$${sys:service.name}-$${sys:service.id}</Property>
    <Property name="statsFile">metrics/$${sys:service.name}-$${sys:service.id}_stats.json</Property>
    <!--
    <Property name="logFile">logs/${serviceName}-${serviceId}</Property>
    <Property name="statsFile">metrics/${serviceName}-${serviceId}_stats.json</Property>
    -->
  </Properties>

  <Appenders>
    <Console name="ConsoleAppender" target="SYSTEM_OUT" follow="true">
      <PatternLayout pattern="${LOG_PATTERN}" />
    </Console>

    <RollingFile name="RollingFile" fileName="${logFile}.current-session.log"
      filePattern="${logFile}.%i.log.gz" ignoreExceptions="false">
      <PatternLayout>
        <Pattern>${LOG_PATTERN}</Pattern>
      </PatternLayout>
      <Policies>
        <OnStartupTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="10 MB" />
      </Policies>
      <DefaultRolloverStrategy max="10" />
    </RollingFile>

    <File name="StatsFile" fileName="${statsFile}" append="false">
      <PatternLayout>
        <Pattern>${STATS_PATTERN}</Pattern>
      </PatternLayout>
    </File>
  </Appenders>

  <Loggers>
    <Logger name="<package>.StatsWriter" level="info" additivity="false">
      <AppenderRef ref="StatsFile" />
    </Logger>

    <Root level="info">
      <AppenderRef ref="ConsoleAppender" />
    </Root>
  </Loggers>
</Configuration>

主要问题

我在 log4j2.xml 文件中有一些变量替换以允许变化,特别是日志文件名。当我运行应用程序时,日志文件会在正确的目录中创建,并且看起来确实有实际的日志内容。问题是它们的名称不正确。例如,文件名为 ${sys:service.name}-${sys:service.id}.current-session.log,而不是 Client-1.current-session.log。显然变量替换没有按计划进行。

属性service.nameservice.id 是当前在关联的application.yml 文件中定义的Spring Boot 配置参数。我原以为文件中的属性会可用,但显然不是这样。

有没有办法让 application.yml 属性在这里可用?如果这不可行,有什么其他方法可以做到这一点?

次要问题

当我在测试环境中执行应用程序时,我将记录器设置为输出到控制台:

<Root level="info">
  <AppenderRef ref="ConsoleAppender" />
</Root>

当它执行时,输出会显示在控制台上,但奇怪的是,还会创建日志文件。为什么会这样?

注意

有一个现有的 SO 项目 (Use Spring boot application properties in log4j2.xml)(这是第二个答案)可以解决这个问题,但它似乎(正如作者承认的那样)有点 hacky。我还没试过(还)。

我对 application-"profile".yml 和 log4j2-spring.xml 的引用有点困惑。我不熟悉这些文件名的这些变体。这些变体(两种文件类型)的意义是什么?

【问题讨论】:

    标签: java spring-boot log4j2


    【解决方案1】:

    对于您的主要问题,您的文件名是log4j2.xml,您应该改用log4j2-spring.xml,因为这样可以让Spring Boot 更好地控制Log4j2。

    其中一个好处是可以整合您缺少的变量。这可能是由于使用log4j2.xml 文件使 log4j2 在 Spring Boot 之前初始化,而使用 log4j2-spring.xml 使 Spring Boot 初始化 log4j2。

    正如SpringBoot documentation 所说:

    如果可能,我们建议您在日志配置中使用 -spring 变体(例如,logback-spring.xml 而不是 logback.xml)。如果使用标准配置位置,Spring 无法完全控制日志初始化。

    您可以查看this thread 由要求log4j2.xmllog4j2-spring.xml 的人打开

    对于您的第二个问题,因为您有 2 个记录器......就是这样:

      <Loggers>
        <Logger name="<package>.StatsWriter" level="info" additivity="false">
          <AppenderRef ref="StatsFile" />   <---- This one creates your file
        </Logger>
    
        <Root level="info">
          <AppenderRef ref="ConsoleAppender" />
        </Root>
      </Loggers>
    

    关于你的第三个问题

    我对 application-"profile".yml 和 log4j2-spring.xml 的引用有点困惑。我不熟悉这些文件名的这些变体。这些变体(两种文件类型)的意义是什么?

    application-"profile".xxx 的变体是一种允许 Spring Boot 基于这些配置文件采用不同配置的方式。您可以使用“dev”参数(本地开发数据库)启动您的应用程序,但在生产中您可以使用不同的参数。您可以通过不同的方式控制如何引导不同的配置文件,一种很常见的方式是执行您的应用程序,例如java -jar -Dspring.profiles.active=prod application.jar

    log4j2-spring.xml 相关,如上所述,以允许 Spring Boot 正确初始化 log4j2(或您使用的任何日志记录工具)。

    【讨论】:

    • 你回答了我的第二个问题 - 我知道我也会得到“stats”文件,但我不明白为什么我也会得到包含控制台的日志文件输出。我没有使用 RollingFile appender 指定记录器。
    • @JosephGagnon 我可以看到您应该有 2 个日志文件和控制台。如果您实际上有 3 个文件,那么您应该打开一个新问题,提供仅与您的日志记录配置相关的详细信息。这种方式更容易跟踪问题/答案。但是,您是否搬到log4j2-spring.xml 这是必须的。
    • 接下来我将尝试使用 log4j2-spring.xml。
    • @JosephGagnon 我建议您,如果您的主要问题已解决,则将此问题标记为已回答并为每个特定问题打开一个新问题。社区不会一直在同一个线程中提出多个不同的问题。
    • @JosephGagnon 我注意到的另一件事是您正在使用$${sys:service.name},其中$$ 正在转义美元符号。您可以尝试仅使用 ${sys:service.name} 吗?我认为使用-spring.xml 后缀加上一个$ 符号应该可以解决主要问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2017-01-23
    • 2016-02-18
    • 1970-01-01
    • 2020-12-25
    • 2012-05-31
    • 1970-01-01
    相关资源
    最近更新 更多