这有点奇怪,但我是日志包及其属性的新手。我通过谷歌搜索找到的所有问题都是“如何让日志记录打开多个文件?”但我今天的问题是如何让它停止同时执行多个文件。我们走了......
首先要做的事情是:这个项目仅限于使用java.util.logging,我不能切换到log4j或任何其他第三方软件包,是的,我知道它们应该更加精彩。 : - )
所以当这个小程序启动时,它运行这段代码:
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最终退出,它就会被删除。)
我在属性文件中做了一些愚蠢的事情,或者误解了如何正确加载属性,还是......?
答案 0 :(得分:3)
我认为readConfiguration()
不像您认为的那样有效。形成JavaDocs:
重新初始化日志记录属性并重新读取日志记录 来自给定流的配置,应该在 java.util.Properties格式。之后将触发PropertyChangeEvent 阅读这些属性。
新配置文件中的任何日志级别定义都将是 如果目标Logger存在,则使用Logger.setLevel()进行应用。
我不确定这是否会实际重置日志记录配置,或者只是附加/更新当前配置。
我认为您可能需要在致电reset()
之前致电readConfiguration()
。
重置日志记录配置。
对于所有已命名的记录器,重置操作将删除并关闭所有记录器 处理程序和(根记录器除外)将级别设置为null。该 root logger的级别设置为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");
}
}
答案 1 :(得分:1)
@Joop钉了它(在评论中,不能标记为答案)。事实证明,设置处理程序是一个添加过程,它不会简单地覆盖以前的设置。这对我来说似乎真的不直观,但那是你的java.util.logging ...保留所有其他属性,但删除处理程序赋值,是可行的方法。
我也在使用@jschoen建议的reset()调用,因为这似乎是一个聪明的事情!
非常感谢你们所有人。我不确定如何将这一切标记为“封闭”......是时候把网站搞砸了。