Commit 19a461b3cf4109f4c73ed7ab2d8480fc21f06b34
1 parent
9034da66
初始化 API 错误日志模块的代码
Showing
12 changed files
with
417 additions
and
62 deletions
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java
| ... | ... | @@ -68,20 +68,20 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { |
| 68 | 68 | |
| 69 | 69 | private void createApiAccessLog(HttpServletRequest request, Date beginTime, |
| 70 | 70 | Map<String, String> queryString, String requestBody, Exception ex) { |
| 71 | + ApiAccessLogCreateDTO accessLog = new ApiAccessLogCreateDTO(); | |
| 71 | 72 | try { |
| 72 | - ApiAccessLogCreateDTO accessLog = this.buildApiAccessLogDTO(request, beginTime, queryString, requestBody, ex); | |
| 73 | + this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); | |
| 73 | 74 | apiAccessLogFrameworkService.createApiAccessLogAsync(accessLog); |
| 74 | - } catch (Exception e) { | |
| 75 | - log.error("[createApiAccessLog][url({}) 发生异常]", request.getRequestURI(), e); | |
| 75 | + } catch (Throwable th) { | |
| 76 | + log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), JsonUtils.toJsonString(accessLog), th); | |
| 76 | 77 | } |
| 77 | 78 | } |
| 78 | 79 | |
| 79 | - private ApiAccessLogCreateDTO buildApiAccessLogDTO(HttpServletRequest request, Date beginTime, | |
| 80 | - Map<String, String> queryString, String requestBody, Exception ex) { | |
| 81 | - ApiAccessLogCreateDTO accessLog = new ApiAccessLogCreateDTO(); | |
| 80 | + private void buildApiAccessLogDTO(ApiAccessLogCreateDTO accessLog, HttpServletRequest request, Date beginTime, | |
| 81 | + Map<String, String> queryString, String requestBody, Exception ex) { | |
| 82 | 82 | // 处理用户信息 |
| 83 | 83 | accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); |
| 84 | - accessLog.setUserType(WebFrameworkUtils.getUsrType(request)); | |
| 84 | + accessLog.setUserType(WebFrameworkUtils.getUesrType(request)); | |
| 85 | 85 | // 设置访问结果 |
| 86 | 86 | CommonResult<?> result = WebFrameworkUtils.getCommonResult(request); |
| 87 | 87 | if (result != null) { |
| ... | ... | @@ -107,7 +107,6 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { |
| 107 | 107 | accessLog.setBeginTime(beginTime); |
| 108 | 108 | accessLog.setEndTime(new Date()); |
| 109 | 109 | accessLog.setDuration((int) DateUtils.diff(accessLog.getEndTime(), accessLog.getBeginTime())); |
| 110 | - return accessLog; | |
| 111 | 110 | } |
| 112 | 111 | |
| 113 | 112 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.logger.apilog.core.service; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; | |
| 4 | + | |
| 5 | +import javax.validation.Valid; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * API 错误日志 Framework Service 接口 | |
| 9 | + * | |
| 10 | + * @author 芋道源码 | |
| 11 | + */ | |
| 12 | +public interface ApiErrorLogFrameworkService { | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 创建 API 错误日志 | |
| 16 | + * | |
| 17 | + * @param createDTO 创建信息 | |
| 18 | + */ | |
| 19 | + void createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO); | |
| 20 | + | |
| 21 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiErrorLogCreateDTO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.logger.apilog.core.service.dto; | |
| 2 | + | |
| 3 | +import lombok.Data; | |
| 4 | +import lombok.experimental.Accessors; | |
| 5 | + | |
| 6 | +import javax.validation.constraints.NotNull; | |
| 7 | +import java.io.Serializable; | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * API 错误日志创建 DTO | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@Data | |
| 16 | +@Accessors(chain = true) | |
| 17 | +public class ApiErrorLogCreateDTO implements Serializable { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 链路编号 | |
| 21 | + */ | |
| 22 | + private String traceId; | |
| 23 | + /** | |
| 24 | + * 账号编号 | |
| 25 | + */ | |
| 26 | + private Long userId; | |
| 27 | + /** | |
| 28 | + * 用户类型 | |
| 29 | + */ | |
| 30 | + private Integer userType; | |
| 31 | + /** | |
| 32 | + * 应用名 | |
| 33 | + */ | |
| 34 | + @NotNull(message = "应用名不能为空") | |
| 35 | + private String applicationName; | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * 请求方法名 | |
| 39 | + */ | |
| 40 | + @NotNull(message = "http 请求方法不能为空") | |
| 41 | + private String requestMethod; | |
| 42 | + /** | |
| 43 | + * 访问地址 | |
| 44 | + */ | |
| 45 | + @NotNull(message = "访问地址不能为空") | |
| 46 | + private String requestUrl; | |
| 47 | + /** | |
| 48 | + * 请求参数 | |
| 49 | + */ | |
| 50 | + @NotNull(message = "请求参数不能为空") | |
| 51 | + private String requestParams; | |
| 52 | + /** | |
| 53 | + * 用户 IP | |
| 54 | + */ | |
| 55 | + @NotNull(message = "ip 不能为空") | |
| 56 | + private String userIp; | |
| 57 | + /** | |
| 58 | + * 浏览器 UA | |
| 59 | + */ | |
| 60 | + @NotNull(message = "User-Agent 不能为空") | |
| 61 | + private String userAgent; | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * 异常时间 | |
| 65 | + */ | |
| 66 | + @NotNull(message = "异常时间不能为空") | |
| 67 | + private Date exceptionTime; | |
| 68 | + /** | |
| 69 | + * 异常名 | |
| 70 | + */ | |
| 71 | + @NotNull(message = "异常名不能为空") | |
| 72 | + private String exceptionName; | |
| 73 | + /** | |
| 74 | + * 异常发生的类全名 | |
| 75 | + */ | |
| 76 | + @NotNull(message = "异常发生的类全名不能为空") | |
| 77 | + private String exceptionClassName; | |
| 78 | + /** | |
| 79 | + * 异常发生的类文件 | |
| 80 | + */ | |
| 81 | + @NotNull(message = "异常发生的类文件不能为空") | |
| 82 | + private String exceptionFileName; | |
| 83 | + /** | |
| 84 | + * 异常发生的方法名 | |
| 85 | + */ | |
| 86 | + @NotNull(message = "异常发生的方法名不能为空") | |
| 87 | + private String exceptionMethodName; | |
| 88 | + /** | |
| 89 | + * 异常发生的方法所在行 | |
| 90 | + */ | |
| 91 | + @NotNull(message = "异常发生的方法所在行不能为空") | |
| 92 | + private Integer exceptionLineNumber; | |
| 93 | + /** | |
| 94 | + * 异常的栈轨迹异常的栈轨迹 | |
| 95 | + */ | |
| 96 | + @NotNull(message = "异常的栈轨迹不能为空") | |
| 97 | + private String exceptionStackTrace; | |
| 98 | + /** | |
| 99 | + * 异常导致的根消息 | |
| 100 | + */ | |
| 101 | + @NotNull(message = "异常导致的根消息不能为空") | |
| 102 | + private String exceptionRootCauseMessage; | |
| 103 | + /** | |
| 104 | + * 异常导致的消息 | |
| 105 | + */ | |
| 106 | + @NotNull(message = "异常导致的消息不能为空") | |
| 107 | + private String exceptionMessage; | |
| 108 | + | |
| 109 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/package-info.java deleted
| 1 | -package cn.iocoder.dashboard.framework.logger.apilog.core.service; |
src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java
| 1 | 1 | package cn.iocoder.dashboard.framework.web.core.handler; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.exceptions.ExceptionUtil; | |
| 4 | +import cn.hutool.core.map.MapUtil; | |
| 5 | +import cn.hutool.extra.servlet.ServletUtil; | |
| 3 | 6 | import cn.iocoder.dashboard.common.exception.GlobalException; |
| 4 | 7 | import cn.iocoder.dashboard.common.exception.ServiceException; |
| 5 | 8 | import cn.iocoder.dashboard.common.pojo.CommonResult; |
| 9 | +import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService; | |
| 10 | +import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; | |
| 6 | 11 | import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; |
| 12 | +import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; | |
| 13 | +import cn.iocoder.dashboard.framework.web.core.util.WebFrameworkUtils; | |
| 14 | +import cn.iocoder.dashboard.util.json.JsonUtils; | |
| 15 | +import cn.iocoder.dashboard.util.servlet.ServletUtils; | |
| 7 | 16 | import io.github.resilience4j.ratelimiter.RequestNotPermitted; |
| 8 | 17 | import lombok.extern.slf4j.Slf4j; |
| 18 | +import org.apache.commons.lang3.exception.ExceptionUtils; | |
| 19 | +import org.springframework.beans.factory.annotation.Value; | |
| 9 | 20 | import org.springframework.security.access.AccessDeniedException; |
| 21 | +import org.springframework.util.Assert; | |
| 10 | 22 | import org.springframework.validation.BindException; |
| 11 | 23 | import org.springframework.validation.FieldError; |
| 12 | 24 | import org.springframework.web.HttpRequestMethodNotSupportedException; |
| ... | ... | @@ -17,10 +29,13 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; |
| 17 | 29 | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; |
| 18 | 30 | import org.springframework.web.servlet.NoHandlerFoundException; |
| 19 | 31 | |
| 32 | +import javax.annotation.Resource; | |
| 20 | 33 | import javax.servlet.http.HttpServletRequest; |
| 21 | 34 | import javax.validation.ConstraintViolation; |
| 22 | 35 | import javax.validation.ConstraintViolationException; |
| 23 | 36 | import javax.validation.ValidationException; |
| 37 | +import java.util.Date; | |
| 38 | +import java.util.Map; | |
| 24 | 39 | |
| 25 | 40 | import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.*; |
| 26 | 41 | |
| ... | ... | @@ -33,6 +48,12 @@ import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstan |
| 33 | 48 | @Slf4j |
| 34 | 49 | public class GlobalExceptionHandler { |
| 35 | 50 | |
| 51 | + @Value("spring.application.name") | |
| 52 | + private String applicationName; | |
| 53 | + | |
| 54 | + @Resource | |
| 55 | + private ApiErrorLogFrameworkService apiErrorLogFrameworkService; | |
| 56 | + | |
| 36 | 57 | /** |
| 37 | 58 | * 处理所有异常,主要是提供给 Filter 使用 |
| 38 | 59 | * 因为 Filter 不走 SpringMVC 的流程,但是我们又需要兜底处理异常,所以这里提供一个全量的异常处理过程,保持逻辑统一。 |
| ... | ... | @@ -232,57 +253,47 @@ public class GlobalExceptionHandler { |
| 232 | 253 | return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMessage()); |
| 233 | 254 | } |
| 234 | 255 | |
| 235 | - // TODO 芋艿:增加异常日志 | |
| 236 | - public void createExceptionLog(HttpServletRequest req, Throwable e) { | |
| 237 | -// // 插入异常日志 | |
| 238 | -// SystemExceptionLogCreateDTO exceptionLog = new SystemExceptionLogCreateDTO(); | |
| 239 | -// try { | |
| 240 | -// // 增加异常计数 metrics TODO 暂时去掉 | |
| 241 | -//// EXCEPTION_COUNTER.increment(); | |
| 242 | -// // 初始化 exceptionLog | |
| 243 | -// initExceptionLog(exceptionLog, req, e); | |
| 244 | -// // 执行插入 exceptionLog | |
| 245 | -// createExceptionLog(exceptionLog); | |
| 246 | -// } catch (Throwable th) { | |
| 247 | -// log.error("[createExceptionLog][插入访问日志({}) 发生异常({})", JSON.toJSONString(exceptionLog), ExceptionUtils.getRootCauseMessage(th)); | |
| 248 | -// } | |
| 256 | + private void createExceptionLog(HttpServletRequest req, Throwable e) { | |
| 257 | + // 插入错误日志 | |
| 258 | + ApiErrorLogCreateDTO errorLog = new ApiErrorLogCreateDTO(); | |
| 259 | + try { | |
| 260 | + // 初始化 errorLog | |
| 261 | + initExceptionLog(errorLog, req, e); | |
| 262 | + // 执行插入 errorLog | |
| 263 | + apiErrorLogFrameworkService.createApiErrorLogAsync(errorLog); | |
| 264 | + } catch (Throwable th) { | |
| 265 | + log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th); | |
| 266 | + } | |
| 249 | 267 | } |
| 250 | 268 | |
| 251 | -// // TODO 优化点:后续可以增加事件 | |
| 252 | -// @Async | |
| 253 | -// public void createExceptionLog(SystemExceptionLogCreateDTO exceptionLog) { | |
| 254 | -// try { | |
| 255 | -// systemExceptionLogRpc.createSystemExceptionLog(exceptionLog); | |
| 256 | -// } catch (Throwable th) { | |
| 257 | -// log.error("[addAccessLog][插入异常日志({}) 发生异常({})", JSON.toJSONString(exceptionLog), ExceptionUtils.getRootCauseMessage(th)); | |
| 258 | -// } | |
| 259 | -// } | |
| 260 | -// | |
| 261 | -// private void initExceptionLog(SystemExceptionLogCreateDTO exceptionLog, HttpServletRequest request, Throwable e) { | |
| 262 | -// // 设置账号编号 | |
| 263 | -// exceptionLog.setUserId(CommonWebUtil.getUserId(request)); | |
| 264 | -// exceptionLog.setUserType(CommonWebUtil.getUserType(request)); | |
| 265 | -// // 设置异常字段 | |
| 266 | -// exceptionLog.setExceptionName(e.getClass().getName()); | |
| 267 | -// exceptionLog.setExceptionMessage(ExceptionUtil.getMessage(e)); | |
| 268 | -// exceptionLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e)); | |
| 269 | -// exceptionLog.setExceptionStackTrace(ExceptionUtil.getStackTrace(e)); | |
| 270 | -// StackTraceElement[] stackTraceElements = e.getStackTrace(); | |
| 271 | -// Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空"); | |
| 272 | -// StackTraceElement stackTraceElement = stackTraceElements[0]; | |
| 273 | -// exceptionLog.setExceptionClassName(stackTraceElement.getClassName()); | |
| 274 | -// exceptionLog.setExceptionFileName(stackTraceElement.getFileName()); | |
| 275 | -// exceptionLog.setExceptionMethodName(stackTraceElement.getMethodName()); | |
| 276 | -// exceptionLog.setExceptionLineNumber(stackTraceElement.getLineNumber()); | |
| 277 | -// // 设置其它字段 | |
| 278 | -// exceptionLog.setTraceId(MallUtils.getTraceId()) | |
| 279 | -// .setApplicationName(applicationName) | |
| 280 | -// .setUri(request.getRequestURI()) | |
| 281 | -// .setQueryString(HttpUtil.buildQueryString(request)) | |
| 282 | -// .setMethod(request.getMethod()) | |
| 283 | -// .setUserAgent(HttpUtil.getUserAgent(request)) | |
| 284 | -// .setIp(HttpUtil.getIp(request)) | |
| 285 | -// .setExceptionTime(new Date()); | |
| 286 | -// } | |
| 269 | + private void initExceptionLog(ApiErrorLogCreateDTO errorLog, HttpServletRequest request, Throwable e) { | |
| 270 | + // 处理用户信息 | |
| 271 | + errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); | |
| 272 | + errorLog.setUserType(WebFrameworkUtils.getUesrType(request)); | |
| 273 | + // 设置异常字段 | |
| 274 | + errorLog.setExceptionName(e.getClass().getName()); | |
| 275 | + errorLog.setExceptionMessage(ExceptionUtil.getMessage(e)); | |
| 276 | + errorLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e)); | |
| 277 | + errorLog.setExceptionStackTrace(ExceptionUtils.getStackTrace(e)); | |
| 278 | + StackTraceElement[] stackTraceElements = e.getStackTrace(); | |
| 279 | + Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空"); | |
| 280 | + StackTraceElement stackTraceElement = stackTraceElements[0]; | |
| 281 | + errorLog.setExceptionClassName(stackTraceElement.getClassName()); | |
| 282 | + errorLog.setExceptionFileName(stackTraceElement.getFileName()); | |
| 283 | + errorLog.setExceptionMethodName(stackTraceElement.getMethodName()); | |
| 284 | + errorLog.setExceptionLineNumber(stackTraceElement.getLineNumber()); | |
| 285 | + // 设置其它字段 | |
| 286 | + errorLog.setTraceId(TracerUtils.getTraceId()); | |
| 287 | + errorLog.setApplicationName(applicationName); | |
| 288 | + errorLog.setRequestUrl(request.getRequestURI()); | |
| 289 | + Map<String, Object> requestParams = MapUtil.<String, Object>builder() | |
| 290 | + .put("query", ServletUtil.getParamMap(request)) | |
| 291 | + .put("body", ServletUtil.getBody(request)).build(); | |
| 292 | + errorLog.setRequestParams(JsonUtils.toJsonString(requestParams)); | |
| 293 | + errorLog.setRequestMethod(request.getMethod()); | |
| 294 | + errorLog.setUserAgent(ServletUtils.getUserAgent(request)); | |
| 295 | + errorLog.setUserIp(ServletUtil.getClientIP(request)); | |
| 296 | + errorLog.setExceptionTime(new Date()); | |
| 297 | + } | |
| 287 | 298 | |
| 288 | 299 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java
| ... | ... | @@ -31,7 +31,7 @@ public class WebFrameworkUtils { |
| 31 | 31 | return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | - public static Integer getUsrType(HttpServletRequest request) { | |
| 34 | + public static Integer getUesrType(HttpServletRequest request) { | |
| 35 | 35 | return UserTypeEnum.ADMIN.getValue(); // TODO 芋艿:等后续优化 |
| 36 | 36 | } |
| 37 | 37 | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java
| ... | ... | @@ -51,6 +51,8 @@ public class InfApiAccessLogDO extends BaseDO { |
| 51 | 51 | */ |
| 52 | 52 | private String applicationName; |
| 53 | 53 | |
| 54 | + // ========== 请求相关字段 ========== | |
| 55 | + | |
| 54 | 56 | /** |
| 55 | 57 | * 请求方法名 |
| 56 | 58 | */ |
| ... | ... | @@ -75,6 +77,8 @@ public class InfApiAccessLogDO extends BaseDO { |
| 75 | 77 | */ |
| 76 | 78 | private String userAgent; |
| 77 | 79 | |
| 80 | + // ========== 执行相关字段 ========== | |
| 81 | + | |
| 78 | 82 | /** |
| 79 | 83 | * 开始请求时间 |
| 80 | 84 | */ | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java
| 1 | 1 | package cn.iocoder.dashboard.modules.infra.dal.dataobject.logger; |
| 2 | 2 | |
| 3 | -public class InfApiErrorLogDO { | |
| 3 | +import cn.iocoder.dashboard.common.enums.UserTypeEnum; | |
| 4 | +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | |
| 5 | +import cn.iocoder.dashboard.modules.infra.enums.logger.ApiErrorLogProcessStatusEnum; | |
| 6 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 7 | +import lombok.*; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * API 异常数据 | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +@TableName("inf_api_error_log") | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +public class InfApiErrorLogDO extends BaseDO { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 编号 | |
| 27 | + */ | |
| 28 | + private Integer id; | |
| 29 | + /** | |
| 30 | + * 用户编号 | |
| 31 | + */ | |
| 32 | + private Integer userId; | |
| 33 | + /** | |
| 34 | + * 链路追踪编号 | |
| 35 | + * | |
| 36 | + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 | |
| 37 | + */ | |
| 38 | + private String traceId; | |
| 39 | + /** | |
| 40 | + * 用户类型 | |
| 41 | + * | |
| 42 | + * 枚举 {@link UserTypeEnum} | |
| 43 | + */ | |
| 44 | + private Integer userType; | |
| 45 | + /** | |
| 46 | + * 应用名 | |
| 47 | + * | |
| 48 | + * 目前读取 spring.application.name | |
| 49 | + */ | |
| 50 | + private String applicationName; | |
| 51 | + | |
| 52 | + // ========== 请求相关字段 ========== | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 请求方法名 | |
| 56 | + */ | |
| 57 | + private String requestMethod; | |
| 58 | + /** | |
| 59 | + * 访问地址 | |
| 60 | + */ | |
| 61 | + private String requestUrl; | |
| 62 | + /** | |
| 63 | + * 请求参数 | |
| 64 | + * | |
| 65 | + * query: Query String | |
| 66 | + * body: Quest Body | |
| 67 | + */ | |
| 68 | + private String requestParams; | |
| 69 | + /** | |
| 70 | + * 用户 IP | |
| 71 | + */ | |
| 72 | + private String userIp; | |
| 73 | + /** | |
| 74 | + * 浏览器 UA | |
| 75 | + */ | |
| 76 | + private String userAgent; | |
| 77 | + | |
| 78 | + // ========== 异常相关字段 ========== | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 异常发生时间 | |
| 82 | + */ | |
| 83 | + private Date exceptionTime; | |
| 84 | + /** | |
| 85 | + * 异常名 | |
| 86 | + * | |
| 87 | + * {@link Throwable#getClass()} 的类全名 | |
| 88 | + */ | |
| 89 | + private String exceptionName; | |
| 90 | + /** | |
| 91 | + * 异常导致的消息 | |
| 92 | + * | |
| 93 | + * {@link cn.hutool.core.exceptions.ExceptionUtil#getMessage(Throwable)} | |
| 94 | + */ | |
| 95 | + private String exceptionMessage; | |
| 96 | + /** | |
| 97 | + * 异常导致的根消息 | |
| 98 | + * | |
| 99 | + * {@link cn.hutool.core.exceptions.ExceptionUtil#getRootCauseMessage(Throwable)} | |
| 100 | + */ | |
| 101 | + private String exceptionRootCauseMessage; | |
| 102 | + /** | |
| 103 | + * 异常的栈轨迹 | |
| 104 | + * | |
| 105 | + * {@link org.apache.commons.lang3.exception.ExceptionUtils#getStackTrace(Throwable)} | |
| 106 | + */ | |
| 107 | + private String exceptionStackTrace; | |
| 108 | + /** | |
| 109 | + * 异常发生的类全名 | |
| 110 | + * | |
| 111 | + * {@link StackTraceElement#getClassName()} | |
| 112 | + */ | |
| 113 | + private String exceptionClassName; | |
| 114 | + /** | |
| 115 | + * 异常发生的类文件 | |
| 116 | + * | |
| 117 | + * {@link StackTraceElement#getFileName()} | |
| 118 | + */ | |
| 119 | + private String exceptionFileName; | |
| 120 | + /** | |
| 121 | + * 异常发生的方法名 | |
| 122 | + * | |
| 123 | + * {@link StackTraceElement#getMethodName()} | |
| 124 | + */ | |
| 125 | + private String exceptionMethodName; | |
| 126 | + /** | |
| 127 | + * 异常发生的方法所在行 | |
| 128 | + * | |
| 129 | + * {@link StackTraceElement#getLineNumber()} | |
| 130 | + */ | |
| 131 | + private Integer exceptionLineNumber; | |
| 132 | + | |
| 133 | + // ========== 处理相关字段 ========== | |
| 134 | + | |
| 135 | + /** | |
| 136 | + * 处理状态 | |
| 137 | + * | |
| 138 | + * 枚举 {@link ApiErrorLogProcessStatusEnum} | |
| 139 | + */ | |
| 140 | + private Integer processStatus; | |
| 141 | + /** | |
| 142 | + * 处理时间 | |
| 143 | + */ | |
| 144 | + private Date processTime; | |
| 145 | + /** | |
| 146 | + * 处理管理员编号 | |
| 147 | + * | |
| 148 | + * 关联 {@link} | |
| 149 | + */ | |
| 150 | + private Integer processUserId; | |
| 151 | + | |
| 4 | 152 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/ApiErrorLogProcessStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.infra.enums.logger; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Getter; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * API 异常数据的处理状态 | |
| 8 | + * | |
| 9 | + * @author 芋道源码 | |
| 10 | + */ | |
| 11 | +@AllArgsConstructor | |
| 12 | +@Getter | |
| 13 | +public enum ApiErrorLogProcessStatusEnum { | |
| 14 | + | |
| 15 | + INIT(0, "未处理"), | |
| 16 | + DONE(1, "已处理"), | |
| 17 | + IGNORE(2, "已忽略"); | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 状态 | |
| 21 | + */ | |
| 22 | + private final Integer status; | |
| 23 | + /** | |
| 24 | + * 资源类型名 | |
| 25 | + */ | |
| 26 | + private final String name; | |
| 27 | + | |
| 28 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.infra.service.logger; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * API 错误日志 Service 接口 | |
| 7 | + * | |
| 8 | + * @author 芋道源码 | |
| 9 | + */ | |
| 10 | +public interface InfApiErrorLogService extends ApiErrorLogFrameworkService { | |
| 11 | + | |
| 12 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java
| ... | ... | @@ -30,7 +30,7 @@ public class InfApiAccessLogServiceImpl implements InfApiAccessLogService { |
| 30 | 30 | |
| 31 | 31 | @Override |
| 32 | 32 | @Async |
| 33 | - public void createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO) { | |
| 33 | + public void createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) { | |
| 34 | 34 | // 插入 |
| 35 | 35 | InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO); |
| 36 | 36 | apiAccessLogMapper.insert(apiAccessLog); | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.infra.service.logger.impl; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; | |
| 4 | +import cn.iocoder.dashboard.modules.infra.service.logger.InfApiErrorLogService; | |
| 5 | +import org.springframework.scheduling.annotation.Async; | |
| 6 | +import org.springframework.stereotype.Service; | |
| 7 | +import org.springframework.validation.annotation.Validated; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * API 错误日志 Service 实现类 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +@Service | |
| 15 | +@Validated | |
| 16 | +public class InfApiErrorLogServiceImpl implements InfApiErrorLogService { | |
| 17 | + | |
| 18 | + @Override | |
| 19 | + @Async | |
| 20 | + public void createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) { | |
| 21 | + | |
| 22 | + } | |
| 23 | + | |
| 24 | +} | ... | ... |