从新创建的 Thread 中使用 PatternLayout 类的 format(LoggingEvent 事件)方法独立执行自定义日志掩码逻辑

Use of PatternLayout class's format(LoggingEvent event) method from a newly created Thread to execute custom log masking logic independently

提问人:Sujit Kumar Mishra 提问时间:7/13/2023 更新时间:7/13/2023 访问量:48

问:

无法从新创建的 Thread 调用 PatternLayout 类的 format(LoggingEvent 事件)方法,以独立执行自定义日志掩码逻辑,而不会对实际功能产生任何影响。出现多个错误,例如 -

  1. 编译器要求使 LoggingEvent 对象成为最终对象。
  2. 无法将屏蔽响应存储到 run() 方法中的全局变量 maskedOutput 中,我们希望从 format(LoggingEvent event) 方法返回该变量。

以下是实际代码:-

public class CardNumberFilteringLayout extends PatternLayout {
    private static final String MASK = "$1++++++++++++";
    private static final Pattern PATTERN = Pattern.compile("([0-9]{4})([0-9]{9,15})");
    @Override
    public String format(LoggingEvent event) {
        if (event.getMessage() instanceof String) {
            String message = event.getRenderedMessage();
            Matcher matcher = PATTERN.matcher(message);
            if (matcher.find()) {
                String maskedMessage = matcher.replaceAll(MASK);
                @SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
                Throwable throwable = event.getThrowableInformation() != null ? 
                        event.getThrowableInformation().getThrowable() : null;
                LoggingEvent maskedEvent = new LoggingEvent(event.fqnOfCategoryClass,
                        Logger.getLogger(event.getLoggerName()), event.timeStamp, 
                        event.getLevel(), maskedMessage, throwable);
                return super.format(maskedEvent);
            }
        }
        return super.format(event);
    }
}

根据我们的要求,我们正在尝试将上面的一段代码更改为以下内容:-

@Override
public String format(LoggingEvent event) {
    String maskedOutput = null;
    new Thread(new Runnable() {
        @Override
        public void run() {
            maskedOutput = //Masking Logic(Same As Above)
        } 
    }).start();
    return maskedOutput; 
}
Java 多线程 log4j 数据掩码

评论

1赞 RealSkeptic 7/13/2023
您的变量是局部变量,而不是全局变量。请编辑问题并添加您的确切要求,因为创建一个线程而不是等待它然后返回是错误的。maskedOutput
0赞 DuncG 7/13/2023
很难看出使用线程在这里做一些工作会有什么帮助,因为你需要等待任务结束才能将值传递回方法的调用者。
0赞 Sujit Kumar Mishra 7/13/2023
@RealSkeptic,我想将'super.format(event);'设置为String类型变量,并希望从format(LoggingEvent event)方法返回相同的变量。如果将在 format(LoggingEvent event) 方法中声明变量,那么我可以轻松返回相同的变量,但不能使用它来分配 run() 方法中的屏蔽逻辑的结果,因为这不是最终的,如果我将其定为最终的,那么我将无法将结果分配给它。如果我将在 Runnable 实例下声明变量,那么我可以分配结果,但无法从上述方法返回相同的结果。
0赞 Sujit Kumar Mishra 7/13/2023
@RealSkeptic,我无法声明要从类级别返回的变量,我有format(LoggingEvent事件),根据我们的项目要求有一定的限制,是的,还有一件事是,根据我们的项目要求,我们不能将LoggingEvent对象设置为最终对象,但是如果不使LoggingEvent对象成为最终对象,我们就不能在掩码逻辑执行期间在run()方法中使用它。如何在不使 LoggingEvent 成为最终结果的情况下执行 run() 方法中的屏蔽逻辑?如何从format(LoggingEvent事件)方法返回掩码逻辑的结果?
0赞 Community 7/14/2023
请澄清您的具体问题或提供其他详细信息以准确说明您的需求。正如目前所写的那样,很难确切地说出你在问什么。

答:

1赞 Piotr P. Karwasz 7/13/2023 #1

Log4j 1.2 自 2015 年起不再受支持。所有现代替换都具有某种正则表达式替换支持。

Log4j 2.x 中,您可以使用:

<PatternLayout pattern="your_pattern">
  <Replace regex="(\d{4})\d{8}(\d{4})" replacement="$1********$2"/>
</PatternLayout>

<PatternLayout pattern="%replace{your_pattern}{(\d{4})\d{8}(\d{4})}{$1********$2}"/>

Logback 中,您可以使用:

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  <pattern>
    %replace(your_pattern){"(\d{4})\d{8}(\d{4})", "$1********$2"}
  </pattern>
</encoder>