Java日志记录打开";“太多”;日志文件
这有点奇怪,但我对日志包及其属性的使用还不熟悉。通过谷歌搜索,我能找到的所有问题都是“如何让日志打开多个文件?”但我今天的问题是如何让它停止同时执行多个文件。我们走吧 第一件事:此项目仅限于使用java.util.logging,不,我不能切换到log4j或任何其他第三方软件包,是的,我知道它们应该更棒。:-) 因此,当这个小程序启动时,它会运行以下代码:Java日志记录打开";“太多”;日志文件,java,java.util.logging,Java,Java.util.logging,这有点奇怪,但我对日志包及其属性的使用还不熟悉。通过谷歌搜索,我能找到的所有问题都是“如何让日志打开多个文件?”但我今天的问题是如何让它停止同时执行多个文件。我们走吧 第一件事:此项目仅限于使用java.util.logging,不,我不能切换到log4j或任何其他第三方软件包,是的,我知道它们应该更棒。:-) 因此,当这个小程序启动时,它会运行以下代码: import java.util.logging.Logger; import java.util.logging.LogManager;
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());
我认为这是相当标准的。我们所有的类都在同一个包中(例如,将其称为project),并且funky日志名称/属性层次结构遵循相同的约定,因为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控制台中,也显示在磁盘文件中。奇怪的是:小程序一运行,就会同时打开两个文件,即project0.0.log和project1.0.log。当日志消息被触发时,它们会同时显示在两个文件中。这两个文件在任何时候都是彼此的精确副本,包括达到最大大小并(都!)旋转时
我检查过,一次只有一个JRE虚拟机在运行
在任何给定的时间,要么两个文件都被打开,要么两个文件都被关闭。这不像是一个比另一个开放的时间更长或更短
如果日志文件已被另一个进程打开,则两个文件名之间不同的%u标记将被记录为“解决冲突的唯一编号”,但我认为这里不是这种情况,因为两个日志都获得相同的数据,没有其他东西打开该文件。(证据:当虚拟机运行时,Windows不允许我删除这两个文件,但一旦虚拟机最终退出,它就会删除。)
我是否在属性文件中做了一些愚蠢的事情,或者误解了如何正确加载属性,或者…?我认为它的工作方式与您认为的不同。形成JavaDocs:
重新初始化日志记录属性并重新读取日志记录
来自给定流的配置,该流应位于
java.util.Properties格式。PropertyChangeEvent将在
属性被读取
新配置文件中的任何日志级别定义都将被删除
如果目标记录器存在,则使用Logger.setLevel()应用
我不确定这是否真的会重置日志记录配置,或者只是附加/更新当前配置
我想你可能需要在打电话之前先打个电话
重置日志记录配置
对于所有命名记录器,重置操作将删除并关闭所有
处理程序和(根记录器除外)将级别设置为null。这个
根记录器的级别设置为level.INFO
编辑:为了表明属性文件没有问题,您可以在项目包中创建一个名为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");
}
}
@乔普(在一篇评论中,不能被标记为答案)说得很对。事实证明,设置处理程序是一个添加过程,它不会简单地覆盖以前的设置。这对我来说似乎很不直观,但这是java.util.logging for ya。。。保留所有其他属性,但删除处理程序分配,是一种方法
我还使用了@jschoen建议的reset()调用,因为这似乎是一件明智的事情
非常感谢你们所有人。我不知道如何将这一切标记为“关闭”。。。是时候去摆弄一下网站了。你有没有试着对项目进行评论。处理程序=…
?你发布的东西似乎没有问题。您是否可能在java代码的某个地方向记录器添加了第二个文件处理程序(例如LogManager.getLogManager().getLogger(NameOfClass.class.getName()).addHandler(新的文件处理程序(“/path/to/logfiles/TheProject%u.%g.log”);
)。这是我复制它的唯一方法。捕捉得好!我将代码改为LogManager LM=LogManager.getLogManager();LM.reset();LM.读取配置(…)代码>不幸的是,这根本没有效果。我在重置之前、重置之后和readConfig之后使用LogManager的getLoggerNames添加了一些转储代码,并且所有三个打印输出都是相同的。@TiStrga我不确定getLoggerNames
是否是您应该查找的,但是每个记录器中都有getHandlers()
。它们似乎以某种方式连接了两个FileHandler
s。您是否检查了代码中是否向记录器添加了第二个FileHandler?