Загрузка данных


import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MaskingPatternLayout extends PatternLayout {

    private final List<ReplaceTemplate> replaceTemplates = new ArrayList<>();

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public void setPatternsProperty(String patternsProperty) throws IOException {
        Map<String, String> map = objectMapper.readValue(patternsProperty, HashMap.class);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            if (entry.getValue().contains("~")) {
                String[] s = entry.getValue().split("~");
                int firstPartLength = Integer.valueOf(s[0]);
                int lastPartLength = Integer.valueOf(s[2]);
                String replaceString = s[1];
                replaceTemplates.add(new ReplaceTemplate(Pattern.compile(entry.getKey()), replaceString, firstPartLength, lastPartLength));
            } else {
                replaceTemplates.add(new ReplaceTemplate(Pattern.compile(entry.getKey()), entry.getValue()));
            }
        }
    }

    @Override
    public String doLayout(ILoggingEvent event) {
        String msg = super.doLayout(event);
        for (ReplaceTemplate replaceTemplate : replaceTemplates) {
            Matcher matcher = replaceTemplate.getSourcePattern().matcher(msg);
            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                if (replaceTemplate.isSimpleReplace()) {
                    matcher.appendReplacement(sb, replaceTemplate.getReplaceString());
                } else {
                    String group = matcher.group();
                    String s1 = group.substring(0, replaceTemplate.getFirstPartLength());
                    String s2 = group.substring(group.length() - replaceTemplate.getLastPartLength());
                    matcher.appendReplacement(sb, s1 + replaceTemplate.replaceString + s2);
                }
            }
            matcher.appendTail(sb);
            msg = sb.toString();
        }
        return msg;
    }
//todo поля final и в record
    private class ReplaceTemplate {
        private Pattern sourcePattern;
        private String replaceString;
        private int firstPartLength;
        private int lastPartLength;
        private boolean simpleReplace;

        public ReplaceTemplate(Pattern sourcePattern, String replaceString) {
            this.sourcePattern = sourcePattern;
            this.replaceString = replaceString;
            this.simpleReplace = true;
        }

        public ReplaceTemplate(Pattern sourcePattern, String replaceString, int firstPartLength, int lastPartLength) {
            this.sourcePattern = sourcePattern;
            this.replaceString = replaceString;
            this.firstPartLength = firstPartLength;
            this.lastPartLength = lastPartLength;
            this.simpleReplace = false;
        }

        public Pattern getSourcePattern() {
            return sourcePattern;
        }

        public String getReplaceString() {
            return replaceString;
        }

        public int getFirstPartLength() {
            return firstPartLength;
        }

        public int getLastPartLength() {
            return lastPartLength;
        }

        public boolean isSimpleReplace() {
            return simpleReplace;
        }
    }
}

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="MaskingPatternLayout">
                <patternsProperty>
                    <![CDATA[
                            {
                                "pan[ ]*[:][ ]*[\\d]*]"             :   "pan : ***]",
                                "PAN[ ]*****[:][ ]*****[\\d]*****]"             :   "PAN : ***]",
                                "pan[ ]*[=:][ ]*'[\\d]*'"           :   "11~**~5",
                                "pan[ ]*****[=:][ ]*****\"[\\d]*\""         :   "11~**~5",
                            }
                            ]]>
                </patternsProperty>
                <pattern>%date [%thread] %-5level %logger:%line - %message %mdc{jobKeyName} %n</pattern>
            </layout>
        </encoder>
    </appender>

//todo AsyncAppender -- может и не потребоваться, но нужно потестить
    <appender name="console_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="console"/>
        <queueSize>1000</queueSize>
        <includeCallerData>true</includeCallerData>
    </appender>

    <root level="INFO">
        <appender-ref ref="console"/>
    </root>