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

时间:2017-12-28 12:17:57

标签: java logging java.util.logging

我希望我的记录器在每条消息上添加一个文本字符串作为前缀,因为我需要识别一个类的实例已记录消息。我怎么能做到这一点?

我不想记得在每个日志记录方法调用中添加前缀,所以我正在寻找一个更像是插件的解决方案。当然,记录器本身不再是静态的,否则就是正常情况。

我已经调查了FomatterHandler的使用情况,但未能解决这个特定用例的问题。 JUL几乎是为类级别的记录器设计的,而不是实例级记录器。也许我会以错误的方式解决这个问题?

想留在JUL。

1 个答案:

答案 0 :(得分:1)

  

我已经研究过使用Fomatters和Handlers,但是还没能为这个特殊的用例破解坚果。 JUL几乎是为类级别的记录器设计的,而不是实例级记录器。也许我会以错误的方式解决这个问题?

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

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)。

在您的申请中加入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()));
    }
}

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