log4j動態日誌級別調整
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; }
是向父級別查找的辦法,所以性能無大影響。
log4j動態日誌級別調整