【问题标题】:Is there a way to change the level of a log based on it's content?有没有办法根据日志的内容来改变日志的级别?
【发布时间】:2021-11-25 17:30:07
【问题描述】:
我正在使用 Logback 进行日志记录,在我的代码的几个地方,我有如下内容:
if(message.contains("kitten")) {
logger.info(message);
} else if (message.contains("wolf")) {
logger.error(message);
} else if(message.contains("chuck norris")) {
logger.fatal(message);
} else {
logger.warn(message);
}
(大多数时候消息来自外部系统)
有没有更丑的方法?
【问题讨论】:
标签:
java
logback
logback-classic
【解决方案1】:
由于您使用 logback 作为后端,并且您没有指定正在使用的日志记录 API,我假设您使用的是 slf4j(logback 的本机 API)。不幸的是,这个 API 并不像人们希望的那样灵活。例如,log4j 2 有Logger.log,它接受Level,然后你可以像这样使用它:
logger.log(levelFor(message), message);
...
private Level levelFor(String message) {
if (message.contains("kitten"))
return Level.INFO;
else if...
return...
}
不幸的是,slf4j 没有Logger.log 方法。您可以使用 log4j2 作为您的 API,并使用适当的 jar 依赖项将其桥接到您的 logback 后端。
【解决方案2】:
这是一个有趣的问题,也引入了新问题。
您可以拥有一个单词列表,这些单词可以升级或降低该消息的日志级别。
解决这个问题的一种方法是制作您自己的记录器类,它封装了您的通用日志框架,镜像每个日志方法。
建立的第一个版本将简单地调用 ie 后面的日志框架。
public class MyLogger {
public void info(String message) { Logger.info(message); }
public void debug(String message) { Logger.debug(message); }
// And so on
}
假设你有一个单词表,如果包含在消息中,你可以引入一些单词来触发另一个级别。
public class MyLogger {
private final List<String> warnTriggerMessages;
public MyLogger(List<String> warnTrigerMessages) {
this.warnTriggerMessages = warnTrigerMessages;
}
public void info(String message) {
if (warnTriggerMessages.stream().anyMatch(trigger => message.contains(trigger))) {
Logger.warn(message);
} else {
Logger.info(message);
}
}
// And so on
}
这只是一个非常简单的示例,但可以使用更通用的方法进行扩展,或者与 strategyPattern 交织在一起,这将根据“建议的”日志级别和消息解析日志记录方法,其中消息可能导致选择另一个日志级别而不是建议的日志级别的策略。
【解决方案3】:
我认为没有办法指示 logback 根据内容更改级别,您可能不想这样做,因为日志记录属于您的业务逻辑。
如果你使用 jdk 16 并且代码和你展示的一样简单,那么 switch 语句可能会更好
switch (message){
case "kitten" -> logger.info(message);
case "wolf" -> logger.error(message);
case "chuck norris" -> logger.fatal(message);
default -> logger.warn(message);
}