Я использую конвертер пользовательских шаблонов log4j. Во время выполнения, когда он пытается вызвать метод newInstance класса преобразователя, он завершается ошибкой:
"Ошибка создания конвертера для cm java.lang.IllegalAccessException:
Класс org.apache.logging.log4j.core.pattern.PatternParser не может
получить доступ к члену класса com.test.plugin.LogMaskingConverter с помощью
модификаторы "public static" "
После отладки я обнаружил, что «newInstance» вызывается с помощью Reflection и в классе Reflection перед вызовом метода, который он вызывает «isSameClassPackage» и возвращает false.
одна из возможных причин может заключаться в том, что для загрузки основного и преобразовательного классов используются разные загрузчики классов.
Я попробовал решение, приведенное в приведенной ниже ветке, а также добавил конфигурацию плагина в pom.xml, но ничего из этого не сработало.
В конфигурации log4j2 не будет загружен конвертер пользовательских шаблонов
LogMaskingConverter.java
package com.test.plugin;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
@Plugin(name = "LogMaskingConverter", category = "Converter")
@ConverterKeys({"cm"})
class LogMaskingConverter extends LogEventPatternConverter {
private static final String NAME = "cm";
private static final String JSON_REPLACEMENT_REGEX = "\"\\$1\": \"****\"";
private static final String JSON_KEYS = String.join("|", new String[]{"ssn", "private", "creditCard"});
private static final Pattern JSON_PATTERN = Pattern.compile("(${ssn|card}): ([^]+)");
private static final LogMaskingConverter INSTANCE = new LogMaskingConverter();
private LogMaskingConverter() {
super(NAME, NAME);
}
public static LogMaskingConverter newInstance(final String[] options) {
return INSTANCE;
}
@Override
public void format(LogEvent event, StringBuilder outputMessage) {
String message = event.getMessage().getFormattedMessage();
String maskedMessage = message;
if (event.getMarker().getName() == LoggingMarkers.JSON.getName()) {
try {
maskedMessage = mask(message);
} catch (Exception e) {
maskedMessage = message; // Although if this fails, it may be better to not log the message
}
}
outputMessage.append(maskedMessage);
}
private String mask(String message) {
StringBuffer buffer = new StringBuffer();
Matcher matcher = JSON_PATTERN.matcher(message);
while (matcher.find()) {
matcher.appendReplacement(buffer, JSON_REPLACEMENT_REGEX);
}
matcher.appendTail(buffer);
return buffer.toString();
}
}
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config"
status="all" packages="com.test.plugin">
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern=" %-6level %cm %d{HH:mm:ss.SSS} %msg%n" />
</Console>
</Appenders>
<Loggers>
<Logger level="all" />
<root level="all">
<appender-ref ref="console" level="TRACE" />
</root>
</Loggers>
</Configuration>
основной класс
package com.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.test.plugin.LoggingMarkers;
public class TestLogging {
public static final Logger logger = LoggerFactory.getLogger(TestLogging.class);
public TestLogging() {
logger.info("test info");
logger.debug(LoggingMarkers.JSON, "{\"ssn\": \"1234567890\"}");
}
public static void main(String[] args) {
new TestLogging();
}
}