java - JUL 日志记录 - 消息上的实例前缀

标签 java logging java.util.logging

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

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

我研究了 FomatterHandler 的使用,但无法解决这个特定用例的问题。 JUL 几乎是为类级记录器设计的,而不是实例级记录器。也许我的处理方式是错误的?

想留在 JUL。

最佳答案

I've investigated use of Fomatters and Handlers but haven't been able to crack the nut for this particular use case. JUL is pretty much designed for class-level loggers, not instance-level loggers. Perhaps I'm going about this the wrong way?

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("============");
        }
    }
}

But I was looking for a solution that would include the prefix in message text. I cannot know what Formatter the user would want to use and he may choose to not log the logger name (in contrast nobody will ever create a Formatter which omits the message text).

在您的应用程序中包含一个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()));
    }
}

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

关于java - JUL 日志记录 - 消息上的实例前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48007387/

相关文章:

java - android - 对何时使用线程和何时使用服务有点困惑?

java - Java 日志记录、Log4J、Logback 的性能和内存占用

java - JAXB 中的 native 查询

java - spymemcached:如何判断memcached是否已连接成功?

java - 我一直收到 "The operator == is undefined for the argument type(s) boolean, int"并且不知道如何修复它

java - 处理所有异常

python - PyTest - 登录生产代码

ruby-on-rails - 如何将特定请求详细信息记录到 Rails 服务器日志

Java 文件句柄不会关闭

logging - Log4j JDK 日志记录适配器 : Apply LogManager system property late in the startup process