package com.nuzar.fcms.framwork.route.annotations;
import com.nuzar.fcms.framwork.route.enums.InvokeType;
import java.lang.annotation.*;
/**
* description: 接口日志记录
*
* @author shizhiyuan
* @date 2022-12-08 16:29:38
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLogRecord {
//请求路径
String path() default "";
//数据Id
String dataId() default "";
InvokeType invokeType() default InvokeType.INNER;
String apiName() default "";
}
package com.nuzar.fcms.accept.aop;
import cn.hutool.json.JSONUtil;
import com.nuzar.fcms.common.core.business.utils.SpelExpressionUtils;
import com.nuzar.cloud.common.utils.DateUtils;
import com.nuzar.cloud.common.utils.StringUtils;
import com.nuzar.fcms.framwork.route.annotations.ApiLogRecord;
import com.nuzar.fcms.framwork.route.enums.InvokeStatus;
import com.nuzar.fcms.framwork.route.log.model.ApiLog;
import com.nuzar.fcms.framwork.route.log.service.ApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
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.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* description:
*
* @author shizhiyuan
* @date 2022-12-08 16:37:37
*/
@Slf4j
public class ApiLogRecordAspect {
private ApiLogService apiLogService;
@Pointcut("@annotation(com.nuzar.fcms.framwork.route.annotations.ApiLogRecord)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
//执行方法
Object result = null;
ApiLog apiLog = null;
try {
result = point.proceed();
} catch (Throwable e) {
apiLog = new ApiLog();
apiLog.setStatus(InvokeStatus.FAIL.code);
try {
apiLog.setErrorInfo(StringUtils.left(ExceptionUtils.getStackTrace(e), 1000));
} catch (Exception ex) {
log.error("build api_log error:", ex);
}
throw e;
} finally {
//保存日志
try {
saveApiLog(point, apiLog, result);
} catch (Exception e) {
log.error("save api_log error:", e);
}
}
return result;
}
private void saveApiLog(ProceedingJoinPoint joinPoint, ApiLog apiLog, Object result) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (Objects.isNull(method)) {
return;
}
ApiLogRecord apiLogRecord = method.getAnnotation(ApiLogRecord.class);
if (Objects.isNull(apiLogRecord)) {
return;
}
if (Objects.isNull(apiLog)) {
apiLog = new ApiLog();
apiLog.setStatus(InvokeStatus.SUCCESS.code);
}
apiLog.setDataId(SpelExpressionUtils.generateKeyBySpEL(apiLogRecord.dataId(), joinPoint));
apiLog.setPath(apiLogRecord.path());
apiLog.setType(apiLogRecord.invokeType().code);
apiLog.setRequest(JSONUtil.toJsonStr(joinPoint.getArgs()));
apiLog.setResponse(JSONUtil.toJsonStr(result));
apiLog.setInvokeTime(DateUtils.getNow());
apiLog.setApiName(apiLogRecord.apiName());
apiLogService.save(apiLog);
}
@Autowired
public void setApiLogService(ApiLogService apiLogService) {
this.apiLogService = apiLogService;
}
}
package com.nuzar.fcms.framwork.route.log.model;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
/**
* api调用日志数据库实体
*
* @author tangang
*/
@Data
@TableName("API_LOG")
@Schema(name = "api日志", description = "api日志")
public class ApiLog {
@Schema(description = "主键ID")
@TableId(value = "id")
private String id;
@Schema(description = "调用类型(0-调出;1-调入)")
@TableField("TYPE")
private Integer type;
@Schema(description = "调用类型")
@TableField(exist = false)
private String typeDesc;
@Schema(description = "请求来源ip")
@TableField("SOURCE_IP")
private String sourceIp;
@Schema(description = "请求目标ip")
@TableField("TARGET_IP")
private String targetIp;
@Schema(description = "调用服务Id")
@TableField("SERVICE_ID")
private String serviceId;
@Schema(description = "api名称")
@TableField("API_NAME")
private String apiName;
@Schema(description = "请求路径")
@TableField("PATH")
private String path;
@Schema(description = "调用状态(0-失败;1-成功)")
@TableField("STATUS")
private Integer status;
@Schema(description = "调用状态")
@TableField(exist = false)
private String statusDesc;
@Schema(description = "请求耗时(单位ms)")
@TableField("DURATION")
private Long duration;
@Schema(description = "请求参数")
@TableField("REQUEST")
private String request;
@Schema(description = "请求数据关联ID")
@TableField("DATA_ID")
private String dataId;
@Schema(description = "响应结果")
@TableField("RESPONSE")
private String response;
@Schema(description = "错误信息")
@TableField("ERROR_INFO")
private String errorInfo;
@Schema(description = "调用时间")
@TableField("INVOKE_TIME")
private Date invokeTime;
@Schema(description = "创建时间")
@TableField(
value = "CREATE_TIME",
fill = FieldFill.INSERT,
updateStrategy = FieldStrategy.NEVER
)
private Date createTime;
}