diff --git a/README.md b/README.md index df38a47e8..4597c708f 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ 1. 配置管理:对系统动态配置常用参数 1. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志 +1. API 日志:包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 1. MySQL 监控:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 1. Redis 监控:监控 Redis 数据库的使用情况,使用的 Redis Key 管理 1. Java 监控:基于 Spring Boot Admin 实现 Java 应用的监控 diff --git a/ruoyi-ui/src/api/infra/apiErrorLog.js b/ruoyi-ui/src/api/infra/apiErrorLog.js new file mode 100644 index 000000000..65942d136 --- /dev/null +++ b/ruoyi-ui/src/api/infra/apiErrorLog.js @@ -0,0 +1,28 @@ +import request from '@/utils/request' + +// 更新 API 错误日志的处理状态 +export function updateApiErrorLogProcess(id, processStatus) { + return request({ + url: '/infra/api-error-log/update-status?id=' + id + '&processStatus=' + processStatus, + method: 'put', + }) +} + +// 获得API 错误日志分页 +export function getApiErrorLogPage(query) { + return request({ + url: '/infra/api-error-log/page', + method: 'get', + params: query + }) +} + +// 导出API 错误日志 Excel +export function exportApiErrorLogExcel(query) { + return request({ + url: '/infra/api-error-log/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/ruoyi-ui/src/utils/constants.js b/ruoyi-ui/src/utils/constants.js index e608fc77d..43bd9c472 100644 --- a/ruoyi-ui/src/utils/constants.js +++ b/ruoyi-ui/src/utils/constants.js @@ -57,3 +57,12 @@ export const InfJobStatusEnum = { NORMAL: 1, // 运行中 STOP: 2, // 暂停运行 } + +/** + * API 异常数据的处理状态 + */ +export const InfApiErrorLogProcessStatusEnum = { + INIT: 0, // 未处理 + DONE: 1, // 已处理 + IGNORE: 2, // 已忽略 +} diff --git a/ruoyi-ui/src/utils/dict.js b/ruoyi-ui/src/utils/dict.js index f402fd598..3817a86fe 100644 --- a/ruoyi-ui/src/utils/dict.js +++ b/ruoyi-ui/src/utils/dict.js @@ -21,6 +21,7 @@ export const DICT_TYPE = { INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type', INF_JOB_STATUS: 'inf_job_status', INF_JOB_LOG_STATUS: 'inf_job_log_status', + INF_API_ERROR_LOG_PROCESS_STATUS: 'inf_api_error_log_process_status', TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type', } diff --git a/ruoyi-ui/src/views/infra/apiAccessLog/index.vue b/ruoyi-ui/src/views/infra/apiAccessLog/index.vue index 04c61fe86..abe0fd44f 100644 --- a/ruoyi-ui/src/views/infra/apiAccessLog/index.vue +++ b/ruoyi-ui/src/views/infra/apiAccessLog/index.vue @@ -81,14 +81,14 @@ - - + + {{ form.id }} {{ form.traceId }} - {{ form.applicationName }} + {{ form.applicationName }} {{ form.userId }} | {{ getDictDataLabel(DICT_TYPE.USER_TYPE, form.userType) }} | {{ form.userIp }} | {{ form.userAgent}} @@ -173,23 +173,7 @@ export default { }, /** 表单重置 */ reset() { - this.form = { - id: undefined, - traceId: undefined, - userId: undefined, - userType: undefined, - applicationName: undefined, - requestMethod: undefined, - requestUrl: undefined, - requestParams: undefined, - userIp: undefined, - userAgent: undefined, - beginTime: undefined, - endTime: undefined, - duration: undefined, - resultCode: undefined, - resultMsg: undefined, - }; + this.form = {}; this.resetForm("form"); }, /** 搜索按钮操作 */ diff --git a/ruoyi-ui/src/views/infra/apiErrorLog/index.vue b/ruoyi-ui/src/views/infra/apiErrorLog/index.vue new file mode 100644 index 000000000..97d614821 --- /dev/null +++ b/ruoyi-ui/src/views/infra/apiErrorLog/index.vue @@ -0,0 +1,237 @@ + + + diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java b/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java index e187b447c..aa064288e 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java @@ -48,7 +48,7 @@ import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstan @Slf4j public class GlobalExceptionHandler { - @Value("spring.application.name") + @Value("${spring.application.name}") private String applicationName; @Resource diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java index 10c8501ba..855c70315 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.dal.dataobject.logger; import cn.iocoder.dashboard.common.enums.UserTypeEnum; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.dashboard.modules.infra.enums.logger.ApiErrorLogProcessStatusEnum; +import cn.iocoder.dashboard.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -136,7 +136,7 @@ public class InfApiErrorLogDO extends BaseDO { /** * 处理状态 * - * 枚举 {@link ApiErrorLogProcessStatusEnum} + * 枚举 {@link InfApiErrorLogProcessStatusEnum} */ private Integer processStatus; /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/ApiErrorLogProcessStatusEnum.java b/src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java similarity index 90% rename from src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/ApiErrorLogProcessStatusEnum.java rename to src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java index e48d6e6a6..45258742d 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/ApiErrorLogProcessStatusEnum.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java @@ -10,7 +10,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ApiErrorLogProcessStatusEnum { +public enum InfApiErrorLogProcessStatusEnum { INIT(0, "未处理"), DONE(1, "已处理"), diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java index d3755c2a9..c6a8418e4 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java @@ -7,13 +7,14 @@ import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfAp import cn.iocoder.dashboard.modules.infra.convert.logger.InfApiErrorLogConvert; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiErrorLogMapper; -import cn.iocoder.dashboard.modules.infra.enums.logger.ApiErrorLogProcessStatusEnum; +import cn.iocoder.dashboard.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; import cn.iocoder.dashboard.modules.infra.service.logger.InfApiErrorLogService; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.Date; import java.util.List; import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; @@ -36,7 +37,7 @@ public class InfApiErrorLogServiceImpl implements InfApiErrorLogService { @Async public void createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) { InfApiErrorLogDO apiErrorLog = InfApiErrorLogConvert.INSTANCE.convert(createDTO); - apiErrorLog.setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus()); + apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus()); apiErrorLogMapper.insert(apiErrorLog); } @@ -56,12 +57,12 @@ public class InfApiErrorLogServiceImpl implements InfApiErrorLogService { if (errorLog == null) { throw exception(API_ERROR_LOG_NOT_FOUND); } - if (!ApiErrorLogProcessStatusEnum.INIT.getStatus().equals(errorLog.getProcessStatus())) { + if (!InfApiErrorLogProcessStatusEnum.INIT.getStatus().equals(errorLog.getProcessStatus())) { throw exception(API_ERROR_LOG_PROCESSED); } // 标记处理 apiErrorLogMapper.updateById(InfApiErrorLogDO.builder().id(id).processStatus(processStatus) - .processUserId(processStatus).build()); + .processUserId(processStatus).processTime(new Date()).build()); } } diff --git a/src/main/resources/codegen/sql/sql.vm b/src/main/resources/codegen/sql/sql.vm index 9f76a8fb2..4a65b6025 100644 --- a/src/main/resources/codegen/sql/sql.vm +++ b/src/main/resources/codegen/sql/sql.vm @@ -5,7 +5,7 @@ INSERT INTO `sys_menu`( ) VALUES ( '${table.classComment}管理', '${permissionPrefix}:query', 2, 0, ${table.parentMenuId}, - '${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 1 + '${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 0 ); -- 按钮父菜单ID @@ -22,6 +22,6 @@ INSERT INTO `sys_menu`( ) VALUES ( '${table.tableComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId, - '', '', '', 1 + '', '', '', 0 ); #end diff --git a/src/main/resources/codegen/vue/api/api.js.vm b/src/main/resources/codegen/vue/api/api.js.vm index 87c3ea225..5e9da3238 100644 --- a/src/main/resources/codegen/vue/api/api.js.vm +++ b/src/main/resources/codegen/vue/api/api.js.vm @@ -19,7 +19,6 @@ export function update${simpleClassName}(data) { }) } - // 删除${table.classComment} export function delete${simpleClassName}(id) { return request({