java - 使用 java.util.logging API 将不同级别的日志记录到单独的文件

标签 java java.util.logging

我想知道如何使用 java.util.logging api,以便根据使用的级别将日志消息写入不同的日志文件。如果级别是 INFO 那么我想将消息写入/log/info.log 等等。定义的 3 个级别是严重、警告和信息。

最佳答案

您使用自定义 Handlers写入日志记录。

这是一个简单但完整的示例,您可以在此基础上构建。

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogRecord;

public class LevelBasedFileHandler extends FileHandler
{
    public LevelBasedFileHandler(final Level level) throws IOException, SecurityException
    {
        super();
        super.setLevel(level);
    }

    public LevelBasedFileHandler(final String s, final Level level) throws IOException, SecurityException
    {
        super(s);
        super.setLevel(level);
    }

    public LevelBasedFileHandler(final String s, final boolean b, final Level level) throws IOException, SecurityException
    {
        super(s, b);
        super.setLevel(level);
    }

    public LevelBasedFileHandler(final String s, final int i, final int i1, final Level level) throws IOException, SecurityException
    {
        super(s, i, i1);
        super.setLevel(level);
    }

    public LevelBasedFileHandler(final String s, final int i, final int i1, final boolean b, final Level level) throws IOException, SecurityException
    {
        super(s, i, i1, b);
        super.setLevel(level);
    }

    @Override
    public void setLevel() { throw new UnsupportedOperationException("Can't change after construction!"); }

    // This is the important part that makes it work
    // it also breaks the contract in the JavaDoc for FileHandler.setLevel() 
    @Override
    public void publish(final LogRecord logRecord)
    {
        if (logRecord.getLevel().equals(super.getLevel())
        {
            super.publish(logRecord);
        }
    }
}

下面是使用方法

try
{
    // I use the Anonymous logger here, but any named logger will work as well
    final Logger l = Logger.getAnonymousLogger();
    l.addHandler(new LevelBasedFileHandler("/tmp/info.log", Level.INFO));
    l.addHandler(new LevelBasedFileHandler("/tmp/warn.log", Level.WARNING));
    l.addHandler(new LevelBasedFileHandler("/tmp/server.log", Level.SEVERE));

    l.info("This is an INFO message");
    l.warning("This is a WARNING message");
    l.severe("This is a SEVERE message");
}
catch (final IOException e)
{
    // ignore this for this example, you should never do this in real code
}

您将在 /tmp 中获得三个文件,每个文件仅包含每个特定日志级别的消息。

请注意,我喜欢在构造函数中要求 Level 的依赖注入(inject)样式方法,因此您在使用它时不会“忘记”调用 .setLevel()子类。我还禁用了 .setLevel() 因为调用它并更改会破坏子类的语义”

为了完整起见,您可以使用 java.util.logging.Filter 来完成同样的事情。它不是封装的,但它是另一种选择。它的代码更多、更冗长,因此更容易出错。

final FileHandler infoFileHandler = new FileHandler("/tmp/info.log");
infoFileHandler.setFilter(new Filter()
{
    public boolean isLoggable(final LogRecord logRecord)
    {
        return logRecord.getLevel().equals(Level.INFO);
    }
});

就我个人而言,我仍然更喜欢子类方法,它更不容易出错,而且更能 self 记录其目的和意图。

关于java - 使用 java.util.logging API 将不同级别的日志记录到单独的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7925674/

相关文章:

java - 双态 Action 的最佳方法

java - 坐标超出 .setRGB 范围

java - Ehcache日志级别

java - 在创建 java.util.logging.Logger 之前,如何检查它是否已经存在?

java - slf4j 与 jdk14 正在将 INFO 消息记录到 stderr

java - 在 Websphere WebApp 中将 JUL 重定向到 Log4J2

java - 在 Java 中登录

java - 我应该使用什么属性类型来保留日期和月份,而不是年份?

java - 静态常量是否违反 "encapsulation"?

java - 为什么要分解不包括 spring-boot-starter-logging 的日志文件?