ฉันสนใจที่จะเปลี่ยนระดับการบันทึกใน Log4j2 โดยทางโปรแกรม ฉันพยายามดูเอกสารการกำหนดค่าของพวกเขาแต่ดูเหมือนจะไม่มีอะไรเลย ฉันลองดูในแพ็คเกจด้วย: org.apache.logging.log4j.core.config
แต่ไม่มีอะไรในนั้นก็ดูเป็นประโยชน์เช่นกัน
ฉันสนใจที่จะเปลี่ยนระดับการบันทึกใน Log4j2 โดยทางโปรแกรม ฉันพยายามดูเอกสารการกำหนดค่าของพวกเขาแต่ดูเหมือนจะไม่มีอะไรเลย ฉันลองดูในแพ็คเกจด้วย: org.apache.logging.log4j.core.config
แต่ไม่มีอะไรในนั้นก็ดูเป็นประโยชน์เช่นกัน
คำตอบ:
แก้ไขตาม log4j2 เวอร์ชัน 2.4 คำถามที่พบบ่อย
คุณสามารถตั้งค่าระดับของคนตัดไม้ด้วยคลาส Configurator จาก Log4j Core แต่โปรดทราบว่าคลาส Configurator ไม่ได้เป็นส่วนหนึ่งของ API สาธารณะ
// org.apache.logging.log4j.core.config.Configurator;
Configurator.setLevel("com.example.Foo", Level.DEBUG);
// You can also set the root logger:
Configurator.setRootLevel(Level.DEBUG);
แก้ไขเพื่อแสดงการเปลี่ยนแปลงใน API ที่นำมาใช้ใน Log4j2 เวอร์ชัน 2.0.2
หากคุณต้องการเปลี่ยนระดับคนตัดไม้รากให้ทำดังนี้:
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(level);
ctx.updateLoggers(); // This causes all Loggers to refetch information from their LoggerConfig.
นี่คือ javadoc สำหรับ LoggerConfig
คำตอบที่ได้รับการยอมรับโดย @slaadvak ไม่ได้ทำงานสำหรับฉันLog4j2 2.8.2 ต่อไปนี้ทำ
ในการเปลี่ยนบันทึกโดยLevel
ทั่วไปให้ใช้:
Configurator.setAllLevels(LogManager.getRootLogger().getName(), level);
หากต้องการเปลี่ยนบันทึกLevel
เฉพาะคลาสปัจจุบันให้ใช้:
Configurator.setLevel(LogManager.getLogger(CallingClass.class).getName(), level);
หากคุณต้องการเปลี่ยนระดับตัวบันทึกเฉพาะรายการเดียว (ไม่ใช่รูทคนตัดไม้หรือตัวบันทึกที่กำหนดค่าในไฟล์คอนฟิกูเรชัน) คุณสามารถทำได้:
public static void setLevel(Logger logger, Level level) {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(logger.getName());
LoggerConfig specificConfig = loggerConfig;
// We need a specific configuration for this logger,
// otherwise we would change the level of all other loggers
// having the original configuration as parent as well
if (!loggerConfig.getName().equals(logger.getName())) {
specificConfig = new LoggerConfig(logger.getName(), level, true);
specificConfig.setParent(loggerConfig);
config.addLogger(logger.getName(), specificConfig);
}
specificConfig.setLevel(level);
ctx.updateLoggers();
}
setLevel(logger, Level.ERROR);
และคำสั่ง logger.debug ยังคงพิมพ์อยู่ ไฟล์ log4j2.xml ของฉันอยู่ที่pastebin.com/fcbV2mTW
ฉันพบคำตอบที่ดีที่นี่: https://garygregory.wordpress.com/2016/01/11/changing-log-levels-in-log4j2/
คุณสามารถใช้ org.apache.logging.log4j.core.config.Configurator เพื่อตั้งค่าระดับสำหรับตัวบันทึกเฉพาะ
Logger logger = LogManager.getLogger(Test.class);
Configurator.setLevel(logger.getName(), Level.DEBUG);
วิธีการแบบเป็นโปรแกรมค่อนข้างก้าวก่าย บางทีคุณควรตรวจสอบการรองรับ JMX ที่ Log4J2 มอบให้:
เปิดใช้งานพอร์ต JMX ในการเริ่มต้นแอปพลิเคชันของคุณ:
-Dcom.sun.management.jmxremote.port = [port_num]
ใช้ไคลเอนต์ JMX ใด ๆ ที่มีอยู่ (JVM มีหนึ่งใน JAVA_HOME / bin / jconsole.exe) ในขณะที่เรียกใช้แอปพลิเคชันของคุณ
ใน JConsole ให้มองหาถั่ว "org.apache.logging.log4j2.Loggers"
ในที่สุดก็เปลี่ยนระดับคนตัดไม้ของคุณ
สิ่งที่ฉันชอบมากที่สุดคือคุณไม่จำเป็นต้องแก้ไขโค้ดหรือการกำหนดค่าเพื่อจัดการสิ่งนี้ ภายนอกและโปร่งใสทั้งหมด
ข้อมูลเพิ่มเติม: http://logging.apache.org/log4j/2.x/manual/jmx.html
โดยค่าเริ่มต้นคำตอบส่วนใหญ่ถือว่าการบันทึกต้องมีการเพิ่มเติม แต่ให้บอกว่าบางแพ็คเกจกำลังสร้างบันทึกจำนวนมากและคุณต้องการปิดการบันทึกสำหรับคนตัดไม้นั้น ๆ เท่านั้น นี่คือรหัสที่ฉันใช้เพื่อให้มันใช้งานได้
public class LogConfigManager {
public void setLogLevel(String loggerName, String level) {
Level newLevel = Level.valueOf(level);
LoggerContext logContext = (LoggerContext) LogManager.getContext(false);
Configuration configuration = logContext.getConfiguration();
LoggerConfig loggerConfig = configuration.getLoggerConfig(loggerName);
// getLoggerConfig("a.b.c") could return logger for "a.b" if there is no logger for "a.b.c"
if (loggerConfig.getName().equalsIgnoreCase(loggerName)) {
loggerConfig.setLevel(newLevel);
log.info("Changed logger level for {} to {} ", loggerName, newLevel);
} else {
// create a new config.
loggerConfig = new LoggerConfig(loggerName, newLevel, false);
log.info("Adding config for: {} with level: {}", loggerConfig, newLevel);
configuration.addLogger(loggerName, loggerConfig);
LoggerConfig parentConfig = loggerConfig.getParent();
do {
for (Map.Entry<String, Appender> entry : parentConfig.getAppenders().entrySet()) {
loggerConfig.addAppender(entry.getValue(), null, null);
}
parentConfig = parentConfig.getParent();
} while (null != parentConfig && parentConfig.isAdditive());
}
logContext.updateLoggers();
}
}
กรณีทดสอบเดียวกัน
public class LogConfigManagerTest {
@Test
public void testLogChange() throws IOException {
LogConfigManager logConfigManager = new LogConfigManager();
File file = new File("logs/server.log");
Files.write(file.toPath(), new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
Logger logger = LoggerFactory.getLogger("a.b.c");
logger.debug("Marvel-1");
logConfigManager.setLogLevel("a.b.c", "debug");
logger.debug("DC-1");
// Parent logger level should remain same
LoggerFactory.getLogger("a.b").debug("Marvel-2");
logConfigManager.setLogLevel("a.b.c", "info");
logger.debug("Marvel-3");
// Flush everything
LogManager.shutdown();
String content = Files.readAllLines(file.toPath()).stream().reduce((s1, s2) -> s1 + "\t" + s2).orElse(null);
Assert.assertEquals(content, "DC-1");
}
}
สมมติว่า log4j2.xml ต่อไปนี้อยู่ใน classpath
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
<Appenders>
<File name="FILE" fileName="logs/server.log" append="true">
<PatternLayout pattern="%m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
</Appenders>
<Loggers>
<AsyncLogger name="a.b" level="info">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="FILE"/>
</AsyncLogger>
<AsyncRoot level="info">
<AppenderRef ref="STDOUT"/>
</AsyncRoot>
</Loggers>
</Configuration>
วิธีหนึ่งที่ผิดปกติที่ฉันพบคือการสร้างไฟล์สองไฟล์แยกกันโดยมีระดับการบันทึกที่แตกต่างกัน
ตัวอย่างเช่น. log4j2.xml และ log4j-debug.xml ตอนนี้เปลี่ยนการกำหนดค่าจากไฟล์นี้
รหัสตัวอย่าง:
ConfigurationFactory configFactory = XmlConfigurationFactory.getInstance();
ConfigurationFactory.setConfigurationFactory(configFactory);
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classloader.getResourceAsStream(logFileName);
ConfigurationSource configurationSource = new ConfigurationSource(inputStream);
ctx.start(configFactory.getConfiguration(ctx, configurationSource));