异步解耦日志模块实现思路

日志设计文档

日志使我们系统中必不可少的元素,他的特点是比较多。为了不让日志影响我们的正常的业务响应速度,采用了如下设计。

1 采用日志池概念,当业务系统产生一条日志时候,我们直接丢在日志池里面,单独开一个线程把日志池中缓存的日志写入数据库。

2 业务系统解耦,一般的操作我们都想记录用户的ip所以我们可以新建拦截器,当用户请求过来时候可以缓存一个log对象记录请求的ip和用户名,当请求结束时候,清空缓存。业务系统丢日志进来后,先根据线程id查询当前线程中缓存的log。取其中的用户ip和名字

核心代码

a 拦截器实现

public class DefaultExceptionInterceptor implements Interceptor {

	public void intercept(Invocation ai) {
		try{
			Controller controller = ai.getController();
			Log log = new Log();
			log.set("user_ip", ActionFunc.getIp(controller.getRequest()));
			LogFactory.getLogManager().putCache(log);
			
			ai.invoke();
		}
		catch(Exception e) {
			String erroCcode = ResultCode.ERROR.getCode();
			String errorMsg = ResultCode.ERROR.getMsg();
			Controller controller = ai.getController();
			if(e instanceof DmsException) {
				erroCcode = ((DmsException) e).getCode();
				errorMsg = e.getMessage();
			}
			else {
				e.printStackTrace();
			}
			//如果是ajax请求
			if("XMLHttpRequest".equals(controller.getRequest().getHeader("X-Requested-With"))){
				controller.renderJson(ResultJson.getError(erroCcode,errorMsg));
			}
			else {
				controller.setAttr("errorMsg", errorMsg);
				controller.render("/WEB-INF/frame/error.html");
			}
		}
		finally {
			LogFactory.getLogManager().removeCache();
		}
	}
}

b 日志池

public class LogManagerImpl implements LogManager {
	
	protected final static Logger logger = LoggerFactory.getLogger(LogManagerImpl.class);
	
	private List<Log> loglist1 = new ArrayList<Log>();
	private List<Log> loglist2 = new ArrayList<Log>();
	private boolean useList1 = true;
	
	private static Hashtable<Long, Log> logs = new Hashtable<Long, Log>();
	
	private final String sql = "insert into sys_log (partner_id,user_id,user_name,user_ip,detail,log_type,create_time) values(?,?,?,?,?,?,?)";

	@Override
	public void run() {
		while(true) {
			try {
				Thread.sleep(5000l);
				List<Log> freeList = null;
				if(useList1) {
					freeList = loglist2;
				}
				else {
					freeList = loglist1;
				}
				int size = freeList.size(); 
				if(size != 0) {
					Object[][] paramValue=new Object[size][7];
					for(int i=0;i<size;i++) {
						Log temp = freeList.get(i);
						paramValue[i] = new Object[]{temp.get("partner_id"),temp.get("user_id"),temp.get("user_name"),temp.get("user_ip"),temp.get("detail"),temp.get("log_type"),temp.get("create_time")};
					}
					Db.batch(sql, paramValue, 500);
				}
				freeList.clear();
				useList1 = !useList1;
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}

	@Override
	public void addLog(int level, String detail) {
		long threadId = Thread.currentThread().getId();
		Log log = logs.get(threadId);
		if(log == null) {
			log = new Log();
		}
		Log saveLog = new Log();
		saveLog.put("partner_id", log.get("partner_id"));
		saveLog.put("user_id", log.get("user_id"));
		saveLog.put("user_name", log.get("user_name"));
		saveLog.put("user_ip", log.get("user_ip"));
		saveLog.put("log_type", level);
		saveLog.put("detail", detail);
		saveLog.put("create_time", new Date());
		if(useList1) {
			loglist1.add(saveLog);
		}
		else {
			loglist2.add(saveLog);
		}
		
	}

	@Override
	public void putCache(Log log) {
		long threadId = Thread.currentThread().getId();
		logs.put(threadId, log);
	}
	
	@Override
	public Log getCacheLog() {
		long threadId = Thread.currentThread().getId();
		return logs.get(threadId);
	}

	@Override
	public void removeCache() {
		long threadId = Thread.currentThread().getId();
		logs.remove(threadId);
	}
	
}

c 日志记录器

public class LoggerImpl implements Logger {
	
	private LogManager manager = null;
	
	public LoggerImpl(LogManager manager) {
		this.manager = manager;
	}

	@Override
	public void debug(String detail) {
		manager.addLog(LogConst.LEVEL_DEBUG, detail);
	}

	@Override
	public void info(String detail) {
		manager.addLog(LogConst.LEVEL_INFO, detail);
	}

	@Override
	public void warn(String detail) {
		manager.addLog(LogConst.LEVEL_WARN, detail);
	}

	@Override
	public void error(String detail) {
		manager.addLog(LogConst.LEVEL_ERROR, detail);
	}

	@Override
	public void fatal(String detail) {
		manager.addLog(LogConst.LEVEL_FATAL, detail);
	}

}
d 日志调用

	private static Logger logger = LogFactory.getLogger();
	
	/**
	 * 用户登录
	 * @param userId
	 * @param password
	 * @return
	 */
	public static Map<String,Object> doLogin(String partnerId,String userId,String password) {
		Map<String,Object> user = null;
		//如果是超级管理员
		if(StrFunc.compareStr(RestaurantConfig.globalConf.getProperty("adminName"), userId)) {
			user = adminLogin(partnerId, userId, password);
		}
		//普通用户登录
		else {
			user = userLogin(partnerId,userId,password);
		}
		logger.info("登录系统");
		return user;
		
	}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值