使用多个参数记录日志

41

我目前正在开发一个程序,在其中必须将所有输出写入日志文件。

我需要编写一个日志方法,该方法应按照指定的顺序提供级别、消息、对象值、另一条消息、整数值、另一条消息和另一个整数值的输出。我似乎找不到可以实现这一点的日志方法。我正在使用 Java.util.logging。这是否可能?


请考虑使用Log4J http://logging.apache.org/log4j/2.x/ - Mirco
1
@verbose-mode为什么?Java util logging已经完成了所有必要的工作,并且使用起来更简单。就我所看到的,你的建议违反了KISS(保持简单原则)。 - Martin
4个回答

40
我假设您需要以下格式的日志记录格式 FINE,Message1,object.GetValue(),Message2,1,Message3,2
您需要创建一个输出消息格式。
logger.log(Level.INFO, "{0},{1},{2},{3},{4},{5}",new Object[]{Message1,object.getValue(),Message2,1,Message3,2});

现在您需要创建一个自定义格式化程序,通过扩展Formatter类来实现

public class DataFormatter extends Formatter {

@Override
public synchronized String format(LogRecord record) {
    String formattedMessage = formatMessage(record);
    String throwable = "";
    String outputFormat = "%1$s, %2$s \n %3$s"; //Also adding for logging exceptions
    if (record.getThrown() != null) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        pw.println();
        record.getThrown().printStackTrace(pw);
        pw.close();
        throwable = sw.toString();
    }
    return String.format(outputFormat,record.getLevel().getName(),formattedMessage,throwable);
}
}

现在设置新创建的格式化程序

    for(int i=0;i<logger.getHandlers().length;i++)
        logger.getHandlers()[i].setFormatter(new DataFormatter());

2
logger.info("使用 id {} 和缓存 {} 进行日志记录", id, cache); - abhishek ringsia
1
这个答案是正确的。我使用了 java.util.logging.Logger 的方法 public void log(Level level, String msg, Object params[]) 来实现相同的功能。你只需要在消息中给占位符编号,如 {0}{1} 等,并传递一个参数数组,就像上面展示的 new Object[] {parameter1, parameter2} - havryliuk

36
我们在使用slf4j记录器时使用了以下代码 -
logger.error("Error while finding A from DB. a : {} and b : {}", a, b);
logger.info("Nothing found in db for A with a : {} and b : {}", a, b);

1
有什么改变吗?对我不起作用。 例如:LOGGER.info("在数据库中未找到A与a: {}和b: {}的内容", target, file.getName()); - hafiz ali
1
这个可以工作: LOGGER.log(Level.INFO,"已将文件 {0} 添加到目标: {1}", target);但是无法处理多个参数。 - hafiz ali
21
问题涉及 java.util.logging - Panu Haaramo

21

这是一个相当老的话题,但我想分享我的两分意见,因为在我的项目中,我也更喜欢使用java.util.logging.Logger。

Lambda使得多个自定义参数的样板代码格式化扩展或多或少过时了,除非你从其应用范围的重复使用中受益。在(我)简单的场景中,日志消息是根据插入它的代码部分进行调整的,因此String.format()通常更加容易和灵活。

在Java 8之前和lambda之前,Formatter是推迟消息构造的唯一可能性。唯一的替代方法是,在基于级别的loggable检查之前提前构造要记录的消息。
使用Java 8 Lambda后,字符串格式化可以推迟到loggable检查之后,但仍然可以访问原始方法上下文。唯一的小缺点是,由于lambda限制,所有访问的字段都需要是final的。

这里是一个相当简单的片段:

final String val1 = "lambda expression log message";
final Level level = Level.INFO;
Logger.getGlobal().log(level, () -> 
        String.format("Hello, I'm a %s, evaluated after %s loggable check.", val1, level)
);
Logger.getGlobal().log(level, new RuntimeException(), () -> 
        String.format("Hello, I'm a %s with a stack trace, evaluated after %s loggable check.", val1, level)
);
希望这可以帮助到一些也想使用内置日志记录的人们 :-)
祝福,Ben

2
这种方法的缺点是,在使用String.format而不是java.util.logging.Logger本身进行插入时,无法应用参数格式化。 - Breina

0
一个对我有效的简单例子:
Logger logger = java.util.logging.Logger.getLogger("MyLogger");
logger.log(java.util.logging.Level.INFO, "Test {0}, {1}", new Object[]{2, 3});

结果:

INFO: Test 2, 3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接