我有一个要求,我需要创建日志文件,以使基于标签(最好是文本)的所有日志都需要记录到相应的日志文件中。
例如,
我有关于苹果,橙子和芒果的日志。
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
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
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。