Java日志记录打开“太多”日志文件

这有点奇怪,但我是日志包及其属性的新手。 我通过谷歌搜索找到的所有问题都是“如何让日志记录打开多个文件?” 但我今天的问题是如何让它停止同时处理多个文件。 开始了…

首先要做的事情是:这个项目仅限于使用java.util.logging,我不能切换到log4j或任何其他第三方软件包,是的,我知道它们应该更加精彩。 🙂

所以当这个applet启动时,它会运行这段代码:

import java.util.logging.Logger; import java.util.logging.LogManager; // in startup routine: LogManager.getLogManager().readConfiguration( this.getClass().getResourceAsStream("/logging.properties")); 

从JAR中提取属性文件并应用它们,这是有效的。 readConfiguration()应该从VM启动重置所有现有设置。 项目的其余部分有像

 private final static Logger LOGGER = Logger.getLogger(NameOfClass.class.getName()); 

我认为这是非常标准的。 我们所有的类都在同一个包中(例如称之为TheProject),而时髦的日志名称/属性层次结构遵循相同的约定,因为这就是java.util.logging喜欢滚动的方式。

logging.properties文件作为Java 6 SE JRE附带的副本的一个副本开始,然后进行了修改。 现在它看起来像这样:

 handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler # Default global logging level. .level=INFO # Loggers # ------------------------------------------ # Loggers are usually attached to packages. # Here, the level for each package is specified. # The global level is used by default, so levels # specified here simply act as an override. java.level = INFO javax.swing.level = INFO sun.awt.level = INFO theproject.level = ALL # Handlers # ----------------------------------------- theproject.handlers=java.util.logging.FileHandler # Override of global logging level java.util.logging.FileHandler.level=ALL # Naming style for the output file: java.util.logging.FileHandler.pattern=/path/to/logfiles/TheProject%u.%g.log 

所有“工作”,因为日志消息显示在Java控制台中,也出现在磁盘文件中。 这是奇怪的部分:applet运行后,同时打开两个文件,包括TheProject0.0.log和TheProject1.0.log。 当日志消息被触发时,它们同时显示在两个文件中。 这两个文件始终是彼此的精确副本,包括达到最大大小并且(都是!)旋转时。

我检查过,一次只运行一个JRE VM。

在任何给定的时间,两个文件都打开,或两者都关闭,我检查。 它不像是一个比另一个更长或更短的时间开放。

如果日志文件已被另一个进程打开,那么两个文件名之间不同的%u标记被记录为“解决冲突的唯一编号”,但我认为这不是这种情况,因为两个日志都获得相同的数据而没有任何内容否则打开文件。 (证据:在VM运行时,Windows不会让我删除任何一个文件,但是一旦VM最终退出,它就会被删除。)

我在属性文件中做了一些愚蠢的事情,或者误解了如何正确加载属性,或者……?

我认为readConfiguration()并不像你认为的那样工作。 形成JavaDocs:

重新初始化日志记录属性并重新读取给定流中的日志记录配置,该流应采用java.util.Properties格式。 读取属性后将触发PropertyChangeEvent。

如果目标Logger存在,则将使用Logger.setLevel()应用新配置文件中的任何日志级别定义。

我不确定这是否实际上重置了日志配置,或者只是追加/更新当前配置。

我想你可能需要在调用readConfiguration()之前调用reset() readConfiguration()

重置日志记录配置。

对于所有已命名的记录器,重置操作将删除和关闭所有处理程序,并且(根记录器除外)将级别设置为null。 根记录器的级别设置为Level.INFO。

编辑:只是为了表明它不是您的属性文件的问题,您可以在theproject包中创建一个名为test的类,如下所示并运行它。 只需确保删除现有的日志文件,以便了解在运行时创建的日志文件数量。

 package theproject; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; public class Test { private final static Logger LOGGER = Logger.getLogger(Test.class.getName()); public static void main(String[] args) throws Exception { LogManager.getLogManager().readConfiguration( Test.class.getResourceAsStream("/logging.properties")); // The only way I could get it to create two log files was to uncomment the line below that // adds another FileHandler to the root logger. // LogManager.getLogManager().getLogger("").addHandler(new FileHandler("/path/to/logfiles/TheProject%u.%g.log")); Test test = new Test(); } public Test(){ LOGGER.log(Level.INFO, "Info"); } } 

@Joop钉了它(在评论中,不能标记为答案)。 事实certificate,设置处理程序是一个附加过程,它不会简单地覆盖以前的设置。 这似乎对我来说真的不直观,但那是你的java.util.logging …留下所有其他属性,但删除处理程序赋值,是要走的路。

我也在使用@jschoen建议的reset()调用,因为这似乎是一个聪明的事情!

非常感谢你们所有人。 我不确定如何将这一切标记为“封闭”…时间来摆弄一些网站。