简体   繁体   中英

Inject spring bean into custom logback filter

in order to reduce the amount of logging present in our application, we decided to enable/disable logging of certain methods on a per-client basis.

public class LoggingFilter extends Filter<ILoggingEvent> {

@Autowired
private MethodNameValidator validator;

@Override
public FilterReply decide(ILoggingEvent event) {
    Map<String, String> mdcProperties = event.getMDCPropertyMap();

    if (mdcProperties.isEmpty()) {
        return FilterReply.ACCEPT;
    }

    String accountId = mdcProperties.get(MDCUtil.ACCOUNT_ID);
    String methodName = mdcProperties.get(MDCUtil.METHOD_NAME);

    if (validator.isValidMethodName(accountId, methodName)) {
        return FilterReply.ACCEPT;
    }

    return FilterReply.DENY;
}

}

The custom filter defined above has a validation component in which the method validation logic is implemented.

The validator is a Spring Bean (which is also exposed via JMX for external configuration).

I fail to inject the MethodNameValidator bean into the filter.

The filter is a bean also.

Is there a way to achieve this?

If I could set a logback filter dynamically then I could initialize my filter as a bean, get the desired logger by name and apply the filter.

Can't figure out how to do it via the provided Logback api.

This works for me.

@Component
public class DiscoveringPostProcessor implements BeanPostProcessor, ApplicationContextAware {

    ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if(bean instanceof CustomLoggingFilter){
            Map<String, TurboFilter> filterBeans = applicationContext.getBeansOfType(TurboFilter.class);
            for (TurboFilter filter : filterBeans.values()) {
                LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
                loggerContext.addTurboFilter(filter);
            }
        }
        return bean;

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}

2.

@Named("customLoggingFilter")
public class CustomLoggingFilter extends TurboFilter {

    @Autowired
    private TestService ts;

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
        System.out.println(ts.doTest());
        return FilterReply.ACCEPT;
    }
}

Thats how we nailed it. Turbo filters instead of event filters. Thx ;)

//filter definition
public class MethodLoggingFilter extends TurboFilter {


private MethodNameValidator  methodNameValidator ;

public MethodLoggingFilter(MethodNameValidator methodNameValidator) {
    this.methodNameValidator = methodNameValidator;
}

@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
    return shouldApplyFilter(level, MDCUtils.getSmsChannelId(), MDCUtils.getMethodName()) ? FilterReply.DENY : FilterReply.NEUTRAL;
}

private boolean shouldApplyFilter(Level level, String accountId, String methodName) {

    if (level == Level.WARN || level == Level.ERROR) {
        return false;//warn and error are logged for any method
    }

    if (methodName == null) {
        return false;
    }

    Integer accountId = accountId != null ? Integer.valueOf(accountId) : null;

    return !methodNameValidator .isLoggingAllowed(accountId, methodName);
}

}
//configuration

    @Bean
public MethodLoggingFilter methodLoggingFilter(MethodNameValidator  methodNameValidator) {
    MethodLoggingFilter filter = new MethodLoggingFilter(methodNameValidator);

    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    loggerContext.addTurboFilter(filter);

    return filter;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM