根据父上下文记录到不同的文件
Logging to different files following parent context
我有一个使用 Spring Boot 构建的后台 Java 应用程序,我使用 SLF4J 进行日志记录(必需)。该应用程序包含多个定期 运行 的作业。
我想在单独的文件中记录每项工作期间发生的所有事情。这将为我提供每个作业一个日志文件,以及一个用于应用程序启动和诸如此类的一般日志文件。
当涉及到工作的主要 class 时,这是一项简单的任务,因为我需要做的就是按名称检索我感兴趣的记录器:
public class SchedulerOne extends Runnable {
@Autowired
private CommonDao commonDao;
private static final Logger LOGGER = LoggerFactory.getLogger("logger_one");
...
}
但棘手的部分是让不同作业调用的公共资源记录到正确的文件中。
public class CommonDao {
private static final Logger LOGGER = LoggerFactory.getLogger(CommonDao.class);
...
}
我想要的:当SchedulerOne调用CommonDao的任何一个方法时,后续的日志应该出现在"logger_one"中。当 SchedulerTwo 调用相同的方法时,日志应该出现在 "logger_two".
中
当前发生的情况:CommonDao 忽略上下文,只写入默认日志文件。
我能找到的关于该主题的唯一资源是 logback 文档 (https://logback.qos.ch/manual/loggingSeparation.html),它使用 ContextJNDISelector 在记录时 select 适当的上下文。这看起来像我的目标,但这些说明针对的是包含多个 Web 应用程序的应用程序。我只有一个应用程序没有 web.xml,所以这似乎不适用。
我目前的logback配置如下:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logger_default.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<FileNamePattern>c:/jcg.%i.log.zip</FileNamePattern>
<MinIndex>1</MinIndex>
<MaxIndex>10</MaxIndex>
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>2MB</MaxFileSize>
</triggeringPolicy>
</appender>
<appender name="SCHEDULER_ONE" class="ch.qos.logback.core.FileAppender">
<file>scheduler_one.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<logger name="logger_one" level="DEBUG" additivity="false">
<appender-ref ref="SCHEDULER_ONE"/>
</logger>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
您需要像 here 中描述的那样将 MDC 与 SiftingAppender 结合起来,例如:
<configuration>
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<defaultValue>default</defaultValue>
<key>context</key>
</discriminator>
<sift>
<appender name="FILE-${context}" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logger_${context}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<FileNamePattern>c:/jcg_${context}.%i.log.zip</FileNamePattern>
<MinIndex>1</MinIndex>
<MaxIndex>10</MaxIndex>
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>2MB</MaxFileSize>
</triggeringPolicy>
</appender>
</sift>
</appender>
<logger name="logger_one" level="DEBUG" additivity="false">
<appender-ref ref="SIFT"/>
</logger>
<root level="DEBUG">
<appender-ref ref="SIFT" />
</root>
</configuration>
然后在 SchedulerOne 中执行 MDC.put("context", "one")
,在 SchedulerTwo 中执行 MDC.put("context", "two")
。
而不是让 CommonDao
有一个单一的静态记录器,您可以传入记录器以将其用作参数,在您调用它的每个方法中或让每个作业创建自己的实例class 并传递记录器以用作构造函数。
这有点不合常规,但如果您希望记录员根据他们 运行 的工作而不是 class 所从事的工作来命名,那么这对我来说很有意义让记录器由他们 运行 的工作创建和维护,而不仅仅是他们所在的 class。
我有一个使用 Spring Boot 构建的后台 Java 应用程序,我使用 SLF4J 进行日志记录(必需)。该应用程序包含多个定期 运行 的作业。
我想在单独的文件中记录每项工作期间发生的所有事情。这将为我提供每个作业一个日志文件,以及一个用于应用程序启动和诸如此类的一般日志文件。
当涉及到工作的主要 class 时,这是一项简单的任务,因为我需要做的就是按名称检索我感兴趣的记录器:
public class SchedulerOne extends Runnable {
@Autowired
private CommonDao commonDao;
private static final Logger LOGGER = LoggerFactory.getLogger("logger_one");
...
}
但棘手的部分是让不同作业调用的公共资源记录到正确的文件中。
public class CommonDao {
private static final Logger LOGGER = LoggerFactory.getLogger(CommonDao.class);
...
}
我想要的:当SchedulerOne调用CommonDao的任何一个方法时,后续的日志应该出现在"logger_one"中。当 SchedulerTwo 调用相同的方法时,日志应该出现在 "logger_two".
中当前发生的情况:CommonDao 忽略上下文,只写入默认日志文件。
我能找到的关于该主题的唯一资源是 logback 文档 (https://logback.qos.ch/manual/loggingSeparation.html),它使用 ContextJNDISelector 在记录时 select 适当的上下文。这看起来像我的目标,但这些说明针对的是包含多个 Web 应用程序的应用程序。我只有一个应用程序没有 web.xml,所以这似乎不适用。
我目前的logback配置如下:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logger_default.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<FileNamePattern>c:/jcg.%i.log.zip</FileNamePattern>
<MinIndex>1</MinIndex>
<MaxIndex>10</MaxIndex>
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>2MB</MaxFileSize>
</triggeringPolicy>
</appender>
<appender name="SCHEDULER_ONE" class="ch.qos.logback.core.FileAppender">
<file>scheduler_one.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<logger name="logger_one" level="DEBUG" additivity="false">
<appender-ref ref="SCHEDULER_ONE"/>
</logger>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
您需要像 here 中描述的那样将 MDC 与 SiftingAppender 结合起来,例如:
<configuration>
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<defaultValue>default</defaultValue>
<key>context</key>
</discriminator>
<sift>
<appender name="FILE-${context}" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logger_${context}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<FileNamePattern>c:/jcg_${context}.%i.log.zip</FileNamePattern>
<MinIndex>1</MinIndex>
<MaxIndex>10</MaxIndex>
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>2MB</MaxFileSize>
</triggeringPolicy>
</appender>
</sift>
</appender>
<logger name="logger_one" level="DEBUG" additivity="false">
<appender-ref ref="SIFT"/>
</logger>
<root level="DEBUG">
<appender-ref ref="SIFT" />
</root>
</configuration>
然后在 SchedulerOne 中执行 MDC.put("context", "one")
,在 SchedulerTwo 中执行 MDC.put("context", "two")
。
而不是让 CommonDao
有一个单一的静态记录器,您可以传入记录器以将其用作参数,在您调用它的每个方法中或让每个作业创建自己的实例class 并传递记录器以用作构造函数。
这有点不合常规,但如果您希望记录员根据他们 运行 的工作而不是 class 所从事的工作来命名,那么这对我来说很有意义让记录器由他们 运行 的工作创建和维护,而不仅仅是他们所在的 class。