将 spring bean 注入自定义 logback 过滤器
Inject spring bean into custom logback filter
为了减少应用程序中的日志记录量,我们决定
enable/disable 以每个客户端为基础记录某些方法。
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;
}
}
上面定义的自定义过滤器有一个验证组件,其中实现了方法验证逻辑。
验证器是一个 Spring Bean(它也通过 JMX 公开用于外部配置)。
我未能将 MethodNameValidator bean 注入过滤器。
过滤器也是一个bean。
有办法实现吗?
如果我可以动态设置一个 logback 过滤器
然后我可以将过滤器初始化为 bean,获取所需的记录器
按名称并应用过滤器。
无法通过提供的 Logback 弄清楚如何做到这一点 api。
这对我有用。
@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;
}
}
这就是我们成功的方式。 Turbo 过滤器而不是事件过滤器。谢谢 ;)
//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;
}
为了减少应用程序中的日志记录量,我们决定 enable/disable 以每个客户端为基础记录某些方法。
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;
}
}
上面定义的自定义过滤器有一个验证组件,其中实现了方法验证逻辑。
验证器是一个 Spring Bean(它也通过 JMX 公开用于外部配置)。
我未能将 MethodNameValidator bean 注入过滤器。
过滤器也是一个bean。
有办法实现吗?
如果我可以动态设置一个 logback 过滤器 然后我可以将过滤器初始化为 bean,获取所需的记录器 按名称并应用过滤器。
无法通过提供的 Logback 弄清楚如何做到这一点 api。
这对我有用。
@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;
}
}
这就是我们成功的方式。 Turbo 过滤器而不是事件过滤器。谢谢 ;)
//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;
}