开发者社区> 问答> 正文

SLF4J-根据标签记录到不同的文件

我有一个要求,我需要创建日志文件,以使基于标签(最好是文本)的所有日志都需要记录到相应的日志文件中。

例如,

我有关于苹果,橙子和芒果的日志。

logger.info("Apples: They are red in color");
logger.info("Oranges: They are orange in color");
logger.info("Mangoes: They are yellowish in color");

按我的要求,第一个日志应记录到Apples.log,第二个Oranges.log和第三至Mangoes.log

日志文件应动态创建。

下面显示的是我的logback.xml文件

    <statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>
                %d %-5p - %marker%m%n
            </Pattern>
        </encoder>
    </appender>
  <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
    <discriminator>
      <key>fruitName</key>
      <defaultValue>Common_logs</defaultValue>
    </discriminator>
    <sift>
      <appender name="FILE-${instanceName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <fileNamePattern>./Logs/${fruitName}/${instanceName}.log</fileNamePattern>
            <maxHistory>50</maxHistory>
            <cleanHistoryOnStart>false</cleanHistoryOnStart>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d %-5p - %m%n</pattern>
        </encoder>
        </appender>
    </sift>
  </appender>

  <logger name="AssetInstanceService" level="info" additivity="false">
    <appender-ref ref="CONSOLE"/>
    <appender-ref ref="FILE"/>
    <appender-ref ref="SIFT" />
  </logger>

  <root level="info">
    <appender-ref ref="SIFT" />
    <appender-ref ref="CONSOLE"/>
    <appender-ref ref="FILE"/>
  </root>
</configuration>```
下面给出的是我的LogManager.java文件

package Data;

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC;

import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; import ch.qos.logback.core.joran.spi.JoranException;

public class LogManager {

static String configFile = "./logback.xml";

private static Logger _logger = LoggerFactory.getLogger(LogManager.class);
private static boolean _isInitialized = false;

private LogManager() {

}

public static Logger Instance() {
    if (_logger == null) {
        _logger = LoggerFactory.getLogger(LogManager.class);
    }
    return _logger;
}

public static Logger Instance(String instanceName) {
    if (!_isInitialized) {
        if (!CommonMethods.CheckFileExist(configFile)) {
            configFile = "../logback.xml";
            if (!CommonMethods.CheckFileExist(configFile)) {
                return null;
            }
        }
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        JoranConfigurator configurator = new JoranConfigurator();
        lc.reset();
        configurator.setContext(lc);
        try {
            configurator.doConfigure(configFile);
            MDC.put("fruitName", instanceName);
        } catch (JoranException e) {
            System.out.println(e);
        }
        _isInitialized = true;
    }
    if (_logger == null) {
        _logger = LoggerFactory.getLogger(LogManager.class);
    }
    return _logger;
}

}``` 在这里,当我在main方法中初始化记录器时,运行jar文件时会创建我的日志。

但是我需要根据日志中的标记或ID创建具有不同名称的不同日志文件。

问题来源:Stack Overflow

展开
收起
montos 2020-03-27 22:40:12 845 0
1 条回答
写回答
取消 提交回答
  • SLF4J和Log4j-API都提供了标记来执行您想要的操作。在SLF4J中,您可以使用以下方法创建标记:

    Marker apples = MarkerFactory.getMarker("Apples");
    Marker oranges = MarkerFactory.getMarker("Oranges");
    Marker mangos = MarkerFactory.getMarker("Mangos");
    

    此外,标记可以有一个父对象,因此您可以执行以下操作:

    Marker fruit = MarkerFactory.getMarker("Fruit");
    Marker apples = MarkerFactory.getMarker("Apples");
    apples.add(fruit);
    Marker oranges = MarkerFactory.getMarker("Oranges");
    apples.add(fruit);
    Marker mangos = MarkerFactory.getMarker("Mangos");
    apples.add(fruit);
    

    在配置中,您可以检查特定的标记,或者如果要检查所有水果标记,则可以检查该标记。

    然后,您可以在应用程序中将标记用作:

    logger.info(apples, "They are red in color");
    logger.info(oranges, "They are orange in color");
    logger.info(mangoes, "They are yellowish in color");
    

    最后,在您的配置中,您可以使用涡轮过滤器执行以下操作:

      <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
        <Marker>Apples</Marker>
        <OnMatch>NEUTRAL</OnMatch>
        <OnMismatch>DENY</OnMismatch>
      </turboFilter>
    

    可以在全局级别进行过滤,也可以使用评估程序过滤器之一在Appender上进行过滤。如果编写自定义鉴别器,也可以使用SiftingAppender动态创建Appender。

    使用Log4j API,事情变得容易一些。要创建没有父母的标记:

    Marker apples = MarkerManager.getMarker("Apples");
    Marker oranges = MarkerManager.getMarker("Oranges");
    Marker mangos = MarkerManager.getMarker("Mangos");
    

    或与父母:

    Marker fruit = MarkerManager.getMarker("Fruit");
    Marker apples = MarkerManager.getMarker("Apples").setParents(fruit);
    Marker oranges = MarkerManager.getMarker("Oranges").setParents(fruit);
    Marker mangos = MarkerManager.getMarker("Mangos").setParents(fruit);
    

    在Log4j中使用它们的代码完全相同:

    logger.info(apples, "They are red in color");
    logger.info(oranges, "They are orange in color");
    logger.info(mangoes, "They are yellowish in color");
    

    最大的区别在于配置。Log4j仅具有一种过滤器,并且可以在全局级别(例如涡轮过滤器),记录器,Appender引用或Appender上使用。在您的情况下,您想使用MarkerFilter

    并将其添加到每个Appender参考或每个Appender。

    与SiftingAppender相似,Log4j还提供了RoutingAppender。它使用查找来确定如何执行路由。Log4j不提供现成的功能来从log事件中检索数据,但是将一个简单的事件添加或添加到Log4j可能很简单,或者您可以使用脚本从事件中检索标记。

    您应该知道,使用MarkerFilters会有一些开销,尽管不多。这是在MacBook Pro上运行4个线程时log4j-perf模块的基准。即使在最坏的情况下,Logback会针对包含子标记的事件检查父标记,每个比较平均平均也仅需要17纳秒。

    Benchmark                                  Mode  Cnt   Score   Error  Units
    MarkerFilterBenchmark.baseline             avgt   10   2.412 ± 0.088  ns/op
    MarkerFilterBenchmark.log4jParentMarker    avgt   10   8.337 ± 0.186  ns/op
    MarkerFilterBenchmark.log4jSimpleMarker    avgt   10   8.043 ± 0.145  ns/op
    MarkerFilterBenchmark.log4jTooFine         avgt   10   2.825 ± 0.281  ns/op
    MarkerFilterBenchmark.logbackParentMarker  avgt   10  17.865 ± 0.533  ns/op
    MarkerFilterBenchmark.logbackSimpleMarker  avgt   10  10.471 ± 0.089  ns/op
    MarkerFilterBenchmark.logbackTooFine       avgt   10   4.255 ± 0.014  ns/op
    

    最后的想法。Ceki Gulcu在创建SLF4J时发明了Markers的概念,因此值得赞扬,因为这是一个了不起的主意。

    回答来源:Stack Overflow

    2020-03-27 22:42:07
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载