【问题标题】:JUL logging - instance prefix on messageJUL 日志记录 - 消息上的实例前缀
【发布时间】:2017-12-28 12:17:57
【问题描述】:

我希望我的记录器为每条消息添加一个文本字符串的前缀,因为我需要确定类的哪个instance 记录了该消息。我怎样才能做到这一点?

我不想记住在每个日志记录方法调用上添加前缀,所以我正在寻找一种更像是一个插件的解决方案。自然地,记录器本身不能再像正常情况下那样是静态的。

我已经调查了 Fomatters 和 Handlers 的使用,但无法解决这个特定用例的问题。 JUL 几乎是为类级记录器设计的,而不是实例级记录器。也许我的做法是错误的?

愿意留在 JUL。

【问题讨论】:

  • 您可以使用实例名称而不是类名称来初始化基于实例的 Logger 对象,然后在输出中包含记录器名称。
  • @DodgyCodeException。正确的。但我正在寻找一种解决方案,该解决方案将在message 文本中包含前缀。我不知道用户想要使用什么 Formatter,他可能会选择不记录记录器名称(相比之下,nobody 将创建一个省略消息文本的 Formatter)。

标签: java logging java.util.logging


【解决方案1】:

我已经调查了 Fomatters 和 Handlers 的使用,但无法解决这个特定用例的问题。 JUL 几乎是为类级记录器设计的,而不是实例级记录器。也许我的做法是错误的?

JUL 仅包含两个格式化程序。 XMLFormatter 包括记录器名称。 SimpleFormatter 包含一个可以设置为包含记录器名称的格式属性。这是一个测试程序,可确保您已正确设置所有内容。

import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;


public class SimpleFormatTest {

    public static void main(String[] args) throws Exception {
        //final String format = "%1$ta %1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS.%1$tL %1$Tp %2$s%n%4$s: %5$s%n";
        final String format = "%1$tc %2$s%n%3$s %4$s: %5$s%6$s%n";
        final String key = "java.util.logging.SimpleFormatter.format";
        test(format);
        test(System.getProperty(key, format));
        test(LogManager.getLogManager().getProperty(key));
    }

    private static void test(String format) {
        if (format != null) {
            System.out.println("============");
            LogRecord record = new LogRecord(Level.INFO, "msg");
            record.setLoggerName("logger.name");
            record.setSourceClassName(SimpleFormatTest.class.getName());
            record.setSourceMethodName("test");
            System.out.println(String.format(format,
                    new java.util.Date(record.getMillis()),
                    record.getSourceClassName(),
                    record.getLoggerName(),
                    record.getLevel().getLocalizedName(),
                    record.getMessage(),
                    record.getThrown() == null ? "" : record.getThrown()));
            System.out.println("============");
        }
    }
}

但我正在寻找一种在消息文本中包含前缀的解决方案。我不知道用户想要使用什么 Formatter,他可能会选择不记录记录器名称(相比之下,没有人会创建省略消息文本的 Formatter)。

在您的应用程序中包含logging.properties。您可以添加一个前提条件检查,使您的代码完全无法工作。这将迫使用户设置配置。

 public class NoStart {
    public static void main(String[] args) throws IOException {
        String id = "logger.name";
        LogRecord record = new LogRecord(Level.INFO, "msg");
        record.setLoggerName(id);
        File f = File.createTempFile("test", ".tmp");
        try {
            FileHandler fh = new FileHandler(f.getCanonicalPath(), false);
            try {
                Formatter fmt = fh.getFormatter();
                String r = fmt.format(record);
                if (!r.contains(id)) {
                    throw new IllegalStateException("Formatter must contain logger name.");
                }
            } finally {
                fh.close();
            }
        } finally {
            f.delete();
        }
    }
}

否则,您可以创建自定义过滤器来修改 LogRecord 消息。

public class PrefixMessageFilter implements Filter {

    private final String instanceId;
    private final Filter target;

    public PrefixMessageFilter(final String instanceId, final Filter target) {
        this.instanceId = instanceId;
        this.target = target;
    }

    @Override
    public boolean isLoggable(LogRecord record) {
        record.setMessage(instanceId + ' ' + record.getMessage());
        return target == null || target.isLoggable(record);
    }

    //Example code to setup filter.
    private Logger logger = Logger.getLogger(toString());
    {
        logger.setFilter(new PrefixMessageFilter(toString(), logger.getFilter()));
    }
}

您只需在首次使用时修改记录器。

【讨论】:

  • 您的回答中有一些有趣的想法。我正在调查它。但是,我必须说我不同意“JUL 假设您正在打包并使用您的应用程序设置 logging.properties。”。在我看来,这个想法是操作员(即不是开发人员)可以对其进行自定义以适应他所在的执行环境的要求。
  • @peterh 当然我明白你的意思。我试图传达的观点是 JVM 包含一个用于其上下文的配置。 Tomcat 为其上下文包含一个配置,而部署在 Tomcat 中的 Web 应用程序可以为其上下文包含一个配置。该示例中的每一层都将映射到操作员角色。所以我的意思是,也许你应该为你的上下文提供一个起始配置,操作员可以调整它。该配置将包括 SimpleFormatter 格式化以包含记录器名称。
猜你喜欢
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2015-05-21
  • 2016-02-20
  • 2013-06-26
  • 2013-08-06
相关资源
最近更新 更多