由于对象中有些字段过大,比如base64字符串,打印出来非常占用空间,所以想要对指定字段日志进行过滤。
实现的逻辑是通过正则表达式对日志进行匹配,如果存在需要过滤的字段, 则对字段后的值进行替换。
第一步:
新建一个类继承PatternLayout,重写doLayout方法。在该方法中实现替换或脱敏逻辑。
package com.a.b.c.conf;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* @program: kangaroo
* @description: 指定字段过滤
* @author: long
* @create: 2024-01-24 18:26
**/
public class MaskingPatternLayout extends PatternLayout {
private Pattern multilinePattern;
private List<String> maskPatterns = new ArrayList<>();
public void addMaskPattern(String maskPattern) {
maskPatterns.add(maskPattern);
multilinePattern = Pattern.compile(maskPatterns.stream().collect(Collectors.joining("|")), Pattern.MULTILINE);
}
@Override
public String doLayout(ILoggingEvent event) {
return maskMessage(super.doLayout(event));
}
private String maskMessage(String message) {
if (multilinePattern == null) {
return message;
}
StringBuilder sb = new StringBuilder(message);
Matcher matcher = multilinePattern.matcher(sb);
while (matcher.find()) {
IntStream.rangeClosed(1, matcher.groupCount()).forEach(group -> {
if (matcher.group(group) != null) {
// 全部替换为*
IntStream.range(matcher.start(group), matcher.end(group)).forEach(i -> sb.setCharAt(i, '*'));
}
});
}
if (StringUtils.isNotBlank(sb.toString())) {
//将所有*替换成一个*号
return sb.toString().replaceAll("\\*+", "*");
}
return sb.toString();
}
}
第二步:
修改logback配置文件,encoder需要指定class为ch.qos.logback.core.encoder.LayoutWrappingEncoder,layout指定刚刚自定义的layout类。然后在maskPattern中指定需要过滤或脱敏的字段。
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.a.b.c.conf.MaskingPatternLayout">
<maskPattern>\"userName\"\s*:\s*\"(.*?)\"</maskPattern>
<maskPattern>\"telephone\"\s*:\s*\"(.*?)\"</maskPattern>
<pattern>${PATTERN}</pattern>
</layout>
<charset>utf8</charset>
</encoder>