log4j动态日志级别调整

时间:2021-12-12 13:21:51

1. 针对root logger的设置

log4j.rootLogger=INFO, CONSOLE
Logger.getRootLogger().setLevel(org.apache.log4j.Level.DEBUG)

2. 针对Appender的Appender设置

log4j.appender.CONSOLE.Threshold=DEBUG
((org.apache.log4j.ConsoleAppender)Logger.getRootLogger().getAppender("CONSOLE")).setThreshold(Priority.DEBUG)
注意Appender的转型,用AppenderSkeleton 更好

3. 针对包名设置的日志级别的调整

log4j.logger.org.simonme.log4j.thread=ERROR
Logger.getRootLogger().getLogger("org.simonme.log4j.thread").setLevel(org.apache.log4j.Level.DEBUG);

另:
Logger.getRootLogger().getCurrentCategories();  能拿到所有logger对象
只是已经是过时api了

再另:
级别无论如何设置,不会超过其父级别
上面 1 2 3 就是按父子顺序的排列的。

再另另:

针对包名的日志级别配置 log4j.logger.org.simonme.log4j.thread=ERROR 是在什么地方处理了这个逻辑 使之生效的

请查看org.apache.log4j.Hierarchy.updateParents(Logger)方法

//System.out.println("UpdateParents called for " + name);

    // if name = "w.x.y.z", loop thourgh "w.x.y", "w.x" and "w", but not "w.x.y.z"
for(int i = name.lastIndexOf('.', length-1); i >= 0;
i = name.lastIndexOf('.', i-1)) {
String substr = name.substring(0, i); //System.out.println("Updating parent : " + substr);
CategoryKey key = new CategoryKey(substr); // simple constructor
Object o = ht.get(key);
// Create a provision node for a future parent.
if(o == null) {
//System.out.println("No parent "+substr+" found. Creating ProvisionNode.");
ProvisionNode pn = new ProvisionNode(cat);
ht.put(key, pn);
} else if(o instanceof Category) {
parentFound = true;
cat.parent = (Category) o;
//System.out.println("Linking " + cat.name + " -> " + ((Category) o).name);
break; // no need to update the ancestors of the closest ancestor
} else if(o instanceof ProvisionNode) {
((ProvisionNode) o).addElement(cat);
} else {
Exception e = new IllegalStateException("unexpected object type " +
o.getClass() + " in ht.");
e.printStackTrace();
}
}

再另另另:

性能如何

org.apache.log4j.Category.getEffectiveLevel()

for(Category c = this; c != null; c=c.parent) {
if(c.level != null)
return c.level;
}

是向父级别查找的办法,所以性能无大影响。