diff --git a/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java b/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java index 29f1bf7..787eb03 100644 --- a/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java +++ b/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java @@ -56,7 +56,10 @@ public enum AppCache implements BaseCacheEnum { SYS_CACHE_FILE_STATS("sys:cache:file-stats", 60 * 60L), // 系统账号密码错误次数 - COUNT_SYS_USER_PASSWD_ERR("count:sys-user:passwd-err:", -1L); + COUNT_SYS_USER_PASSWD_ERR("count:sys-user:passwd-err:", -1L), + + // 系统日志按级别按天统计数 + COUNT_SYS_LOG("count:sys-log:{}:{}", 3 * 24 * 60 * 60L); /** * 系统缓存前缀 diff --git a/xtools-app-common/xtools-app-common-log/xtools-app-common-log-bus/src/main/java/xtools/app/common/log/bus/service/LogBusService.java b/xtools-app-common/xtools-app-common-log/xtools-app-common-log-bus/src/main/java/xtools/app/common/log/bus/service/LogBusService.java index 5786279..89d3e41 100644 --- a/xtools-app-common/xtools-app-common-log/xtools-app-common-log-bus/src/main/java/xtools/app/common/log/bus/service/LogBusService.java +++ b/xtools-app-common/xtools-app-common-log/xtools-app-common-log-bus/src/main/java/xtools/app/common/log/bus/service/LogBusService.java @@ -22,4 +22,11 @@ public interface LogBusService { */ void saveLog(LogBody logBody); + /** + * 日志统计 + * + * @return 保存结果 + */ + String total(); + } diff --git a/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java b/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java index ce068a0..99f0c1e 100644 --- a/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java +++ b/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java @@ -20,6 +20,8 @@ public enum TaskType implements BaseTaskType { OTHER(10, "其他任务"), // 删除系统日志 DEL_SYS_LOG(20, "删除系统日志"), + // 统计系统日志 + TOTAL_SYS_LOG(21, "统计系统日志"), // 删除系统文件 DEL_SYS_FILE(30, "删除系统文件"), // 删除禁用的系统用户 diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysLogTotalController.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysLogTotalController.java new file mode 100644 index 0000000..0162b99 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysLogTotalController.java @@ -0,0 +1,25 @@ +package xtools.app.sys.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import xtools.app.sys.service.SysLogTotalService; + +/** + *

Title : SysLogTotalController

+ *

Description : 系统日志统计表 Controller

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +@RequiredArgsConstructor +@Tag(name = "系统日志统计表") +@RestController +@RequestMapping("/sys/log-total") +public class SysLogTotalController { + + private final SysLogTotalService sysLogTotalService; +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysLogTotalConvert.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysLogTotalConvert.java new file mode 100644 index 0000000..ea5b7be --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysLogTotalConvert.java @@ -0,0 +1,17 @@ +package xtools.app.sys.convert; + +import org.mapstruct.Mapper; + +/** + *

Title : SysLogTotalConvert

+ *

Description : 系统日志统计表 Convert

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +@Mapper(componentModel = "spring") +public interface SysLogTotalConvert { + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysLogTotalJob.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysLogTotalJob.java new file mode 100644 index 0000000..55f924d --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysLogTotalJob.java @@ -0,0 +1,69 @@ +package xtools.app.sys.job; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import xtools.app.common.job.base.BaseJob; +import xtools.app.common.log.bus.service.LogBusService; +import xtools.app.common.task.enums.TaskType; +import xtools.boot.log.LogBus; +import xtools.boot.log.enums.LogBusBaseType; +import xtools.boot.task.TaskBus; +import xtools.boot.task.enums.TaskStatus; +import xtools.core.UuidUtils; +import xtools.core.enums.LogLevel; + +import java.util.Objects; + +/** + *

Title : SysLogTotalJob

+ *

Description : SysLogTotalJob

+ *

DevelopTools : Idea_x64_v2026.1

+ *

DevelopSystem : macOS Sequoia 15.7.5

+ *

Company : org.xujun

+ * + * @author : XuJun + * @version : 1.0.0 + * @date : 2026/3/17 21:24 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class SysLogTotalJob extends BaseJob { + + private final LogBusService logBusService; + + /** + * 运行作业 + */ + @Override + public void runJob() { + // 任务日志code + String code = UuidUtils.get(); + // 任务类型 + TaskType taskType = TaskType.TOTAL_SYS_LOG; + // 任务信息 + String info = "开始统计昨天的日志信息,请稍候..."; + // 保存任务 + TaskBus.init(code, taskType, TaskStatus.ING).info(info).save(); + // 异常 + Exception ex = null; + try { + // 记录任务日志 + info = logBusService.total(); + } catch (Exception e) { + ex = e; + info = "执行失败"; + throw e; + } finally { + // 保存任务 + TaskStatus status = Objects.isNull(ex) ? TaskStatus.SUCCESS : TaskStatus.ERROR; + TaskBus.init(code, taskType, status).info(info).save(); + if (Objects.nonNull(ex)) { + // 保存异常日志 + LogBus.init(LogLevel.ERROR, LogBusBaseType.TASK).error(ex).save(); + } + } + } + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysLogTotalMapper.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysLogTotalMapper.java new file mode 100644 index 0000000..d617d4b --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysLogTotalMapper.java @@ -0,0 +1,19 @@ +package xtools.app.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import xtools.app.sys.model.entity.SysLogTotal; + +/** + *

Title : SysLogTotalMapper

+ *

Description : 系统日志统计表 Mapper 接口

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +@Mapper +public interface SysLogTotalMapper extends BaseMapper { + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysTaskStatsResp.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysTaskStatsResp.java index f9ce414..1f371ed 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysTaskStatsResp.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysTaskStatsResp.java @@ -24,19 +24,27 @@ import java.time.Instant; @AllArgsConstructor public class SysTaskStatsResp implements Serializable { - /** 当天(Instant,当天 0 点) */ + /** + * 当天(Instant,当天 0 点) + */ @Schema(description = "当天(Instant,当天 0 点)") private Instant day; - /** 成功数 */ + /** + * 成功数 + */ @Schema(description = "成功数") private Long successCount; - /** 失败数 */ + /** + * 失败数 + */ @Schema(description = "失败数") private Long failCount; - /** 进行中数 */ + /** + * 进行中数 + */ @Schema(description = "进行中数") private Long ingCount; diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLogTotal.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLogTotal.java new file mode 100644 index 0000000..a6d14dc --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLogTotal.java @@ -0,0 +1,72 @@ +package xtools.app.sys.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.Instant; + +/** + *

Title : SysLogTotal

+ *

Description : 系统日志统计表实体对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("sys_log_total") +public class SysLogTotal implements Serializable { + + /** + * 主键 ID + */ + @Schema(description = "主键 ID") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 日志级别 + */ + @Schema(description = "日志级别") + @TableField(value = "level") + private Integer level; + + /** + * 统计数值 + */ + @Schema(description = "统计数值") + @TableField(value = "count") + private Long count; + + /** + * 数据时间(天) + */ + @Schema(description = "数据时间(天)") + @TableField(value = "data_time") + private Instant dataTime; + + /** + * 备注 + */ + @Schema(description = "备注") + @TableField(value = "memo") + private String memo; + + /** + * 创建时间 + */ + @Schema(description = "创建时间", example = "2026-01-05 10:32:00") + @TableField(value = "gmt_create") + private Instant gmtCreate; + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysLogTotalService.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysLogTotalService.java new file mode 100644 index 0000000..aed69a9 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysLogTotalService.java @@ -0,0 +1,14 @@ +package xtools.app.sys.service; + +/** + *

Title : SysLogTotalService

+ *

Description : 系统日志统计表 Service

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +public interface SysLogTotalService { + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysLogTotalBaseService.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysLogTotalBaseService.java new file mode 100644 index 0000000..834c97f --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysLogTotalBaseService.java @@ -0,0 +1,20 @@ +package xtools.app.sys.service.base; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Component; + +import xtools.app.sys.mapper.SysLogTotalMapper; +import xtools.app.sys.model.entity.SysLogTotal; + +/** + *

Title : SysLogTotalBaseService

+ *

Description : 系统日志统计表 BaseService

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +@Component +public class SysLogTotalBaseService extends ServiceImpl { +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/LogBusServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/LogBusServiceImpl.java index 0b1a3d1..c22f040 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/LogBusServiceImpl.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/LogBusServiceImpl.java @@ -2,22 +2,37 @@ package xtools.app.sys.service.impl; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; +import xtools.app.common.cache.enums.AppCache; import xtools.app.common.log.bus.service.LogBusService; import xtools.app.sys.model.entity.SysLog; +import xtools.app.sys.model.entity.SysLogTotal; import xtools.app.sys.service.SysLogService; import xtools.app.sys.service.SysOptLogService; +import xtools.app.sys.service.base.SysLogTotalBaseService; +import xtools.base.config.BaseParams; import xtools.boot.api.model.dto.log.LogTrack; +import xtools.boot.cache.redis.base.RedisService; import xtools.boot.log.enums.LogBusBaseType; import xtools.boot.log.model.dto.LogBody; import xtools.boot.log.model.dto.RunInfo; import xtools.core.CollectionUtils; import xtools.core.StringUtils; +import xtools.core.enums.LogLevel; +import xtools.core.enums.TimePattern; +import xtools.core.time.CalendarUtils; +import xtools.core.time.InstantUtils; import xtools.extend.JsonUtils; +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -35,12 +50,22 @@ import java.util.Objects; @Primary @Service @RequiredArgsConstructor -public class LogBusServiceImpl implements LogBusService { +public class LogBusServiceImpl implements LogBusService, BaseParams { + + /** + * 缓存参数 + */ + private final static AppCache CACHE_PARAM = AppCache.COUNT_SYS_LOG; private final SysLogService sysLogService; private final SysOptLogService sysOptLogService; + private final SysLogTotalBaseService sysLogTotalBaseService; + + @Resource + private RedisService redisService; + /** * 保存日志 * @@ -62,6 +87,13 @@ public class LogBusServiceImpl implements LogBusService { return; } + // 统计日志 + try { + statLog(logBody.getLevel(), logTrack.time()); + } catch (Exception e) { + log.error("统计日志异常", e); + } + RunInfo runInfo = logBody.getRunInfo(); JSONArray stackTrace = logBody.getStackTrace(); @@ -117,4 +149,76 @@ public class LogBusServiceImpl implements LogBusService { } return false; } + + /** + * 统计日志 + * + * @param level 日志级别 + * @param time 日志时间 + */ + private void statLog(LogLevel level, Long time) { + if (Objects.isNull(level) || Objects.isNull(time)) { + return; + } + // 当天日期 + String date = InstantUtils.format(InstantUtils.from(time), TimePattern.YMD); + redisService.incr(CACHE_PARAM.key(date, level.code())); + } + + /** + * 日志统计 + * + * @return 保存结果 + */ + @Override + public String total() { + // 前一天时间 + Instant yesterday = CalendarUtils.yesterday(); + // 获取前一天的统计数据 + Map totalMap = getTotalByDay(yesterday); + if (CollectionUtils.isEmpty(totalMap)) { + return "执行完成,前一天日志统计数据为空"; + } + List list = new ArrayList<>(totalMap.size()); + for (Map.Entry entry : totalMap.entrySet()) { + Long count = entry.getValue(); + if (count <= CP_NUM0) { + continue; + } + SysLogTotal total = new SysLogTotal(); + total.setLevel(entry.getKey()); + total.setCount(count); + total.setDataTime(yesterday); + list.add(total); + } + if (list.isEmpty()) { + return "执行完成,前一天日志统计数据无需保存"; + } + // 保存统计 + sysLogTotalBaseService.saveBatch(list); + return "执行完成,保存日志统计成功"; + } + + /** + * 获取指定日期的日志统计数据 + * + * @param time 时间 + * @return 统计数据 + */ + public Map getTotalByDay(Instant time) { + Map result = new HashMap<>(); + if (Objects.isNull(time)) { + return result; + } + // 日期 + String date = InstantUtils.format(time, TimePattern.YMD); + for (LogLevel level : LogLevel.values()) { + // 缓存key + String key = CACHE_PARAM.key(date, level.code()); + // 获取数量 + Long count = redisService.get(key, Long.class); + result.put(level.code(), Objects.nonNull(count) ? count : 0L); + } + return result; + } } diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLogTotalServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLogTotalServiceImpl.java new file mode 100644 index 0000000..987e0df --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLogTotalServiceImpl.java @@ -0,0 +1,28 @@ +package xtools.app.sys.service.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import xtools.app.sys.convert.SysLogTotalConvert; +import xtools.app.sys.service.SysLogTotalService; +import xtools.app.sys.service.base.SysLogTotalBaseService; + +/** + *

Title : SysLogTotalServiceImpl

+ *

Description : 系统日志统计表 ServiceImpl

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-07-26 11:14:47 + */ +@Primary +@Service +@RequiredArgsConstructor +public class SysLogTotalServiceImpl implements SysLogTotalService { + + private final SysLogTotalBaseService sysLogTotalBaseService; + + private final SysLogTotalConvert sysLogTotalConvert; + +}