捕获项目中的异常信息,并处理、入库

公司的项目是一个爬虫的管理中心,需要对爬虫进行监控,监控它们是不是在正常运行。

从网上搜到的解决方案都是 spring boot 下的,由于公司的项目是老项目,所以不适用。于是想到了从log4j下手,通过自定义Appender,拦截日志,并从日志中提取出我需要的信息入库。然后调用父类的同方法,保证日志以前能干的事不会少了。

由于自定义所考虑的东西太多,所以继承了 DailyRollingFileAppender 减少工作量。

第一反应的写法:

  1. 每当产生一条日志时,根据配置的日志级别进行调用
  2. LoggingEvent 对象内包含了日志内容,如果是异常日志,还会包含整个的异常栈的信息。
  3. 通过LoggingEvent对象的getLevel拿到我们想要的日志级别。
  4. 从日志中解析我们需要的内容
  5. 将日志保存到数据库中
  6. 调用父类的doAppend方法,保证之前逻辑的执行。
        @Override
	public void doAppend(LoggingEvent event) {
		if (isAsSevereAsThreshold(event.getLevel())) {
			if(service == null) {
				init();
			}
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date = new Date(event.getTimeStamp());
			ThrowableInformation throwableInfo = event.getThrowableInformation();
			ExceptionBean eb = parseException(throwableInfo);
			eb.setMessage(event.getMessage().toString());
			
			eb.setTime(df.format(date));
			eb.setLevel(event.getLevel().toString());
			service.save(eb);
		}
		super.doAppend(event);
	}

存在的问题:

由于这个自定义的类是直接通过log4j的配置文件,被加载到内存的,不是spring直接管理的。所以入库需要的资源不能自动注入,也就没有办法入库了。

解决方案:

虽然这个自定义类不是spring直接管理的,但是我可以拿到spring的上下文信息啊

拿到了spring的上下文信息之后,通过其获取我需要的 Bean 并存起来,不就可以实现入库了吗

SpringContextUtil类代码:

public class SpringContextUtil {

	private static ApplicationContext applicationContext = null;
	
	private synchronized static void init() {
		if(applicationContext == null) { 
			ServletContext sc = ContextLoader.getCurrentWebApplicationContext().getServletContext();
			applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
		}
	}

	public static Object getBean(String beanName) {
		return applicationContext.getBean(beanName);
	}

	public static Object getBean(Class c) {
		if(applicationContext == null) {
			init();
		}
		return applicationContext.getBean(c);
	}
}

再次遇到问题:

由于我在 Appender 初始化的时候就去调用 SpringContextUtil 去获取 Service 层的 Bean,看起来是没有问题的。但是系统在启动的时候也是要打日志的啊,这个时候 SpringContext 还没有初始化,于是便出问题了。

最后的解决方案是,用一个懒加载的办法去获取 Bean 这样就避免了初始化 Bean 的时候出现的问题。

初始化 Service Bean 的代码:

private synchronized void init() {
	if(service == null) {
		service = (ExceptionService) SpringContextUtil.getBean(ExceptionService.class);
	}
}

这段代码调用是在最开始那段代码,为了防止出现并发问题,所以在外层也做了 null 值判断。

水平有限,若有错误,请指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值