28 changed files with 20 additions and 543 deletions
			
			
		@ -1,95 +0,0 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright (c) 2018 人人开源 All rights reserved. | 
				
			|||
 * | 
				
			|||
 * https://www.renren.io
 | 
				
			|||
 * | 
				
			|||
 * 版权所有,侵权必究! | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.log; | 
				
			|||
 | 
				
			|||
import com.epmet.commons.tools.exception.ExceptionUtils; | 
				
			|||
import com.epmet.commons.tools.log.BaseLog; | 
				
			|||
import com.epmet.commons.tools.log.enums.LogTypeEnum; | 
				
			|||
import com.epmet.commons.tools.redis.RedisKeys; | 
				
			|||
import com.epmet.commons.tools.redis.RedisUtils; | 
				
			|||
import com.epmet.commons.tools.utils.ConvertUtils; | 
				
			|||
import com.epmet.entity.SysLogErrorEntity; | 
				
			|||
import com.epmet.entity.SysLogLoginEntity; | 
				
			|||
import com.epmet.entity.SysLogOperationEntity; | 
				
			|||
import com.epmet.service.SysLogErrorService; | 
				
			|||
import com.epmet.service.SysLogLoginService; | 
				
			|||
import com.epmet.service.SysLogOperationService; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.apache.commons.lang3.concurrent.BasicThreadFactory; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.boot.CommandLineRunner; | 
				
			|||
import org.springframework.stereotype.Component; | 
				
			|||
 | 
				
			|||
import java.util.concurrent.ScheduledExecutorService; | 
				
			|||
import java.util.concurrent.ScheduledThreadPoolExecutor; | 
				
			|||
import java.util.concurrent.TimeUnit; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 从Redis队列中获取Log,保存到DB | 
				
			|||
 * | 
				
			|||
 * @author Mark sunlightcs@gmail.com | 
				
			|||
 * @since 1.0.0 | 
				
			|||
 */ | 
				
			|||
@Slf4j | 
				
			|||
@Component | 
				
			|||
public class LogConsumer implements CommandLineRunner { | 
				
			|||
    @Autowired | 
				
			|||
    private RedisUtils redisUtils; | 
				
			|||
    @Autowired | 
				
			|||
    private SysLogErrorService sysLogErrorService; | 
				
			|||
    @Autowired | 
				
			|||
    private SysLogLoginService sysLogLoginService; | 
				
			|||
    @Autowired | 
				
			|||
    private SysLogOperationService sysLogOperationService; | 
				
			|||
    private ScheduledExecutorService scheduledService = new ScheduledThreadPoolExecutor(1, | 
				
			|||
            new BasicThreadFactory.Builder().namingPattern("log-consumer-schedule-pool-%d").daemon(true).build()); | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public void run(String... args) { | 
				
			|||
        //上次任务结束后,等待10秒钟,再执行下次任务
 | 
				
			|||
        scheduledService.scheduleWithFixedDelay(() -> { | 
				
			|||
            try { | 
				
			|||
                receiveQueue(); | 
				
			|||
            }catch (Exception e){ | 
				
			|||
                log.error("LogConsumer Error:"+ ExceptionUtils.getErrorStackTrace(e)); | 
				
			|||
            } | 
				
			|||
        }, 1, 10, TimeUnit.SECONDS); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private void receiveQueue() { | 
				
			|||
        String key = RedisKeys.getSysLogKey(); | 
				
			|||
        //每次插入100条
 | 
				
			|||
        int count = 100; | 
				
			|||
        for(int i = 0; i < count; i++){ | 
				
			|||
            BaseLog log = (BaseLog) redisUtils.rightPop(key); | 
				
			|||
            if(log == null){ | 
				
			|||
                return; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            //登录日志
 | 
				
			|||
            if(log.getType() == LogTypeEnum.LOGIN.value()){ | 
				
			|||
                SysLogLoginEntity entity = ConvertUtils.sourceToTarget(log, SysLogLoginEntity.class); | 
				
			|||
                sysLogLoginService.save(entity); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            //操作日志
 | 
				
			|||
            if(log.getType() == LogTypeEnum.OPERATION.value()){ | 
				
			|||
                SysLogOperationEntity entity = ConvertUtils.sourceToTarget(log, SysLogOperationEntity.class); | 
				
			|||
                sysLogOperationService.save(entity); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            //异常日志
 | 
				
			|||
            if(log.getType() == LogTypeEnum.ERROR.value()){ | 
				
			|||
                SysLogErrorEntity entity = ConvertUtils.sourceToTarget(log, SysLogErrorEntity.class); | 
				
			|||
                sysLogErrorService.save(entity); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -1,24 +0,0 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright (c) 2018 人人开源 All rights reserved. | 
				
			|||
 * | 
				
			|||
 * https://www.renren.io
 | 
				
			|||
 * | 
				
			|||
 * 版权所有,侵权必究! | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.commons.tools.annotation; | 
				
			|||
 | 
				
			|||
import java.lang.annotation.*; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 操作日志注解 | 
				
			|||
 * | 
				
			|||
 * @author Mark sunlightcs@gmail.com | 
				
			|||
 * @since 1.0.0 | 
				
			|||
 */ | 
				
			|||
@Target(ElementType.METHOD) | 
				
			|||
@Retention(RetentionPolicy.RUNTIME) | 
				
			|||
@Documented | 
				
			|||
public @interface LogOperation { | 
				
			|||
    String value() default ""; | 
				
			|||
} | 
				
			|||
@ -1,121 +0,0 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright (c) 2018 人人开源 All rights reserved. | 
				
			|||
 * | 
				
			|||
 * https://www.renren.io
 | 
				
			|||
 * | 
				
			|||
 * 版权所有,侵权必究! | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.commons.tools.aspect; | 
				
			|||
 | 
				
			|||
import com.alibaba.fastjson.JSON; | 
				
			|||
import com.epmet.commons.tools.annotation.LogOperation; | 
				
			|||
import com.epmet.commons.tools.config.ModuleConfig; | 
				
			|||
import com.epmet.commons.tools.security.user.SecurityUser; | 
				
			|||
import com.epmet.commons.tools.log.SysLogOperation; | 
				
			|||
import com.epmet.commons.tools.log.enums.LogTypeEnum; | 
				
			|||
import com.epmet.commons.tools.log.enums.OperationStatusEnum; | 
				
			|||
import com.epmet.commons.tools.log.producer.LogProducer; | 
				
			|||
import com.epmet.commons.tools.security.user.UserDetail; | 
				
			|||
import com.epmet.commons.tools.utils.HttpContextUtils; | 
				
			|||
import com.epmet.commons.tools.utils.IpUtils; | 
				
			|||
import org.aspectj.lang.ProceedingJoinPoint; | 
				
			|||
import org.aspectj.lang.annotation.Around; | 
				
			|||
import org.aspectj.lang.annotation.Aspect; | 
				
			|||
import org.aspectj.lang.annotation.Pointcut; | 
				
			|||
import org.aspectj.lang.reflect.MethodSignature; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.http.HttpHeaders; | 
				
			|||
import org.springframework.stereotype.Component; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletRequest; | 
				
			|||
import java.lang.reflect.Method; | 
				
			|||
import java.util.Date; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 操作日志,切面处理类 | 
				
			|||
 * | 
				
			|||
 * @author Mark sunlightcs@gmail.com | 
				
			|||
 * @since 1.0.0 | 
				
			|||
 */ | 
				
			|||
@Aspect | 
				
			|||
@Component | 
				
			|||
public class LogOperationAspect { | 
				
			|||
    @Autowired | 
				
			|||
    private ModuleConfig moduleConfig; | 
				
			|||
    @Autowired | 
				
			|||
    private LogProducer logProducer; | 
				
			|||
 | 
				
			|||
    @Pointcut("@annotation(com.epmet.commons.tools.annotation.LogOperation)") | 
				
			|||
    public void logPointCut() { | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Around("logPointCut()") | 
				
			|||
    public Object around(ProceedingJoinPoint point) throws Throwable { | 
				
			|||
        long beginTime = System.currentTimeMillis(); | 
				
			|||
        try { | 
				
			|||
            //执行方法
 | 
				
			|||
            Object result = point.proceed(); | 
				
			|||
 | 
				
			|||
            //执行时长(毫秒)
 | 
				
			|||
            long time = System.currentTimeMillis() - beginTime; | 
				
			|||
            //保存日志
 | 
				
			|||
            saveLog(point, time, OperationStatusEnum.SUCCESS.value()); | 
				
			|||
 | 
				
			|||
            return result; | 
				
			|||
        }catch(Exception e) { | 
				
			|||
            //执行时长(毫秒)
 | 
				
			|||
            long time = System.currentTimeMillis() - beginTime; | 
				
			|||
            //保存日志
 | 
				
			|||
            saveLog(point, time, OperationStatusEnum.FAIL.value()); | 
				
			|||
 | 
				
			|||
            throw e; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status) { | 
				
			|||
        MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | 
				
			|||
        Method method = signature.getMethod(); | 
				
			|||
 | 
				
			|||
        SysLogOperation log = new SysLogOperation(); | 
				
			|||
        LogOperation annotation = method.getAnnotation(LogOperation.class); | 
				
			|||
        if(annotation != null){ | 
				
			|||
            //注解上的描述
 | 
				
			|||
            log.setOperation(annotation.value()); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        //登录用户信息
 | 
				
			|||
        UserDetail user = SecurityUser.getUser(); | 
				
			|||
        if(user != null){ | 
				
			|||
            log.setCreator(user.getId()); | 
				
			|||
            log.setCreatorName(user.getUsername()); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        log.setType(LogTypeEnum.OPERATION.value()); | 
				
			|||
        log.setModule(moduleConfig.getName()); | 
				
			|||
        log.setStatus(status); | 
				
			|||
        log.setRequestTime((int)time); | 
				
			|||
        log.setCreateDate(new Date()); | 
				
			|||
 | 
				
			|||
        //请求相关信息
 | 
				
			|||
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); | 
				
			|||
        log.setIp(IpUtils.getIpAddr(request)); | 
				
			|||
        log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); | 
				
			|||
        log.setRequestUri(request.getRequestURI()); | 
				
			|||
        log.setRequestMethod(request.getMethod()); | 
				
			|||
 | 
				
			|||
        //请求参数
 | 
				
			|||
        Object[] args = joinPoint.getArgs(); | 
				
			|||
        try{ | 
				
			|||
            String params = JSON.toJSONString(args[0]); | 
				
			|||
            log.setRequestParams(params); | 
				
			|||
        }catch (Exception e){ | 
				
			|||
 | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        //保存到Redis队列里
 | 
				
			|||
        logProducer.saveLog(log); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,153 +0,0 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright (c) 2018 人人开源 All rights reserved. | 
				
			|||
 * | 
				
			|||
 * https://www.renren.io
 | 
				
			|||
 * | 
				
			|||
 * 版权所有,侵权必究! | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.commons.tools.exception; | 
				
			|||
 | 
				
			|||
import cn.hutool.core.map.MapUtil; | 
				
			|||
import com.alibaba.fastjson.JSON; | 
				
			|||
import com.epmet.commons.tools.config.ModuleConfig; | 
				
			|||
import com.epmet.commons.tools.log.SysLogError; | 
				
			|||
import com.epmet.commons.tools.log.enums.LogTypeEnum; | 
				
			|||
import com.epmet.commons.tools.log.producer.LogProducer; | 
				
			|||
import com.epmet.commons.tools.security.user.LoginUserUtil; | 
				
			|||
import com.epmet.commons.tools.utils.HttpContextUtils; | 
				
			|||
import com.epmet.commons.tools.utils.IpUtils; | 
				
			|||
import com.epmet.commons.tools.utils.Result; | 
				
			|||
import org.slf4j.Logger; | 
				
			|||
import org.slf4j.LoggerFactory; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.dao.DuplicateKeyException; | 
				
			|||
import org.springframework.http.HttpHeaders; | 
				
			|||
import org.springframework.web.bind.annotation.ExceptionHandler; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletRequest; | 
				
			|||
import java.util.Date; | 
				
			|||
import java.util.Map; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 异常处理器 | 
				
			|||
 * 暂停使用,改用BaseRequestLogAspect | 
				
			|||
 * @author Mark sunlightcs@gmail.com | 
				
			|||
 * @since 1.0.0 | 
				
			|||
 */ | 
				
			|||
//@RestControllerAdvice
 | 
				
			|||
public class RenExceptionHandler { | 
				
			|||
	private static final Logger logger = LoggerFactory.getLogger(RenExceptionHandler.class); | 
				
			|||
	@Autowired | 
				
			|||
	private ModuleConfig moduleConfig; | 
				
			|||
	@Autowired | 
				
			|||
	private LogProducer logProducer; | 
				
			|||
	@Autowired | 
				
			|||
	private LoginUserUtil loginUserUtil; | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 处理自定义异常 | 
				
			|||
	 * "code": 8000, | 
				
			|||
	 * "msg": "服务器开小差了...", | 
				
			|||
	 */ | 
				
			|||
	@ExceptionHandler(RenException.class) | 
				
			|||
	public Result handleRRException(RenException ex){ | 
				
			|||
		if (ex.getCode() > 8000) { | 
				
			|||
			Result result=new Result().error(ex.getCode()); | 
				
			|||
			result.setData(ex.getInternalMsg()); | 
				
			|||
			return result; | 
				
			|||
		} | 
				
			|||
		logger.error(ExceptionUtils.getErrorStackTrace(ex)); | 
				
			|||
		Result result=new Result().error(); | 
				
			|||
		result.setData(ex.getInternalMsg()); | 
				
			|||
		return result; | 
				
			|||
//		return new Result().error();
 | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 处理自定义异常 | 
				
			|||
	 * "code": 8000, | 
				
			|||
	 * "msg": "服务器开小差了...", | 
				
			|||
	 */ | 
				
			|||
	@ExceptionHandler(ValidateException.class) | 
				
			|||
	public Result handleVException(ValidateException ex){ | 
				
			|||
		logger.error(ExceptionUtils.getErrorStackTrace(ex)); | 
				
			|||
		Result result=new Result(); | 
				
			|||
		result.setCode(ex.getCode()); | 
				
			|||
		result.setMsg(ex.getMsg()); | 
				
			|||
		return result; | 
				
			|||
//		return new Result().error();
 | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 运行时异常拦截 | 
				
			|||
	 * "code": 8000, | 
				
			|||
	 * "msg": "服务器开小差了...", | 
				
			|||
	 */ | 
				
			|||
	@ExceptionHandler(RuntimeException.class) | 
				
			|||
	public Result handleRuntimeException(RuntimeException ex){ | 
				
			|||
		logger.error(ExceptionUtils.getErrorStackTrace(ex)); | 
				
			|||
		Result result=new Result().error(); | 
				
			|||
		result.setData(ex.getMessage()); | 
				
			|||
		return result; | 
				
			|||
//		return new Result().error();
 | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 处理自定义异常 | 
				
			|||
	 * "code": 10002, | 
				
			|||
	 * "msg": "数据库中已存在该记录", | 
				
			|||
	 */ | 
				
			|||
	@ExceptionHandler(DuplicateKeyException.class) | 
				
			|||
	public Result handleDuplicateKeyException(DuplicateKeyException ex){ | 
				
			|||
		logger.error(ExceptionUtils.getErrorStackTrace(ex)); | 
				
			|||
		return new Result().error(ErrorCode.DB_RECORD_EXISTS); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 异常 | 
				
			|||
	 * "code": 8000, | 
				
			|||
	 * "msg": "服务器开小差了...", | 
				
			|||
	 */ | 
				
			|||
	@ExceptionHandler(Exception.class) | 
				
			|||
	public Result handleException(Exception ex){ | 
				
			|||
		logger.error(ExceptionUtils.getErrorStackTrace(ex)); | 
				
			|||
//		saveLog(ex);
 | 
				
			|||
		Result result=new Result().error(); | 
				
			|||
		result.setData(ex.getMessage()); | 
				
			|||
		return result; | 
				
			|||
//		return new Result().error();
 | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 保存异常日志 | 
				
			|||
	 */ | 
				
			|||
	private void saveLog(Exception ex){ | 
				
			|||
		SysLogError log = new SysLogError(); | 
				
			|||
		log.setType(LogTypeEnum.ERROR.value()); | 
				
			|||
		log.setModule(moduleConfig.getName()); | 
				
			|||
 | 
				
			|||
		//请求相关信息
 | 
				
			|||
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); | 
				
			|||
		log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); | 
				
			|||
		log.setRequestUri(request.getRequestURI()); | 
				
			|||
		log.setRequestMethod(request.getMethod()); | 
				
			|||
		log.setIp(IpUtils.getIpAddr(request)); | 
				
			|||
		Map<String, String> params = HttpContextUtils.getParameterMap(request); | 
				
			|||
		if(MapUtil.isNotEmpty(params)){ | 
				
			|||
			log.setRequestParams(JSON.toJSONString(params)); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		//登录用户ID
 | 
				
			|||
 | 
				
			|||
		log.setCreator(loginUserUtil.getLoginUserId()); | 
				
			|||
		//异常信息
 | 
				
			|||
		log.setErrorInfo(ExceptionUtils.getErrorStackTrace(ex)); | 
				
			|||
 | 
				
			|||
		//保存到Redis队列里
 | 
				
			|||
		log.setCreateDate(new Date()); | 
				
			|||
		logProducer.saveLog(log); | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
@ -1,43 +0,0 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright (c) 2018 人人开源 All rights reserved. | 
				
			|||
 * | 
				
			|||
 * https://www.renren.io
 | 
				
			|||
 * | 
				
			|||
 * 版权所有,侵权必究! | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.commons.tools.log.producer; | 
				
			|||
 | 
				
			|||
import com.google.common.util.concurrent.ThreadFactoryBuilder; | 
				
			|||
import com.epmet.commons.tools.log.BaseLog; | 
				
			|||
import com.epmet.commons.tools.redis.RedisKeys; | 
				
			|||
import com.epmet.commons.tools.redis.RedisUtils; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.stereotype.Component; | 
				
			|||
 | 
				
			|||
import java.util.concurrent.*; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 日志通过redis队列,异步保存到数据库 | 
				
			|||
 * | 
				
			|||
 * @author Mark sunlightcs@gmail.com | 
				
			|||
 * @since 1.0.0 | 
				
			|||
 */ | 
				
			|||
@Component | 
				
			|||
public class LogProducer { | 
				
			|||
    @Autowired | 
				
			|||
    private RedisUtils redisUtils; | 
				
			|||
    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("log-producer-pool-%d").build(); | 
				
			|||
    ExecutorService pool = new ThreadPoolExecutor(5, 200, 0L,TimeUnit.MILLISECONDS, | 
				
			|||
            new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 保存Log到Redis消息队列 | 
				
			|||
     */ | 
				
			|||
    public void saveLog(BaseLog log){ | 
				
			|||
        String key = RedisKeys.getSysLogKey(); | 
				
			|||
 | 
				
			|||
        //异步保存到队列
 | 
				
			|||
        pool.execute(() -> redisUtils.leftPush(key, log, RedisUtils.NOT_EXPIRE)); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
					Loading…
					
					
				
		Reference in new issue