Как добавить PatternLayout в корневой логгер во время выполнения?

Я использую logback в качестве бэкенда для Slf4j. В настоящее время я настраиваю регистратор, используя logback.xml файл. Моя проблема в том, что конфиденциальная информация регистрируется (вне моего контроля), и я хочу замаскировать эту конфиденциальную информацию. Чтобы замаскировать информацию, я написал кастом PatternLayout класс, который по существу делает:

@Override
public String doLayout(ILoggingEvent event) {
    String message = super.doLayout(event);
    Matcher matcher = sesnsitiveInfoPattern.matcher(message);
    if (matcher.find()) {
        message = matcher.replaceAll("XXX");
    }
    return message;
}

Моя проблема заключается в том, что мне нужно сказать logback, чтобы использовать этот пользовательский макет шаблона. Однако я не хочу добавлять это в конфигурацию XML. Моя текущая конфигурация выглядит так:

<configuration> 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <encoder>
      <layout class="com.my.MaskingPatternLayout"> <!-- here -->
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
      </layout>
    </encoder>
  </appender>

  <root level="info">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

В XML моя желаемая конфигурация будет выглядеть так (но я не хочу использовать XML):

1 ответ

Здравствуйте Макс! Я надеюсь, что вы используете Log4j 2.x, потому что это решение использует подход плагинов, представленный в log4j 2.x . Сначала вы должны создать пакет, в который вы собираетесь поместить классы плагинов, и поместите туда эти два класса:

my.log4j.pluggins.CustomConfigurationFactory:

@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
    @Order(value = 0)
    public class CustomConfigurationFactory extends ConfigurationFactory {

        private Configuration createConfiguration(final String name,
                ConfigurationBuilder<BuiltConfiguration> builder) {
            System.out.println("init logger");
            builder.setConfigurationName(name);
            builder.setStatusLevel(Level.INFO);
            builder.setPackages("my.log4j.pluggins");
            AppenderComponentBuilder appenderBuilder = builder.newAppender(
                    "Stdout", "CONSOLE").addAttribute("target",
                    ConsoleAppender.Target.SYSTEM_OUT);
            appenderBuilder
                    .add(builder
                            .newLayout("PatternLayout")
                            .addAttribute("pattern", "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %myMsg%n"));
            builder.add(appenderBuilder);
            builder.add(builder.newRootLogger(Level.TRACE).add(
                    builder.newAppenderRef("Stdout")));
            return builder.build();
        }

        @Override
        protected String[] getSupportedTypes() {
            String[] supportedExt = { "*" };
            return supportedExt;

        }

        @Override
        public Configuration getConfiguration(ConfigurationSource source) {
            ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
            return createConfiguration(source.toString(), builder);
        }

        @Override
        public Configuration getConfiguration(String name, URI configLocation) {
            ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
            return createConfiguration(name, builder);
        }

    }

my.log4j.pluggins.SampleLayout:

    @Plugin(name = "CustomConverter", category = "Converter")
    @ConverterKeys({"myMsg"})
    public class SampleLayout extends LogEventPatternConverter {

        protected SampleLayout(String name, String style) {
            super(name, style);
        }
        public static SampleLayout newInstance(){
            return new SampleLayout("custConv", "custConv");
        }

        @Override
        public void format(LogEvent event, StringBuilder stringBuilder) {
           //replace the %myMsg by XXXXX if sensitive           
           if (sensitive()){
               stringBuilder.append("XXXX");}
           else {
            stringBuilder.append(event.getMessage().getFormattedMessage());}            
        }   
    }

класс CustomConfiguration отвечает за создание конфигурации log4j и строки 9, где важен 'builder.setPackages("my.log4j.pluggins") ", чтобы отсканировать этот пакет и выбрать подключаемый модуль конвертера SampleLayout. второй класс будет отвечать за форматирование нового ключа "% myMsg" в шаблоне, который содержит мое конфиденциальное сообщение, этот класс преобразователя проверяет, является ли это сообщение чувствительным, и действует ли он соответствующим образом.

Перед началом регистрации вы должны настроить ваш log4j следующим образом

ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory());
Другие вопросы по тегам