我正在学习log4j2。我尝试编写一个在xml配置文件中定义的自定义级别过滤器的示例。
由于某些原因,它们似乎未被识别。
log4j2 xml配置文件
log4j2_config_20_Filters_LevelFilter_Custom.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<CustomLevels>
<CustomLevel name="level350" intLevel="350"/>
<CustomLevel name="level450" intLevel="450"/>
<CustomLevel name="level550" intLevel="550"/>
</CustomLevels>
<Appenders>
<Console name="appender1" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="[%date]('%logger'-'%level') %msg\n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="logger1_level350" level="level350" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger1_level450" level="level450" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger1_level550" level="level550" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
</Loggers>
</Configuration>
一种用于打印已识别级别的实用程序方法。
public static List<String> getLog4j2LevelsDescriptionsList() {
final List<Level> sortedLevels = Arrays.stream(Level.values()).sorted(Comparator.comparingInt(Level::intLevel)).collect(Collectors.toList());
final List<String> levelsDescriptionList = new ArrayList<>();
int maxNameLength = 5;
for (Level sortedLevel : sortedLevels) {
final int currentLength = sortedLevel.name().length();
if (currentLength > maxNameLength) maxNameLength = currentLength;
}
for (Level level : sortedLevels) {
levelsDescriptionList.add(String.format("%-" + maxNameLength + "S : %d", level.name(), level.intLevel()));
}
return levelsDescriptionList;
}
测试
@Test
public void test_CustomLevels_DeclaredIn_ConfigFile() {
setLog4j2ConfigFile("log4j2_config_20_Filters_LevelFilter_Custom.xml");
final Level level350 = Level.getLevel("level350");
// Level.forName("level350", 350);
// Level.forName("level450", 450);
// Level.forName("level550", 550);
for (String s : getLog4j2LevelsDescriptionsList()) {
System.out.println(s);
}
System.out.println();
final Logger loggers[] = {
LogManager.getLogger("logger1_level350"),
LogManager.getLogger("logger1_level450"),
LogManager.getLogger("logger1_level550")
};
for (Logger logger : loggers) {
logger.fatal("This is a fatal message");
logger.error("This is an error message");
logger.warn("This is a warning message");
logger.info("This is an info message");
logger.debug("This is a debug message");
logger.trace("This is a trace message");
System.out.println();
}
}
输出
OFF : 0
FATAL : 100
ERROR : 200
WARN : 300
INFO : 400
DEBUG : 500
TRACE : 600
ALL : 2147483647
[2018-07-20 06:04:20,819]('logger1_level350'-'FATAL') This is a fatal message
[2018-07-20 06:04:20,821]('logger1_level350'-'ERROR') This is an error message
[2018-07-20 06:04:20,821]('logger1_level450'-'FATAL') This is a fatal message
[2018-07-20 06:04:20,821]('logger1_level450'-'ERROR') This is an error message
[2018-07-20 06:04:20,821]('logger1_level550'-'FATAL') This is a fatal message
[2018-07-20 06:04:20,821]('logger1_level550'-'ERROR') This is an error message
为什么不能识别自定义级别? 我希望可以识别自定义级别。并根据其intLevel将记录的事件“追加”。
答案 0 :(得分:0)
log4j2_config_20_2_Filters_LevelFilter_Custom_OverridingCustomLevels.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<CustomLevels>
<CustomLevel name="ALL_CAPS_CONFIG_FILE_ONLY_LOGGER_LEVEL_310" intLevel="310"/>
</CustomLevels>
<CustomLevels>
<CustomLevel name="all_small_config_file_only_logger_level_320" intLevel="320"/>
</CustomLevels>
<CustomLevels>
<CustomLevel name="ALL_CAPS_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_350" intLevel="350"/>
</CustomLevels>
<CustomLevels>
<CustomLevel name="all_small_config_file_only_appender_ref_level_360" intLevel="360"/>
</CustomLevels>
<CustomLevels>
<CustomLevel name="ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370" intLevel="370"/>
</CustomLevels>
<Appenders>
<Console name="appender1" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="[%date]('%logger'-'%level') %msg\n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="logger1" level="ALL_CAPS_CONFIG_FILE_ONLY_LOGGER_LEVEL_310" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger2" level="all_small_config_file_only_logger_level_320" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger3" level="ALL_SMALL_CONFIG_FILE_ONLY_LOGGER_LEVEL_320" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger4" additivity="false">
<AppenderRef ref="appender1" level="ALL_CAPS_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_350"/>
</Logger>
<Logger name="logger5" additivity="false">
<AppenderRef ref="appender1" level="all_small_config_file_only_appender_ref_level_360"/>
</Logger>
<Logger name="logger6" additivity="false">
<AppenderRef ref="appender1" level="ALL_SMALL_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_320"/>
</Logger>
<Logger name="logger7" level="ALL_CAPS_JAVA_ONLY_LEVEL_330" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger8" level="all_small_java_only_level_340" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
<Logger name="logger9" level="ALL_SMALL_JAVA_ONLY_LEVEL_340" additivity="false">
<AppenderRef ref="appender1"/>
</Logger>
</Loggers>
</Configuration>
JUnit test
/*
* If you register a level in the config file, make sure to call at least one logger before attempting to obtain the level's instance.
* Make sure that the level's name is in capital letters only.
* */
@Test
public void test_CustomLevels_RegisteringCustomLevelsInConfigFileAndJava_Testing() {
setLog4j2ConfigFile("log4j2_config_20_1_Filters_LevelFilter_Custom_RegisteringCustomLevels_test.xml");
Level.forName("ALL_CAPS_JAVA_ONLY_LEVEL_330", 330);
Level.forName("all_small_java_only_level_340", 340);
printLevels("Before calling loggers");
LogManager.getLogger("logger1"); /*LogManager.getRootLogger();*//*Same effect*/
printLevels("After calling logger1 only");
System.out.println("Level.getLevel(\"ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370\") = " + Level.getLevel("ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370"));
final Logger[] loggers = {
LogManager.getLogger("logger1"),
LogManager.getLogger("logger2"),
LogManager.getLogger("logger3"),
LogManager.getLogger("logger4"),
LogManager.getLogger("logger5"),
LogManager.getLogger("logger6"),
LogManager.getLogger("logger7"),
LogManager.getLogger("logger8"),
LogManager.getLogger("logger9")
};
printLoggersAndTheirLevels(loggers);
printLevels("After calling loggers");
}
我没有得到官方支持的答案。但是根据以前的测试,必须满足两个条件,才能使用在配置文件中定义/声明的级别。
LogManager.getLogger("logger_name")
或LogManager.getRootLevel()
),才能在Java代码中注册和使用所有级别。记录器必须在尝试使用任何config-file-defined-level-filters 输出
Before calling loggers
OFF : 0
FATAL : 100
ERROR : 200
WARN : 300
ALL_CAPS_JAVA_ONLY_LEVEL_330 : 330
ALL_SMALL_JAVA_ONLY_LEVEL_340 : 340
INFO : 400
DEBUG : 500
TRACE : 600
ALL : 2147483647
After calling logger1 only
OFF : 0
FATAL : 100
ERROR : 200
WARN : 300
ALL_CAPS_CONFIG_FILE_ONLY_LOGGER_LEVEL_310 : 310
ALL_SMALL_CONFIG_FILE_ONLY_LOGGER_LEVEL_320 : 320
ALL_CAPS_JAVA_ONLY_LEVEL_330 : 330
ALL_SMALL_JAVA_ONLY_LEVEL_340 : 340
ALL_CAPS_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_350 : 350
ALL_SMALL_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_360 : 360
ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370 : 370
INFO : 400
DEBUG : 500
TRACE : 600
ALL : 2147483647
Level.getLevel("ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370") = ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370
[Logger]"logger1": Level=("ALL_CAPS_CONFIG_FILE_ONLY_LOGGER_LEVEL_310" - 310)
[Logger]"logger2": Level=("ERROR" - 200)
[Logger]"logger3": Level=("ERROR" - 200)
[Logger]"logger4": Level=("ERROR" - 200)
[Logger]"logger5": Level=("ERROR" - 200)
[Logger]"logger6": Level=("ERROR" - 200)
[Logger]"logger7": Level=("ALL_CAPS_JAVA_ONLY_LEVEL_330" - 330)
[Logger]"logger8": Level=("ERROR" - 200)
[Logger]"logger9": Level=("ERROR" - 200)
After calling loggers
OFF : 0
FATAL : 100
ERROR : 200
WARN : 300
ALL_CAPS_CONFIG_FILE_ONLY_LOGGER_LEVEL_310 : 310
ALL_SMALL_CONFIG_FILE_ONLY_LOGGER_LEVEL_320 : 320
ALL_CAPS_JAVA_ONLY_LEVEL_330 : 330
ALL_SMALL_JAVA_ONLY_LEVEL_340 : 340
ALL_CAPS_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_350 : 350
ALL_SMALL_CONFIG_FILE_ONLY_APPENDER_REF_LEVEL_360 : 360
ALL_CAPS_CONFIG_FILE_ONLY_NOT_USED_LEVEL_370 : 370
INFO : 400
DEBUG : 500
TRACE : 600
ALL : 2147483647