diff --git a/.env.example b/.env.example index fd95d68b..c6400a8c 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,13 @@ VOLUME_BASE=/data/orion-visor-space/docker-volumes -DEMO_MODE=false - SERVICE_PORT=1081 SPRING_PROFILES_ACTIVE=prod + +DEMO_MODE=false + +API_CORS=true SECRET_KEY=uQeacXV8b3isvKLK +API_EXPOSE_TOKEN=pmqeHOyZaumHm0Wt MYSQL_HOST=mysql MYSQL_PORT=3306 @@ -25,3 +28,11 @@ GUACD_SSH_USERNAME=guacd GUACD_SSH_PASSWORD=guacd GUACD_DRIVE_PATH=/drive +INFLUXDB_ENABLED=true +INFLUXDB_HOST=influxdb +INFLUXDB_PORT=8086 +INFLUXDB_ORG=orion-visor +INFLUXDB_BUCKET=metrics +INFLUXDB_TOKEN=Data@123456 +INFLUXDB_ADMIN_USERNAME=admin +INFLUXDB_ADMIN_PASSWORD=Data@123456 diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md new file mode 100644 index 00000000..15c3bf47 --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -0,0 +1,10 @@ +### *当前使用版本 (必填) + +### 问题描述 + +### 该问题是如何引起的 + +### 重现步骤 + +### 报错信息 + diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md new file mode 100644 index 00000000..cd72b47b --- /dev/null +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -0,0 +1,8 @@ +### 修改描述 + +### 关联的 Issue + +### 测试用例 + +### 修复效果的截屏 + diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 00000000..67cc45e2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,58 @@ +name: 错误报告 +description: File a bug report. +title: "[错误报告]: " +labels: [ "" ] +body: + - type: markdown + attributes: + value: | + 在提交前请确认: + - 使用的是[最新版本](https://github.com/dromara/orion-visor/releases) + - 参考了[安装文档](https://visor.orionsec.cn/quickstart/docker.html) + - 查阅了[常见问题](https://visor.orionsec.cn/support/faq.html) + - 搜索了[已有 issue](https://github.com/dromara/orion-visor/issues) + - type: checkboxes + id: confirm + attributes: + label: 确认 + description: 在提交 issue 之前, 请确认你已经阅读并确认以下内容 + options: + - label: 我使用的是最新版本 [最新版](https://github.com/dromara/orion-visor/releases) + required: true + - label: 我使用官方文档进行部署 [安装文档](https://visor.orionsec.cn/quickstart/docker.html) + required: true + - label: 我已检查了 [常见问题](https://visor.orionsec.cn/support/faq.html) 并没有找到解决方法 + required: true + - label: 我已搜索 [issue](https://github.com/dromara/orion-visor/issues) 并没有找到相关问题 + required: true + - type: input + id: version + attributes: + label: 当前程序版本 + description: 遇到问题时程序所在的版本号 + validations: + required: true + - type: dropdown + id: install + attributes: + label: 安装方式 + options: + - Docker + - 普通安装 + - 其他 + validations: + required: true + - type: textarea + id: what-happened + attributes: + label: 问题描述 + description: 请详细描述你碰到的问题 + placeholder: "问题描述" + validations: + required: true + - type: textarea + id: logs + attributes: + label: 详细日志 + description: 问题出现时的程序日志 + render: bash diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yaml new file mode 100644 index 00000000..ce4ad1df --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yaml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 官网 + url: https://visor.orionsec.cn/ + about: document. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 00000000..59730be8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,35 @@ +name: 功能改进 +description: 提出新功能建议 (请提交到需求收集帖) +title: "[功能建议]: " +labels: [ "" ] +body: + - type: markdown + attributes: + value: | + 所有功能建议请统一提交到需求收集帖: 🔗 [#83 需求收集](https://github.com/dromara/orion-visor/issues/83) + + 在提交前请确认: + - ✅ 使用的是[最新版本](https://github.com/dromara/orion-visor/releases) + - ✅ 已搜索[已有 issue](https://github.com/dromara/orion-visor/issues) 和 需求收集帖避免重复 + - ✅ 定制化需求请联系作者 + + --- + + ### 如何提交高质量建议? + 1. **功能描述**: 你希望增加什么? + 2. **使用场景**: 你在什么情况下需要它? + 4. **参考实现**: 开源项目中的类似功能(**禁止引用商业闭源软件**) + - type: textarea + id: feature + attributes: + label: 功能改进 + description: 请详细描述需要改进或者添加的功能。 + placeholder: "功能改进" + validations: + required: true + - type: textarea + id: references + attributes: + label: 参考资料 + description: 可以列举一些参考资料, 但是不要引用同类但商业化软件的任何内容。 + placeholder: "参考资料" \ No newline at end of file diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yaml similarity index 93% rename from .github/workflows/docker-publish.yml rename to .github/workflows/docker-publish.yaml index 16b4c128..be3a9c77 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yaml @@ -41,6 +41,10 @@ jobs: pnpm install pnpm build + - name: 📦️ Download instance-agent + working-directory: ./docker/service + run: wget https://github.com/lijiahangmax/orion-visor-agent/releases/latest/download/instance-agent-release.tar.gz -O instance-agent-release.tar.gz + - name: 📁 Prepare build context run: | cp -r ./sql ./docker/mysql/sql @@ -62,7 +66,7 @@ jobs: strategy: matrix: - service: [ adminer, guacd, mysql, redis, service, ui ] + service: [ adminer, guacd, mysql, redis, influxdb, service, ui ] env: GITHUB_REGISTRY: ghcr.io diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 87eef70c..1be49f4c 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -18,4 +18,4 @@ jobs: run: | sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose sudo chmod u+x /usr/local/bin/docker-compose - docker compose -f docker-compose-testing.yml up --build testing --exit-code-from testing --remove-orphans + docker compose -f docker-compose-testing.yaml up --build testing --exit-code-from testing --remove-orphans diff --git a/NOTICE b/NOTICE index 64df0a06..5896e2ac 100644 --- a/NOTICE +++ b/NOTICE @@ -5,5 +5,5 @@ 1. 禁止修改或删除 LICENSE 文件。 2. 禁止修改或删除源码头部的版权声明。 3. 本项目可免费商业使用,商业使用请保留项目源码、出处、描述文件和作者声明等。 - 4. 分发源码时候,请注明软件出处 https://visor.dromara.org/ + 4. 分发源码时候,请注明软件出处 https://visor.orionsec.cn/ 5. 不可二次开发或参与同类竞品的开发。 diff --git a/README.md b/README.md index 289002d2..398cbea4 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ * **文件管理**:支持远程主机 SFTP 大文件的批量上传、下载和在线编辑等操作。 * **批量操作**:支持批量执行主机命令、多主机文件分发等功能。 * **计划任务**:支持配置 cron 表达式,定时执行主机命令。 -* **系统监控**:(开发中)。 +* **系统监控**:支持对主机 CPU、内存、磁盘、网络等系统指标的监控和告警。 * **安全可靠**:动态配置权限,记录用户操作日志,提供简单的审计功能。 ## 演示环境 @@ -88,6 +88,7 @@ docker compose up -d * SpringBoot 2.7+ * Mysql 8.0+ * Redis 6.0+ +* InfluxDB 2.7+ * Vue 3.5+ * Arco Design 2.56+ @@ -109,6 +110,11 @@ docker compose up -d ![主机列表](docs/assets/screenshot/host-list.png?time=20250627 "主机列表") +#### 主机监控 + +![主机监控](docs/assets/screenshot/monitor-list.png?time=20250627 "主机监控") +![监控详情](docs/assets/screenshot/monitor-detail.png?time=20250627 "监控详情") + #### 批量执行 ![批量执行](docs/assets/screenshot/exec-command.png?time=20250627 "批量执行") @@ -155,6 +161,10 @@ QQ群: 755242157 本项目遵循 [Apache-2.0](https://github.com/dromara/orion-visor/blob/main/LICENSE) 开源许可证。 +## 贡献者 + +[![Contributors](https://contri.buzz/api/wall?repo=dromara/orion-visor)](https://github.com/dromara/orion-visor, "Contributors") + ## Gitee 最有价值的开源项目 GVP ![GVP](docs/assets/gvp.jpg?time=20250627 "GVP") diff --git a/docker-compose-testing.yml b/docker-compose-testing.yaml similarity index 100% rename from docker-compose-testing.yml rename to docker-compose-testing.yaml diff --git a/docker-compose.yml b/docker-compose.yaml similarity index 74% rename from docker-compose.yml rename to docker-compose.yaml index 425cc70f..845935d2 100644 --- a/docker-compose.yml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ version: '3.3' -# latest = 2.4.3 +# latest = 2.5.0 # 支持以下源 # lijiahangmax/* @@ -35,10 +35,18 @@ services: REDIS_PASSWORD: ${REDIS_PASSWORD:-Data@123456} REDIS_DATABASE: ${REDIS_DATABASE:-0} REDIS_DATA_VERSION: ${REDIS_DATA_VERSION:-1} + INFLUXDB_ENABLED: ${INFLUXDB_ENABLED:-true} + INFLUXDB_HOST: ${INFLUXDB_HOST:-influxdb} + INFLUXDB_PORT: ${INFLUXDB_PORT:-8086} + INFLUXDB_ORG: ${INFLUXDB_ORG:-orion-visor} + INFLUXDB_BUCKET: ${INFLUXDB_BUCKET:-metrics} + INFLUXDB_TOKEN: ${INFLUXDB_TOKEN:-Data@123456} GUACD_HOST: ${GUACD_HOST:-guacd} GUACD_PORT: ${GUACD_PORT:-4822} GUACD_DRIVE_PATH: ${GUACD_DRIVE_PATH:-/drive} - SECRET_KEY: ${SECRET_KEY:-uQeacXV8b3isvKLK} + SECRET_KEY: ${SECRET_KEY:-pmqeHOyZaumHm0Wt} + API_EXPOSE_TOKEN: ${API_EXPOSE_TOKEN:-uQeacXV8b3isvKLK} + API_CORS: ${API_CORS:-true} DEMO_MODE: ${DEMO_MODE:-false} volumes: - ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion @@ -54,6 +62,8 @@ services: condition: service_healthy redis: condition: service_healthy + influxdb: + condition: service_healthy networks: - orion-visor-net @@ -100,6 +110,31 @@ services: networks: - orion-visor-net + influxdb: + image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-influxdb:latest + privileged: true + ports: + - "8086:8086" + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: ${INFLUXDB_ADMIN_USERNAME:-admin} + DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_ADMIN_PASSWORD:-Data@123456} + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_TOKEN:-Data@123456} + DOCKER_INFLUXDB_INIT_ORG: ${INFLUXDB_ORG:-orion-visor} + DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUXDB_BUCKET:-metrics} + volumes: + - ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/influxdb/data:/var/lib/influxdb2 + - ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/influxdb/config:/etc/influxdb2 + restart: unless-stopped + healthcheck: + test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/8086" ] + interval: 15s + timeout: 5s + retries: 10 + start_period: 10s + networks: + - orion-visor-net + guacd: image: registry.cn-hangzhou.aliyuncs.com/orionsec/orion-visor-guacd:latest ports: diff --git a/docker/docker-build.sh b/docker/docker-build.sh index 0b18e41d..e9797cae 100644 --- a/docker/docker-build.sh +++ b/docker/docker-build.sh @@ -7,7 +7,7 @@ set -e source ./project-build.sh "$@" # 版本号 -version=2.4.3 +version=2.5.0 # 是否推送镜像 push_image=false # 是否构建 latest @@ -46,6 +46,7 @@ declare -A images=( ["./service/Dockerfile"]="orion-visor-service" ["./mysql/Dockerfile"]="orion-visor-mysql" ["./redis/Dockerfile"]="orion-visor-redis" + ["./influxdb/Dockerfile"]="orion-visor-influxdb" ["./adminer/Dockerfile"]="orion-visor-adminer" ["./guacd/Dockerfile"]="orion-visor-guacd" ) @@ -68,6 +69,30 @@ function prepare_app_jar() { fi } +# 准备 instance-agent +function prepare_instance_agent() { + local target_file="./service/instance-agent-release.tar.gz" + if [ ! -f "$target_file" ]; then + echo "警告: $target_file 不存在, 正在尝试从 Github Release 下载..." + # 尝试从 GitHub Release 下载 + if curl -L --fail \ + --connect-timeout 30 --max-time 30 \ + https://github.com/lijiahangmax/orion-visor-agent/releases/latest/download/instance-agent-release.tar.gz \ + -o "$target_file"; then + echo "已成功下载到 $target_file" + fi + + # 如果下载失败, 提示用户手动下载 + echo "错误: 无法从 Release 获取 instance-agent-release.tar.gz" + echo "请手动从以下地址下载, 并放置到 $target_file" + echo " 1) https://github.com/lijiahangmax/orion-visor-agent/raw/main/instance-agent-release.tar.gz" + echo " 2) https://gitee.com/lijiahangmax/orion-visor-agent/raw/main/instance-agent-release.tar.gz" + exit 1 + else + echo "$target_file 已存在, 无需下载." + fi +} + # 准备前端 dist 目录 function prepare_dist_directory() { local source_dir="../orion-visor-ui/dist" @@ -185,6 +210,7 @@ fi # 检查资源 echo "正在检查并准备必要的构建资源..." prepare_app_jar +prepare_instance_agent prepare_dist_directory prepare_sql_directory echo "所有前置资源已准备完毕" diff --git a/docker/influxdb/Dockerfile b/docker/influxdb/Dockerfile new file mode 100644 index 00000000..2a47b7c5 --- /dev/null +++ b/docker/influxdb/Dockerfile @@ -0,0 +1,8 @@ +FROM --platform=$TARGETPLATFORM influxdb:2 + +# 系统时区 +ARG TZ=Asia/Shanghai + +# 设置时区 +RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \ + echo "${TZ}" > /etc/timezone diff --git a/docker/project-build.sh b/docker/project-build.sh index c944f22c..e4e5c237 100644 --- a/docker/project-build.sh +++ b/docker/project-build.sh @@ -4,7 +4,7 @@ set -e # DockerContext: orion-visor # 版本号 -version=2.4.3 +version=2.5.0 # 是否构建 service export build_service=false # 是否构建 ui diff --git a/docker/service/Dockerfile b/docker/service/Dockerfile index b846a739..b04ef717 100644 --- a/docker/service/Dockerfile +++ b/docker/service/Dockerfile @@ -17,12 +17,19 @@ RUN \ ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \ echo "${TZ}" > /etc/timezone +# 复制启动脚本 +COPY ./service/entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + # 复制 jar 包 COPY ./service/orion-visor-launch.jar /app/app.jar +# 复制探针包 +ADD ./service/instance-agent-release.tar.gz /app/instance-agent-release # 启动检测 HEALTHCHECK --interval=15s --timeout=5s --retries=5 --start-period=10s \ CMD wget -T5 -qO- http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health | grep ok || exit 1 # 启动 +ENTRYPOINT ["/app/entrypoint.sh"] CMD ["java", "-jar", "/app/app.jar"] diff --git a/docker/service/entrypoint.sh b/docker/service/entrypoint.sh new file mode 100644 index 00000000..d163a824 --- /dev/null +++ b/docker/service/entrypoint.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +AGENT_RELEASE_DIR="/root/orion/orion-visor/instance-agent-release" +DEFAULT_AGENT_DIR="/app/instance-agent-release" + +# 确保父目录存在 +mkdir -p "$(dirname "$AGENT_RELEASE_DIR")" + +# 加载探针 +if [ -d "$AGENT_RELEASE_DIR" ] && [ -n "$(ls -A "$AGENT_RELEASE_DIR" 2>/dev/null)" ]; then + echo "Using mounted agent release: $AGENT_RELEASE_DIR" +else + echo "Using default agent release: $DEFAULT_AGENT_DIR" + # 复制探针 + cp -rf "$DEFAULT_AGENT_DIR" "$AGENT_RELEASE_DIR" +fi + +# 打印探针版本信息 +if [ -f "$AGENT_RELEASE_DIR/.version" ]; then + echo "Agent version: $(cat "$AGENT_RELEASE_DIR/.version")" +fi + +exec "$@" \ No newline at end of file diff --git a/docs/assets/screenshot/monitor-detail.png b/docs/assets/screenshot/monitor-detail.png new file mode 100644 index 00000000..ca38b3d6 Binary files /dev/null and b/docs/assets/screenshot/monitor-detail.png differ diff --git a/docs/assets/screenshot/monitor-list.png b/docs/assets/screenshot/monitor-list.png new file mode 100644 index 00000000..1686f022 Binary files /dev/null and b/docs/assets/screenshot/monitor-list.png differ diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/AesEncryptor.java b/orion-visor-common/src/main/java/org/dromara/visor/common/cipher/AesEncryptor.java similarity index 97% rename from orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/AesEncryptor.java rename to orion-visor-common/src/main/java/org/dromara/visor/common/cipher/AesEncryptor.java index bf3f1360..326908f1 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/AesEncryptor.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/cipher/AesEncryptor.java @@ -20,7 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.dromara.visor.common.interfaces; +package org.dromara.visor.common.cipher; import cn.orionsec.kit.lang.utils.codec.Base62s; import cn.orionsec.kit.lang.utils.crypto.symmetric.SymmetricCrypto; diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/RsaDecryptor.java b/orion-visor-common/src/main/java/org/dromara/visor/common/cipher/RsaDecryptor.java similarity index 95% rename from orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/RsaDecryptor.java rename to orion-visor-common/src/main/java/org/dromara/visor/common/cipher/RsaDecryptor.java index a0bec1ae..d64e4e0c 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/RsaDecryptor.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/cipher/RsaDecryptor.java @@ -20,7 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.dromara.visor.common.interfaces; +package org.dromara.visor.common.cipher; /** * rsa 解密器 diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AppConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AppConst.java index 31ecc24f..caa4bc74 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AppConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AppConst.java @@ -36,7 +36,7 @@ public interface AppConst extends OrionConst { /** * 同 ${orion.version} 迭代时候需要手动更改 */ - String VERSION = "2.4.3"; + String VERSION = "2.5.0"; /** * 同 ${spring.application.name} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AutoConfigureOrderConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AutoConfigureOrderConst.java index e652083a..2b089ba3 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AutoConfigureOrderConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/AutoConfigureOrderConst.java @@ -53,21 +53,23 @@ public interface AutoConfigureOrderConst { int FRAMEWORK_REDIS_CACHE = Integer.MIN_VALUE + 2000; - int FRAMEWORK_CONFIG = Integer.MIN_VALUE + 2100; + int FRAMEWORK_INFLUXDB = Integer.MIN_VALUE + 2100; - int FRAMEWORK_ENCRYPT = Integer.MIN_VALUE + 2200; + int FRAMEWORK_CONFIG = Integer.MIN_VALUE + 2300; - int FRAMEWORK_STORAGE = Integer.MIN_VALUE + 2300; + int FRAMEWORK_CYPHER = Integer.MIN_VALUE + 2400; - int FRAMEWORK_JOB = Integer.MIN_VALUE + 2400; + int FRAMEWORK_STORAGE = Integer.MIN_VALUE + 2500; - int FRAMEWORK_JOB_QUARTZ = Integer.MIN_VALUE + 2500; + int FRAMEWORK_JOB = Integer.MIN_VALUE + 2600; - int FRAMEWORK_JOB_ASYNC = Integer.MIN_VALUE + 2600; + int FRAMEWORK_JOB_QUARTZ = Integer.MIN_VALUE + 2700; - int FRAMEWORK_MONITOR = Integer.MIN_VALUE + 2700; + int FRAMEWORK_JOB_ASYNC = Integer.MIN_VALUE + 2800; - int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 2800; + int FRAMEWORK_MONITOR = Integer.MIN_VALUE + 2900; + + int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 3000; int FRAMEWORK_BANNER = Integer.MIN_VALUE + 10000; diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/BeanOrderConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/BeanOrderConst.java index a84c8b3b..7c898e04 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/BeanOrderConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/BeanOrderConst.java @@ -31,24 +31,29 @@ package org.dromara.visor.common.constant; */ public interface BeanOrderConst { - /** - * 公共返回值包装处理器 - */ - int RESPONSE_ADVICE_WRAPPER = Integer.MIN_VALUE + 1000; - /** * 演示模式切面 */ - int DEMO_DISABLE_API_ASPECT = Integer.MIN_VALUE + 10; + int DEMO_DISABLE_API_ASPECT = Integer.MIN_VALUE + 100; /** * 全局日志打印 */ - int LOG_PRINT_ASPECT = Integer.MIN_VALUE + 20; + int LOG_PRINT_ASPECT = Integer.MIN_VALUE + 200; + + /** + * 暴露接口切面 + */ + int EXPOSE_API_ASPECT = Integer.MIN_VALUE + 300; /** * 操作日志切面 */ - int OPERATOR_LOG_ASPECT = Integer.MIN_VALUE + 30; + int OPERATOR_LOG_ASPECT = Integer.MIN_VALUE + 400; + + /** + * 公共返回值包装处理器 + */ + int RESPONSE_ADVICE_WRAPPER = Integer.MIN_VALUE + 1000; } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/CustomHeaderConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/CustomHeaderConst.java index 3f1017cc..5e96e40d 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/CustomHeaderConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/CustomHeaderConst.java @@ -33,4 +33,8 @@ public interface CustomHeaderConst { String APP_VERSION = "X-App-Version"; + String AGENT_KEY_HEADER = "X-Agent-Key"; + + String AGENT_VERSION_HEADER = "X-Agent-Version"; + } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java index 9e981d47..d1dcd803 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorCode.java @@ -48,6 +48,8 @@ public enum ErrorCode implements CodeInfo { UNAUTHORIZED(401, "当前认证信息已失效, 请重新登录"), + EXPOSE_UNAUTHORIZED(401, "当前认证信息错误, 请检查后重试"), + FORBIDDEN(403, "无操作权限"), NOT_FOUND(404, "未找到该资源"), diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java index ae874b64..c1463e93 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ErrorMessage.java @@ -102,7 +102,7 @@ public interface ErrorMessage { String HOST_TYPE_ERROR = "主机类型错误"; - String HOST_NOT_ENABLED = "主机未启用"; + String HOST_NOT_ENABLED = "{} 主机未启用"; String CONFIG_NOT_ENABLED = "配置未启用"; @@ -146,6 +146,8 @@ public interface ErrorMessage { String FILE_ABSENT = "文件不存在"; + String FILE_EXTENSION_TYPE = "文件类型不正确"; + String FILE_ABSENT_CLEAR = "文件不存在 (可能已被清理)"; String LOG_ABSENT = "日志不存在"; @@ -158,6 +160,8 @@ public interface ErrorMessage { String FILE_UPLOAD_ERROR = "文件上传失败"; + String CALC_SIGN_FAILED = "计算签名失败"; + String SCRIPT_UPLOAD_ERROR = "脚本上传失败"; String EXEC_ERROR = "执行失败"; @@ -182,6 +186,8 @@ public interface ErrorMessage { String COMPRESS_FILE_ABSENT = "压缩文件不存在"; + String DECOMPRESS_FILE_ABSENT = "压缩文件不存在"; + String UNABLE_DOWNLOAD_FOLDER = "无法下载文件夹"; String VALID_ERROR = "验证失败"; @@ -209,6 +215,27 @@ public interface ErrorMessage { || ex instanceof ApplicationException; } + /** + * 获取错误信息 + * + * @param ex ex + * @return message + */ + static String getErrorMessage(Exception ex) { + return getErrorMessage(ex, ErrorMessage.EXEC_ERROR, 0); + } + + /** + * 获取错误信息 + * + * @param ex ex + * @param len len + * @return message + */ + static String getErrorMessage(Exception ex, int len) { + return getErrorMessage(ex, ErrorMessage.EXEC_ERROR, len); + } + /** * 获取错误信息 * @@ -217,6 +244,18 @@ public interface ErrorMessage { * @return message */ static String getErrorMessage(Exception ex, String defaultMsg) { + return getErrorMessage(ex, defaultMsg, 0); + } + + /** + * 获取错误信息 + * + * @param ex ex + * @param defaultMsg defaultMsg + * @param len len + * @return message + */ + static String getErrorMessage(Exception ex, String defaultMsg, int len) { if (ex == null) { return null; } @@ -226,7 +265,11 @@ public interface ErrorMessage { } // 业务异常 if (isBizException(ex)) { - return message; + if (len > 0) { + return Strings.retain(message, len); + } else { + return message; + } } return defaultMsg; } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java index acbaf3e1..830d6739 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/ExtraFieldConst.java @@ -35,6 +35,8 @@ public interface ExtraFieldConst extends FieldConst { String TRACE_ID = "traceId"; + String TASK_ID = "taskId"; + String IDENTITY = "identity"; String GROUP_NAME = "groupName"; @@ -69,4 +71,6 @@ public interface ExtraFieldConst extends FieldConst { String DARK = "dark"; + String AGENT_KEY = "agentKey"; + } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java index 9097021a..539875e1 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FieldConst.java @@ -45,12 +45,18 @@ public interface FieldConst { String LABEL = "label"; + String FIELD = "field"; + String TYPE = "type"; String COLOR = "color"; + String LOADING = "loading"; + String STATUS = "status"; + String SWITCH = "switch"; + String INFO = "info"; String EXTRA = "extra"; @@ -71,6 +77,8 @@ public interface FieldConst { String SEQ = "seq"; + String START = "start"; + String PATH = "path"; String ADDRESS = "address"; @@ -119,4 +127,12 @@ public interface FieldConst { String CONFIG = "config"; + String VERSION = "version"; + + String SYNCED = "synced"; + + String SIGN = "sign"; + + String SIGN_SHORT = "signShort"; + } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FileConst.java b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FileConst.java index df4b1d5f..1a68275a 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FileConst.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/constant/FileConst.java @@ -37,4 +37,20 @@ public interface FileConst { String SCRIPT = "script"; + String INSTANCE_AGENT_PATH = "instance-agent"; + + String INSTANCE_AGENT_NAME = "instance_agent"; + + String INSTANCE_AGENT_FILE_FORMAT = "instance_agent_{}_{}{}"; + + String INSTANCE_AGENT_RELEASE = "instance-agent-release"; + + String INSTANCE_AGENT_RELEASE_TEMP = "instance-agent-release-temp"; + + String INSTANCE_AGENT_RELEASE_TAR_GZ = "instance-agent-release.tar.gz"; + + String VERSION = ".version"; + + String CONFIG_YAML = "config.yaml"; + } diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/entity/chart/TimeChartSeries.java b/orion-visor-common/src/main/java/org/dromara/visor/common/entity/chart/TimeChartSeries.java new file mode 100644 index 00000000..670b8c62 --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/entity/chart/TimeChartSeries.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.entity.chart; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * 时序图系列 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/9/3 21:08 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "TimeChartSeries", description = "时序图系列") +public class TimeChartSeries { + + @Schema(description = "name") + private String name; + + @Schema(description = "颜色") + private String color; + + @Schema(description = "tags") + private Map tags; + + @Schema(description = "数据 [0]timestampMills [1]value") + private List> data; + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/FileClient.java b/orion-visor-common/src/main/java/org/dromara/visor/common/file/FileClient.java similarity index 98% rename from orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/FileClient.java rename to orion-visor-common/src/main/java/org/dromara/visor/common/file/FileClient.java index d6f62d4a..e9ea011b 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/FileClient.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/file/FileClient.java @@ -20,7 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.dromara.visor.common.interfaces; +package org.dromara.visor.common.file; import java.io.InputStream; import java.io.OutputStream; diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/lock/EmptyLocker.java b/orion-visor-common/src/main/java/org/dromara/visor/common/lock/EmptyLocker.java new file mode 100644 index 00000000..b2e16b7c --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/lock/EmptyLocker.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.lock; + +import cn.orionsec.kit.lang.able.Executable; + +import java.util.function.Supplier; + +/** + * 空实现的锁 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/23 13:59 + */ +public class EmptyLocker implements Locker { + + @Override + public boolean tryLockExecute(String key, Executable executable) { + executable.exec(); + return true; + } + + @Override + public boolean tryLockExecute(String key, long timeout, Executable executable) { + executable.exec(); + return true; + } + + @Override + public T tryLockExecute(String key, Supplier callable) { + return callable.get(); + } + + @Override + public T tryLockExecute(String key, long timeout, Supplier callable) { + return callable.get(); + } + + @Override + public void lockExecute(String key, Executable executable) { + executable.exec(); + } + + @Override + public void lockExecute(String key, long timeout, Executable executable) { + executable.exec(); + } + + @Override + public T lockExecute(String key, Supplier callable) { + return callable.get(); + } + + @Override + public T lockExecute(String key, long timeout, Supplier callable) { + return callable.get(); + } + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/lock/Locker.java b/orion-visor-common/src/main/java/org/dromara/visor/common/lock/Locker.java new file mode 100644 index 00000000..12e87471 --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/lock/Locker.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.lock; + +import cn.orionsec.kit.lang.able.Executable; + +import java.util.function.Supplier; + +/** + * 分布式锁 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/5/16 12:24 + */ +public interface Locker { + + /** + * 尝试获取锁并执行 + * + * @param key key + * @param executable exec + * @return 是否获取到锁 + */ + boolean tryLockExecute(String key, Executable executable); + + /** + * 尝试获取锁并执行 + * + * @param key key + * @param timeout timeout + * @param executable exec + * @return 是否获取到锁 + */ + boolean tryLockExecute(String key, long timeout, Executable executable); + + /** + * 尝试获取锁并执行 未获取到锁则抛出异常 + * + * @param key key + * @param callable callable + * @param T + * @return 执行结果 + */ + T tryLockExecute(String key, Supplier callable); + + /** + * 尝试获取锁并执行 未获取到锁则抛出异常 + * + * @param key key + * @param timeout timeout + * @param callable callable + * @param T + * @return 执行结果 + */ + T tryLockExecute(String key, long timeout, Supplier callable); + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param executable exec + */ + void lockExecute(String key, Executable executable); + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param timeout timeout + * @param executable exec + */ + void lockExecute(String key, long timeout, Executable executable); + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param callable callable + * @param T + * @return 执行结果 + */ + T lockExecute(String key, Supplier callable); + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param timeout timeout + * @param callable callable + * @param T + * @return 执行结果 + */ + T lockExecute(String key, long timeout, Supplier callable); + +} diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java index e9d0d82b..785d8ab9 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/BaseConnectConfig.java @@ -63,6 +63,9 @@ public class BaseConnectConfig implements IBaseConnectConfig { @Schema(description = "主机端口") private Integer hostPort; + @Schema(description = "agentKey") + private String agentKey; + @Schema(description = "用户名") private String username; diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java index f6893156..cbba6814 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/session/config/IBaseConnectConfig.java @@ -61,6 +61,10 @@ public interface IBaseConnectConfig { void setHostPort(Integer hostPort); + String getAgentKey(); + + void setAgentKey(String agentKey); + String getUsername(); void setUsername(String username); diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/AesEncryptUtils.java b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/AesEncryptUtils.java index cf8cfaf1..56446750 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/AesEncryptUtils.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/AesEncryptUtils.java @@ -23,7 +23,7 @@ package org.dromara.visor.common.utils; import cn.orionsec.kit.lang.utils.Exceptions; -import org.dromara.visor.common.interfaces.AesEncryptor; +import org.dromara.visor.common.cipher.AesEncryptor; /** * aes 数据加密工具类 diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/LockerUtils.java b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/LockerUtils.java index 01ce1219..e72ba3f2 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/LockerUtils.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/LockerUtils.java @@ -22,9 +22,10 @@ */ package org.dromara.visor.common.utils; +import cn.orionsec.kit.lang.able.Executable; import cn.orionsec.kit.lang.utils.Exceptions; import lombok.extern.slf4j.Slf4j; -import org.dromara.visor.common.interfaces.Locker; +import org.dromara.visor.common.lock.Locker; import java.util.function.Supplier; @@ -44,26 +45,97 @@ public class LockerUtils { } /** - * 尝试获取锁 + * 尝试获取锁并执行 * - * @param key key - * @param run run + * @param key key + * @param executable exec * @return 是否获取到锁 */ - public static boolean tryLock(String key, Runnable run) { - return delegate.tryLock(key, run); + public static boolean tryLockExecute(String key, Executable executable) { + return delegate.tryLockExecute(key, executable); } /** - * 尝试获取锁 + * 尝试获取锁并执行 * - * @param key key - * @param call call - * @param T + * @param key key + * @param timeout timeout + * @param executable exec + * @return 是否获取到锁 + */ + public static boolean tryLockExecute(String key, long timeout, Executable executable) { + return delegate.tryLockExecute(key, timeout, executable); + } + + /** + * 尝试获取锁并执行 未获取到锁则抛出异常 + * + * @param key key + * @param callable callable + * @param T * @return 执行结果 */ - public static T tryLock(String key, Supplier call) { - return delegate.tryLock(key, call); + public static T tryLockExecute(String key, Supplier callable) { + return delegate.tryLockExecute(key, callable); + } + + /** + * 尝试获取锁并执行 未获取到锁则抛出异常 + * + * @param key key + * @param timeout timeout + * @param callable callable + * @param T + * @return 执行结果 + */ + public static T tryLockExecute(String key, long timeout, Supplier callable) { + return delegate.tryLockExecute(key, timeout, callable); + } + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param executable exec + */ + public static void lockExecute(String key, Executable executable) { + delegate.lockExecute(key, executable); + } + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param timeout timeout + * @param executable exec + */ + public static void lockExecute(String key, long timeout, Executable executable) { + delegate.lockExecute(key, timeout, executable); + } + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param callable callable + * @param T + * @return 执行结果 + */ + public static T lockExecute(String key, Supplier callable) { + return delegate.lockExecute(key, callable); + } + + /** + * 阻塞获取锁并执行 + * + * @param key key + * @param timeout timeout + * @param callable callable + * @param T + * @return 执行结果 + */ + public static T lockExecute(String key, long timeout, Supplier callable) { + return delegate.lockExecute(key, timeout, callable); } public static void setDelegate(Locker delegate) { diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/RsaParamDecryptUtils.java b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/RsaParamDecryptUtils.java index 56b24887..f7d14ff6 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/utils/RsaParamDecryptUtils.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/utils/RsaParamDecryptUtils.java @@ -23,7 +23,7 @@ package org.dromara.visor.common.utils; import cn.orionsec.kit.lang.utils.Exceptions; -import org.dromara.visor.common.interfaces.RsaDecryptor; +import org.dromara.visor.common.cipher.RsaDecryptor; /** * rsa 参数解密工具类 diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Id.java b/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Id.java index 5fccd109..6bc5930d 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Id.java +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Id.java @@ -23,7 +23,7 @@ package org.dromara.visor.common.validator.group; /** - * 分页验证分组 + * id 验证分组 * * @author Jiahang Li * @version 1.0.0 diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Key.java b/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Key.java new file mode 100644 index 00000000..6bbe8ea6 --- /dev/null +++ b/orion-visor-common/src/main/java/org/dromara/visor/common/validator/group/Key.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.common.validator.group; + +/** + * key 验证分组 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/9/1 19:13 + */ +public interface Key { +} diff --git a/orion-visor-dependencies/pom.xml b/orion-visor-dependencies/pom.xml index 08190e0d..86ff5680 100644 --- a/orion-visor-dependencies/pom.xml +++ b/orion-visor-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/dromara/orion-visor - 2.4.3 + 2.5.0 2.7.17 2.7.15 1.5.0 @@ -31,6 +31,7 @@ 1.2.16 3.18.0 2.14.2 + 6.6.0 4.11.0 1.0.7 7.2.11.RELEASE @@ -54,8 +55,12 @@ ${orion.kit.version} - orion-log cn.orionsec.kit + orion-log + + + cn.orionsec.kit + orion-generator @@ -118,7 +123,7 @@ org.dromara.visor - orion-visor-spring-boot-starter-encrypt + orion-visor-spring-boot-starter-cipher ${revision} @@ -146,6 +151,11 @@ orion-visor-spring-boot-starter-test ${revision} + + org.dromara.visor + orion-visor-spring-boot-starter-influxdb + ${revision} + org.dromara.visor orion-visor-spring-boot-starter-biz-operator-log @@ -272,6 +282,13 @@ ${transmittable.thread.local.version} + + + com.influxdb + influxdb-client-java + ${influxdb.client.version} + + org.springframework.boot diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-biz-operator-log/src/main/java/org/dromara/visor/framework/biz/operator/log/core/aspect/OperatorLogAspect.java b/orion-visor-framework/orion-visor-spring-boot-starter-biz-operator-log/src/main/java/org/dromara/visor/framework/biz/operator/log/core/aspect/OperatorLogAspect.java index 283e55dd..7b9f32c3 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-biz-operator-log/src/main/java/org/dromara/visor/framework/biz/operator/log/core/aspect/OperatorLogAspect.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-biz-operator-log/src/main/java/org/dromara/visor/framework/biz/operator/log/core/aspect/OperatorLogAspect.java @@ -73,7 +73,6 @@ public class OperatorLogAspect { .maxPoolSize(1) .useLinkedBlockingQueue() .allowCoreThreadTimeout() - .useLinkedBlockingQueue() .build(); private final OperatorLogFrameworkService operatorLogFrameworkService; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/pom.xml b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/pom.xml similarity index 93% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/pom.xml rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/pom.xml index b1364d07..db7e036d 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/pom.xml +++ b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/pom.xml @@ -9,7 +9,7 @@ 4.0.0 - orion-visor-spring-boot-starter-encrypt + orion-visor-spring-boot-starter-cipher ${project.artifactId} jar diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/configuration/OrionEncryptAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/configuration/OrionEncryptAutoConfiguration.java similarity index 93% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/configuration/OrionEncryptAutoConfiguration.java rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/configuration/OrionEncryptAutoConfiguration.java index f6e942be..27c5864b 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/configuration/OrionEncryptAutoConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/configuration/OrionEncryptAutoConfiguration.java @@ -22,10 +22,10 @@ */ package org.dromara.visor.framework.encrypt.configuration; +import org.dromara.visor.common.cipher.AesEncryptor; +import org.dromara.visor.common.cipher.RsaDecryptor; import org.dromara.visor.common.config.ConfigStore; import org.dromara.visor.common.constant.AutoConfigureOrderConst; -import org.dromara.visor.common.interfaces.AesEncryptor; -import org.dromara.visor.common.interfaces.RsaDecryptor; import org.dromara.visor.common.utils.AesEncryptUtils; import org.dromara.visor.common.utils.RsaParamDecryptUtils; import org.dromara.visor.framework.encrypt.configuration.config.AesEncryptConfig; @@ -45,7 +45,7 @@ import org.springframework.context.annotation.Bean; */ @AutoConfiguration @EnableConfigurationProperties({AesEncryptConfig.class}) -@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_ENCRYPT) +@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_CYPHER) public class OrionEncryptAutoConfiguration { /** diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/configuration/config/AesEncryptConfig.java b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/configuration/config/AesEncryptConfig.java similarity index 100% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/configuration/config/AesEncryptConfig.java rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/configuration/config/AesEncryptConfig.java diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/BaseAesEncryptor.java b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/BaseAesEncryptor.java similarity index 96% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/BaseAesEncryptor.java rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/BaseAesEncryptor.java index 27e0a390..4bd331a8 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/BaseAesEncryptor.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/BaseAesEncryptor.java @@ -22,7 +22,7 @@ */ package org.dromara.visor.framework.encrypt.core; -import org.dromara.visor.common.interfaces.AesEncryptor; +import org.dromara.visor.common.cipher.AesEncryptor; /** * 数据加密器 diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/impl/AesEncryptorImpl.java b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/impl/AesEncryptorImpl.java similarity index 100% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/impl/AesEncryptorImpl.java rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/impl/AesEncryptorImpl.java diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/impl/RsaDecryptorImpl.java b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/impl/RsaDecryptorImpl.java similarity index 96% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/impl/RsaDecryptorImpl.java rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/impl/RsaDecryptorImpl.java index 1b482252..7c9cfff3 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/java/org/dromara/visor/framework/encrypt/core/impl/RsaDecryptorImpl.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/java/org/dromara/visor/framework/encrypt/core/impl/RsaDecryptorImpl.java @@ -26,7 +26,7 @@ import cn.orionsec.kit.lang.utils.crypto.RSA; import org.dromara.visor.common.config.ConfigRef; import org.dromara.visor.common.config.ConfigStore; import org.dromara.visor.common.constant.ConfigKeys; -import org.dromara.visor.common.interfaces.RsaDecryptor; +import org.dromara.visor.common.cipher.RsaDecryptor; import java.security.interfaces.RSAPrivateKey; import java.util.Arrays; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/resources/META-INF/additional-spring-configuration-metadata.json similarity index 100% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/resources/META-INF/additional-spring-configuration-metadata.json rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports similarity index 100% rename from orion-visor-framework/orion-visor-spring-boot-starter-encrypt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename to orion-visor-framework/orion-visor-spring-boot-starter-cipher/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/pom.xml b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/pom.xml new file mode 100644 index 00000000..fe47372d --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/pom.xml @@ -0,0 +1,39 @@ + + + + org.dromara.visor + orion-visor-framework + ${revision} + + + 4.0.0 + orion-visor-spring-boot-starter-influxdb + ${project.artifactId} + jar + + 项目 influxdb 配置包 + https://github.com/dromara/orion-visor + + + + + org.dromara.visor + orion-visor-common + + + + + com.influxdb + influxdb-client-java + + + + + org.springframework.boot + spring-boot-starter-web + + + + \ No newline at end of file diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/configuration/OrionInfluxdbAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/configuration/OrionInfluxdbAutoConfiguration.java new file mode 100644 index 00000000..e6982f35 --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/configuration/OrionInfluxdbAutoConfiguration.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.influxdb.configuration; + +import cn.orionsec.kit.lang.utils.Strings; +import com.influxdb.LogLevel; +import com.influxdb.client.InfluxDBClient; +import com.influxdb.client.InfluxDBClientFactory; +import com.influxdb.client.InfluxDBClientOptions; +import org.dromara.visor.common.constant.AutoConfigureOrderConst; +import org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig; +import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; + +import java.net.ConnectException; + +/** + * influxdb 配置类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/10 20:35 + */ +@Lazy(false) +@AutoConfiguration +@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_INFLUXDB) +@ConditionalOnProperty(value = "spring.influxdb.enabled", havingValue = "true") +@EnableConfigurationProperties(InfluxdbConfig.class) +public class OrionInfluxdbAutoConfiguration { + + /** + * TODO 重连 + * + * @param config config + * @return influxdb 客户端 + */ + @Bean(name = "influxDBClient") + public InfluxDBClient influxDBClient(InfluxdbConfig config) throws ConnectException { + // 参数 + InfluxDBClientOptions options = InfluxDBClientOptions.builder() + .url(config.getUrl()) + .authenticateToken(config.getToken().toCharArray()) + .org(config.getOrg()) + .bucket(config.getBucket()) + .logLevel(LogLevel.NONE) + .build(); + // 客户端 + InfluxDBClient client = InfluxDBClientFactory.create(options); + // 尝试连接 + Boolean ping = client.ping(); + if (!ping) { + throw new ConnectException(Strings.format("connect to influxdb failed. url: {}, org: {}", config.getUrl(), config.getOrg())); + } + // 设置工具类 + InfluxdbUtils.setInfluxClient(config.getBucket(), client); + return client; + } + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/configuration/config/InfluxdbConfig.java b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/configuration/config/InfluxdbConfig.java new file mode 100644 index 00000000..c9d53f61 --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/configuration/config/InfluxdbConfig.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.influxdb.configuration.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * influxdb 配置 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/10 20:36 + */ +@Data +@ConfigurationProperties("spring.influxdb") +public class InfluxdbConfig { + + /** + * url + */ + private String url; + + /** + * org + */ + private String org; + + /** + * bucket + */ + private String bucket; + + /** + * apiToken + */ + private String token; + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/core/query/FluxQueryBuilder.java b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/core/query/FluxQueryBuilder.java new file mode 100644 index 00000000..1e479080 --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/core/query/FluxQueryBuilder.java @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.influxdb.core.query; + +import cn.orionsec.kit.lang.utils.collect.Collections; +import cn.orionsec.kit.lang.utils.collect.Lists; +import org.dromara.visor.common.constant.Const; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * flux 查询构建器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/9/3 16:08 + */ +public class FluxQueryBuilder { + + private final StringBuilder query; + + private boolean hasFilter; + + private boolean pretty; + + private FluxQueryBuilder(String bucket) { + this.query = new StringBuilder(); + this.query.append(String.format("from(bucket: \"%s\")", bucket)); + } + + /** + * 创建构建器 + * + * @param bucket bucket + * @return builder + */ + public static FluxQueryBuilder from(String bucket) { + return new FluxQueryBuilder(bucket); + } + + /** + * 时间范围 + * + * @param start 开始时间 + * @param end 结束时间 + * @return this + */ + public FluxQueryBuilder range(long start, long end) { + query.append(String.format(" |> range(start: %s, stop: %s)", Instant.ofEpochMilli(start), Instant.ofEpochMilli(end))); + return this; + } + + /** + * 时间范围 + * + * @param range range + * @return this + */ + public FluxQueryBuilder range(String range) { + query.append(String.format(" |> range(start: %s)", range)); + return this; + } + + /** + * 过滤 measurement + * + * @param measurement measurement + * @return this + */ + public FluxQueryBuilder measurement(String measurement) { + this.appendFilter(String.format("r[\"_measurement\"] == \"%s\"", measurement)); + this.closeFilter(); + return this; + } + + /** + * 过滤单个 field + * + * @param field field + * @return this + */ + public FluxQueryBuilder field(String field) { + this.appendFilter(String.format("r[\"_field\"] == \"%s\"", field)); + this.closeFilter(); + return this; + } + + /** + * 过滤多个 field + * + * @param fields fields + * @return this + */ + public FluxQueryBuilder fields(Collection fields) { + if (Collections.isEmpty(fields)) { + return this; + } + List conditions = new ArrayList<>(); + for (String field : fields) { + conditions.add(String.format("r[\"_field\"] == \"%s\"", field)); + } + this.appendFilter(String.join(" or ", conditions)); + this.closeFilter(); + return this; + } + + /** + * 过滤 tag key + * + * @param value value + * @return this + */ + public FluxQueryBuilder key(String value) { + return this.tag(Const.KEY, value); + } + + /** + * 过滤 tag key + * + * @param values values + * @return this + */ + public FluxQueryBuilder key(Collection values) { + return this.tag(Const.KEY, values); + } + + /** + * 过滤 tag name + * + * @param value value + * @return this + */ + public FluxQueryBuilder name(String value) { + return this.tag(Const.NAME, value); + } + + /** + * 过滤 tag name + * + * @param values values + * @return this + */ + public FluxQueryBuilder name(Collection values) { + return this.tag(Const.NAME, values); + } + + /** + * 过滤 tag + * + * @return this + */ + public FluxQueryBuilder tag(String key, String value) { + this.appendFilter(String.format("r[\"%s\"] == \"%s\"", key, value)); + this.closeFilter(); + return this; + } + + /** + * 过滤 tag + * + * @param key key + * @param values values + * @return this + */ + public FluxQueryBuilder tag(String key, Collection values) { + if (values == null || values.isEmpty()) { + return this; + } + if (values.size() == 1) { + return this.tag(key, Collections.first(values)); + } + // + Collection conditions = values.stream() + .map(value -> String.format("r[\"%s\"] == \"%s\"", key, value)) + .collect(Collectors.toList()); + this.appendFilter(String.join(" or ", conditions)); + this.closeFilter(); + return this; + } + + /** + * 过滤多个 tag + * tag 使用 and + * value 使用 or + * + * @param tags tags + * @return this + */ + public FluxQueryBuilder tags(Map> tags) { + for (Map.Entry> entry : tags.entrySet()) { + String key = entry.getKey(); + Collection values = entry.getValue(); + if (Collections.isEmpty(values)) { + continue; + } + if (values.size() == 1) { + // 单值直接用等号 + String singleValue = values.iterator().next(); + this.appendFilter(String.format("r[\"%s\"] == \"%s\"", key, singleValue)); + } else { + // 多值用 OR + Collection conditions = values.stream() + .map(v -> String.format("r[\"%s\"] == \"%s\"", key, v)) + .collect(Collectors.toList()); + this.appendFilter("(" + String.join(" or ", conditions) + ")"); + } + } + this.closeFilter(); + return this; + } + + /** + * 聚合窗口 + */ + public FluxQueryBuilder aggregateWindow(String every, String fn) { + query.append(String.format(" |> aggregateWindow(every: %s, fn: %s)", every, fn)); + return this; + } + + /** + * 聚合窗口 + */ + public FluxQueryBuilder aggregateWindow(String every, String fn, boolean createEmpty) { + query.append(String.format(" |> aggregateWindow(every: %s, fn: %s, createEmpty: %b)", every, fn, createEmpty)); + return this; + } + + /** + * 排序 + * + * @param columns columns + * @return this + */ + public FluxQueryBuilder sort(List columns) { + StringBuilder cols = new StringBuilder(); + for (int i = 0; i < columns.size(); i++) { + cols.append("\"").append(columns.get(i)).append("\""); + if (i < columns.size() - 1) cols.append(", "); + } + query.append(String.format(" |> sort(columns: [%s])", cols)); + return this; + } + + /** + * 降序 + * + * @param column column + * @return this + */ + public FluxQueryBuilder sortDesc(String column) { + return this.sort(Lists.singleton("-" + column)); + } + + /** + * 升序 + * + * @param column column + * @return this + */ + public FluxQueryBuilder sortAsc(String column) { + return this.sort(Lists.singleton(column)); + } + + /** + * 限制条数 + * + * @param n limit + * @return this + */ + public FluxQueryBuilder limit(int n) { + query.append(String.format(" |> limit(n: %d)", n)); + return this; + } + + /** + * 基础过滤拼接 + */ + private void appendFilter(String condition) { + if (!hasFilter) { + query.append(" |> filter(fn: (r) => "); + this.hasFilter = true; + } else { + query.append(" and "); + } + query.append(condition); + } + + /** + * 结束 filter 并闭合括号 + */ + private void closeFilter() { + if (hasFilter) { + query.append(")"); + this.hasFilter = false; + } + } + + /** + * 设置美观输出 + * + * @return this + */ + public FluxQueryBuilder pretty() { + this.pretty = true; + return this; + } + + /** + * 构建查询 + */ + public String build() { + if (this.pretty) { + return query.toString().replaceAll("\\|>", "\n |>"); + } else { + return query.toString(); + } + } + + @Override + public String toString() { + return this.build(); + } + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/core/utils/InfluxdbUtils.java b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/core/utils/InfluxdbUtils.java new file mode 100644 index 00000000..71a7d901 --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/java/org/dromara/visor/framework/influxdb/core/utils/InfluxdbUtils.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.influxdb.core.utils; + +import cn.orionsec.kit.lang.utils.Exceptions; +import cn.orionsec.kit.lang.utils.collect.Lists; +import com.influxdb.client.InfluxDBClient; +import com.influxdb.client.WriteApi; +import com.influxdb.client.write.Point; +import com.influxdb.query.FluxRecord; +import com.influxdb.query.FluxTable; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.entity.chart.TimeChartSeries; +import org.dromara.visor.framework.influxdb.core.query.FluxQueryBuilder; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * influxdb 工具类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/10 20:47 + */ +public class InfluxdbUtils { + + private static final String FIELD_KEY = "_field"; + + private static final List SKIP_EXTRA_KEY = Lists.of("result", "table", "_measurement", "_start", "_stop", "_time", "_value"); + + private static InfluxDBClient client; + + private static String bucket; + + private InfluxdbUtils() { + } + + /** + * 写入指标 + * + * @param points points + */ + public static void writePoints(List points) { + try (WriteApi api = client.makeWriteApi()) { + // 写入指标 + api.writePoints(points); + } + } + + /** + * 查询数据点 + * + * @param query query + * @return points + */ + public static List queryTable(String query) { + return client.getQueryApi().query(query); + } + + /** + * 查询数据点 + * + * @param query query + * @return points + */ + public static FluxTable querySingleTable(String query) { + return Lists.first(queryTable(query)); + } + + /** + * 查询时序系列 + * + * @param query query + * @return points + */ + public static List querySeries(String query) { + return toSeries(queryTable(query)); + } + + /** + * 查询时序系列 + * + * @param query query + * @return points + */ + public static TimeChartSeries querySingleSeries(String query) { + return toSeries(querySingleTable(query)); + } + + /** + * 转为时序系列 + * + * @param table table + * @return series + */ + public static TimeChartSeries toSeries(FluxTable table) { + // 数据 + Map tags = new HashMap<>(); + List> dataList = new ArrayList<>(); + for (FluxRecord record : table.getRecords()) { + Instant time = record.getTime(); + if (time == null) { + continue; + } + // 设置数据 + List data = new ArrayList<>(2); + data.add(time.toEpochMilli()); + data.add(record.getValue()); + dataList.add(data); + // 设置额外值 + record.getValues().forEach((k, v) -> { + if (SKIP_EXTRA_KEY.contains(k)) { + return; + } + tags.put(k, v); + }); + } + // 设置 field + tags.put(Const.FIELD, tags.get(FIELD_KEY)); + tags.remove(FIELD_KEY); + // 创建 series + return TimeChartSeries.builder() + .data(dataList) + .tags(tags) + .build(); + } + + /** + * 转为时序系列 + * + * @param tables tables + * @return series + */ + public static List toSeries(List tables) { + return tables.stream() + .map(InfluxdbUtils::toSeries) + .collect(Collectors.toList()); + } + + /** + * 获取查询构建器 + * + * @return builder + */ + public static FluxQueryBuilder query() { + return FluxQueryBuilder.from(bucket); + } + + public static void setInfluxClient(String bucket, InfluxDBClient client) { + if (InfluxdbUtils.client != null) { + // unmodified + throw Exceptions.state(); + } + InfluxdbUtils.client = client; + InfluxdbUtils.bucket = bucket; + } + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..28c7773f --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,37 @@ +{ + "groups": [ + { + "name": "spring.influxdb", + "type": "org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig", + "sourceType": "org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig" + } + ], + "properties": [ + { + "name": "spring.influxdb.enabled", + "type": "java.lang.Boolean", + "description": "是否启用 influxdb.", + "defaultValue": "false" + }, + { + "name": "spring.influxdb.url", + "type": "java.lang.String", + "description": "influxdb 地址." + }, + { + "name": "spring.influxdb.org", + "type": "java.lang.String", + "description": "influxdb org." + }, + { + "name": "spring.influxdb.bucket", + "type": "java.lang.String", + "description": "influxdb bucket." + }, + { + "name": "spring.influxdb.token", + "type": "java.lang.String", + "description": "influxdb token." + } + ] +} \ No newline at end of file diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..3eda3a8a --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-influxdb/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.dromara.visor.framework.influxdb.configuration.OrionInfluxdbAutoConfiguration \ No newline at end of file diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-job/src/main/java/org/dromara/visor/framework/job/configuration/OrionAsyncAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-job/src/main/java/org/dromara/visor/framework/job/configuration/OrionAsyncAutoConfiguration.java index 30427ded..7544e5b8 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-job/src/main/java/org/dromara/visor/framework/job/configuration/OrionAsyncAutoConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-job/src/main/java/org/dromara/visor/framework/job/configuration/OrionAsyncAutoConfiguration.java @@ -23,13 +23,13 @@ package org.dromara.visor.framework.job.configuration; import org.dromara.visor.common.constant.AutoConfigureOrderConst; +import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.thread.ThreadPoolMdcTaskExecutor; import org.dromara.visor.framework.job.configuration.config.AsyncExecutorConfig; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.annotation.EnableAsync; @@ -49,13 +49,10 @@ import java.util.concurrent.ThreadPoolExecutor; public class OrionAsyncAutoConfiguration { /** - * 支持 MDC 的异步线程池 - *

* {@code @Async("asyncExecutor")} * - * @return 异步线程池 + * @return 支持 MDC 的异步线程池 */ - @Primary @Bean(name = "asyncExecutor") public TaskExecutor asyncExecutor(AsyncExecutorConfig config) { ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor(); @@ -75,4 +72,25 @@ public class OrionAsyncAutoConfiguration { return executor; } + /** + * {@code @Async("metricsExecutor")} + * + * @return 指标线程池 + */ + @Bean(name = "metricsExecutor") + public TaskExecutor metricsExecutor() { + ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor(); + executor.setCorePoolSize(4); + executor.setMaxPoolSize(8); + executor.setQueueCapacity(1000); + executor.setKeepAliveSeconds(Const.MS_S_60); + executor.setAllowCoreThreadTimeOut(true); + executor.setThreadNamePrefix("metrics-task-"); + executor.setWaitForTasksToCompleteOnShutdown(true); + executor.setAwaitTerminationSeconds(60); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } + } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/annotation/IgnoreLog.java b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/annotation/IgnoreLog.java index 7a9c335c..a72fcd92 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/annotation/IgnoreLog.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/annotation/IgnoreLog.java @@ -29,8 +29,8 @@ import java.lang.annotation.*; /** * 不执行统一日志打印 *

- * 如果设置在方法上,则忽略该方法的日志打印 - * 如果设置到参数上,则忽略该参数的日志打印 + * 如果设置在方法上, 则忽略该方法的日志打印 + * 如果设置到参数上, 则忽略该参数的日志打印 * * @author Jiahang Li * @version 1.0.0 diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/AbstractLogPrinterInterceptor.java b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/AbstractLogPrinterInterceptor.java index 2b219c1a..f0411deb 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/AbstractLogPrinterInterceptor.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/AbstractLogPrinterInterceptor.java @@ -22,6 +22,7 @@ */ package org.dromara.visor.framework.log.core.interceptor; +import cn.orionsec.kit.lang.utils.Strings; import cn.orionsec.kit.lang.utils.collect.Maps; import cn.orionsec.kit.lang.utils.reflect.Classes; import com.alibaba.fastjson.JSON; @@ -31,8 +32,8 @@ import com.alibaba.fastjson.serializer.ValueFilter; import org.aopalliance.intercept.MethodInvocation; import org.dromara.visor.common.json.FieldDesensitizeFilter; import org.dromara.visor.common.json.FieldIgnoreFilter; -import org.dromara.visor.common.trace.TraceIdHolder; import org.dromara.visor.common.security.SecurityHolder; +import org.dromara.visor.common.trace.TraceIdHolder; import org.dromara.visor.framework.log.configuration.config.LogPrinterConfig; import org.dromara.visor.framework.log.core.annotation.IgnoreLog; import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; @@ -42,12 +43,13 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Date; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; -import java.util.function.Predicate; /** * 日志打印拦截器 基类 @@ -60,11 +62,6 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce private static final ThreadLocal IGNORE_LOG_MODE = new ThreadLocal<>(); - /** - * 请求头过滤器 - */ - protected Predicate headerFilter; - /** * 字段过滤器 */ @@ -93,8 +90,6 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce @Override public void init() { - // 请求头过滤器 - this.headerFilter = header -> config.getHeaders().contains(header); // 参数过滤器 this.serializeFilters = new SerializeFilter[]{ // 忽略字段过滤器 @@ -136,6 +131,24 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce } } + /** + * 获取请求头 + * + * @param request request + * @return headers + */ + protected Map getHeaderMap(HttpServletRequest request) { + Map headers = new LinkedHashMap<>(); + for (String headerName : config.getHeaders()) { + String headerValue = request.getHeader(headerName); + if (Strings.isBlank(headerValue)) { + continue; + } + headers.put(headerName, headerValue); + } + return headers; + } + /** * 打印请求信息 * diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/PrettyLogPrinterInterceptor.java b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/PrettyLogPrinterInterceptor.java index 1031ad25..d0aee0dc 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/PrettyLogPrinterInterceptor.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/PrettyLogPrinterInterceptor.java @@ -84,13 +84,11 @@ public class PrettyLogPrinterInterceptor extends AbstractLogPrinterInterceptor { if (request != null) { // remoteAddr requestLog.append("\tremoteAddr: ").append(IpUtils.getRemoteAddr(request)).append('\n'); - // header - Servlets.getHeaderMap(request).forEach((hk, hv) -> { - if (headerFilter.test(hk.toLowerCase())) { - requestLog.append('\t') - .append(hk).append(": ") - .append(hv).append('\n'); - } + // headers + this.getHeaderMap(request).forEach((hk, hv) -> { + requestLog.append('\t') + .append(hk).append(": ") + .append(hv).append('\n'); }); } Method method = invocation.getMethod(); diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/RowLogPrinterInterceptor.java b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/RowLogPrinterInterceptor.java index 6e7696a0..20d47322 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/RowLogPrinterInterceptor.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-log/src/main/java/org/dromara/visor/framework/log/core/interceptor/RowLogPrinterInterceptor.java @@ -85,14 +85,8 @@ public class RowLogPrinterInterceptor extends AbstractLogPrinterInterceptor impl if (request != null) { // remoteAddr fields.put(REMOTE_ADDR, IpUtils.getRemoteAddr(request)); - // header - Map headers = new LinkedHashMap<>(); - Servlets.getHeaderMap(request).forEach((hk, hv) -> { - if (headerFilter.test(hk.toLowerCase())) { - headers.put(hk, hv); - } - }); - fields.put(HEADERS, headers); + // headers + fields.put(HEADERS, this.getHeaderMap(request)); } Method method = invocation.getMethod(); // 方法签名 diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/domain/BaseDO.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/domain/BaseDO.java index e15ccd3e..03feba02 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/domain/BaseDO.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/domain/BaseDO.java @@ -66,7 +66,7 @@ public class BaseDO implements Serializable { private String creator; @Schema(description = "修改人") - @TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR) + @TableField(fill = FieldFill.INSERT_UPDATE, update = "IFNULL(#{et.updater}, updater)", jdbcType = JdbcType.VARCHAR) private String updater; /** @@ -78,4 +78,4 @@ public class BaseDO implements Serializable { @TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.TINYINT) private Boolean deleted; -} \ No newline at end of file +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java index 1cd3bd16..1396b731 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java @@ -54,12 +54,13 @@ public class CodeGenerators { // 作者 String author = Const.ORION_AUTHOR; // 模块 - String module = "infra"; + String module = "asset"; // 生成的表 Table[] tables = { // Template.create("dict_key", "字典配置项", "dict") // .enableProviderApi() // .disableUnitTest() + // .enableDeleteUseBatch() // .cache("dict:keys", "字典配置项") // .expire(8, TimeUnit.HOURS) // .vue("system", "dict-key") @@ -73,23 +74,28 @@ public class CodeGenerators { // .color("blue", "gray", "red", "green", "white") // .valueUseFields() // .build(), - // Template.create("exec_template_host", "执行模板主机", "exec") - // .enableProviderApi() - // .cache("sl", "22") - // .vue("exec", "exec-template-host") - // .build(), - Template.create("system_message", "系统消息", "message") + + Template.create("host_agent_log", "主机探针日志", "agent") .disableUnitTest() - .enableProviderApi() - .vue("system", "message") - .dict("messageType", "type", "messageType") - .comment("消息类型") - .fields("EXEC_FAILED", "UPLOAD_FAILED") - .labels("执行失败", "上传失败") - .extra("tagLabel", "执行失败", "上传失败") - .extra("tagVisible", true, true) - .extra("tagColor", "red", "red") + .vue("monitor", "monitor-host") + .disableRowSelection() + .enableCardView() + .enableDrawerForm() + + .dict("agentLogType", "type") + .comment("探针日志类型") + .fields("OFFLINE", "ONLINE", "INSTALL", "START", "STOP") + .labels("下线", "上线", "安装", "启动", "停止") .valueUseFields() + + .dict("agentLogStatus", "status") + .comment("探针日志状态") + .fields("WAIT", "RUNNING", "SUCCESS", "FAILED") + .labels("等待中", "运行中", "成功", "失败") + .color("green", "green", "arcoblue", "red") + .loading(true, true, false, false) + .valueUseFields() + .build(), }; // jdbc 配置 - 使用配置文件 @@ -98,7 +104,6 @@ public class CodeGenerators { String url = resolveConfigValue(yaml.getValue("spring.datasource.druid.url")); String username = resolveConfigValue(yaml.getValue("spring.datasource.druid.username")); String password = resolveConfigValue(yaml.getValue("spring.datasource.druid.password")); - // 执行 runGenerator(outputDir, author, tables, module, diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/CodeGenerator.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/CodeGenerator.java index d2d0ec94..258e70c7 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/CodeGenerator.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/CodeGenerator.java @@ -23,10 +23,12 @@ package org.dromara.visor.framework.mybatis.core.generator.core; import cn.orionsec.kit.lang.able.Executable; +import cn.orionsec.kit.lang.constant.Const; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.builder.CustomFile; +import com.baomidou.mybatisplus.generator.config.builder.Entity; import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; @@ -135,6 +137,10 @@ public class CodeGenerator implements Executable { // 整合注入配置 .injection(injectionConfig); + // 提前解析父类 并且排除父类的 id 字段 + Entity entity = strategyConfig.entity(); + entity.getSuperEntityColumns().remove(Const.ID); + // 执行 ag.execute(engine); } @@ -188,6 +194,8 @@ public class CodeGenerator implements Executable { case Types.BIT: case Types.TINYINT: return DbColumnType.INTEGER; + case Types.DOUBLE: + return DbColumnType.DOUBLE; default: return typeRegistry.getColumnType(metaInfo); } @@ -321,9 +329,14 @@ public class CodeGenerator implements Executable { */ private InjectionConfig getInjectionConfig() { String[][] customFileDefineArr = new String[][]{ - // -------------------- 后端 - module -------------------- + // -------------------- 后端 -------------------- // http 文件 new String[]{"/templates/orion-server-module-controller.http.vm", "${type}Controller.http", "controller"}, + // operator log define 文件 + new String[]{"/templates/orion-server-module-operator-key-define.java.vm", "${type}OperatorType.java", "define.operator"}, + // convert 文件 + new String[]{"/templates/orion-server-module-convert.java.vm", "${type}Convert.java", "convert"}, + // -------------------- 后端 - 实体 -------------------- // vo 文件 new String[]{"/templates/orion-server-module-entity-vo.java.vm", "${type}VO.java", "entity.vo"}, // create request 文件 @@ -332,19 +345,19 @@ public class CodeGenerator implements Executable { new String[]{"/templates/orion-server-module-entity-request-update.java.vm", "${type}UpdateRequest.java", "entity.request.${bizPackage}"}, // query request 文件 new String[]{"/templates/orion-server-module-entity-request-query.java.vm", "${type}QueryRequest.java", "entity.request.${bizPackage}"}, - // convert 文件 - new String[]{"/templates/orion-server-module-convert.java.vm", "${type}Convert.java", "convert"}, + // -------------------- 后端 - 缓存 -------------------- // cache dto 文件 new String[]{"/templates/orion-server-module-cache-dto.java.vm", "${type}CacheDTO.java", "entity.dto"}, // cache key define 文件 new String[]{"/templates/orion-server-module-cache-key-define.java.vm", "${type}CacheKeyDefine.java", "define.cache"}, - // operator log define 文件 - new String[]{"/templates/orion-server-module-operator-key-define.java.vm", "${type}OperatorType.java", "define.operator"}, // -------------------- 后端 - provider -------------------- // api 文件 new String[]{"/templates/orion-server-provider-api.java.vm", "${type}Api.java", "api"}, // api impl 文件 new String[]{"/templates/orion-server-provider-api-impl.java.vm", "${type}ApiImpl.java", "api.impl"}, + // convert 文件 + new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"}, + // -------------------- 后端 - provider 实体 -------------------- // dto 文件 new String[]{"/templates/orion-server-provider-entity-dto.java.vm", "${type}DTO.java", "entity.dto.${bizPackage}"}, // create dto 文件 @@ -353,8 +366,6 @@ public class CodeGenerator implements Executable { new String[]{"/templates/orion-server-provider-entity-dto-update.java.vm", "${type}UpdateDTO.java", "entity.dto.${bizPackage}"}, // query dto 文件 new String[]{"/templates/orion-server-provider-entity-dto-query.java.vm", "${type}QueryDTO.java", "entity.dto.${bizPackage}"}, - // convert 文件 - new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"}, // -------------------- 后端 - test -------------------- // service unit test 文件 new String[]{"/templates/orion-server-test-service-impl-tests.java.vm", "${type}ServiceImplTests.java", "service.impl"}, @@ -369,22 +380,26 @@ public class CodeGenerator implements Executable { new String[]{"/templates/orion-vue-router.ts.vm", "${feature}.ts", "vue/router/routes/modules"}, // views index.ts 文件 new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${module}/${feature}"}, + // const.ts 文件 + new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"}, + // -------------------- 前端 - form -------------------- // form-modal.vue 文件 new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${module}/${feature}/components"}, // form-drawer.vue 文件 new String[]{"/templates/orion-vue-views-components-form-drawer.vue.vm", "${feature}-form-drawer.vue", "vue/views/${module}/${feature}/components"}, - // table.vue 文件 - new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"}, - // card-list.vue 文件 - new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"}, - // const.ts 文件 - new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"}, // form.rules.ts 文件 new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${module}/${feature}/types"}, + // -------------------- 前端 - table -------------------- + // table.vue 文件 + new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"}, // table.columns.ts 文件 new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${module}/${feature}/types"}, + // -------------------- 前端 - card -------------------- + // card-list.vue 文件 + new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"}, // card.fields.ts 文件 new String[]{"/templates/orion-vue-views-types-card.fields.ts.vm", "card.fields.ts", "vue/views/${module}/${feature}/types"}, + // -------------------- sql -------------------- // menu.sql 文件 new String[]{"/templates/orion-sql-menu.sql.vm", "${tableName}-menu.sql", "sql"}, // dict.sql 文件 diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/DictParser.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/DictParser.java index e66a8487..10f163e8 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/DictParser.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/core/DictParser.java @@ -81,7 +81,7 @@ public class DictParser { meta.setComment(Strings.def(tableField.getComment(), meta.getField())); } // 设置额外参数 schema - if (meta.getExtraValues().size() > 0) { + if (!meta.getExtraValues().isEmpty()) { List> extraSchema = meta.getExtraValues().get(0) .keySet() .stream() diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/template/DictTemplate.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/template/DictTemplate.java index 376ca74b..4ddd1100 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/template/DictTemplate.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/template/DictTemplate.java @@ -165,6 +165,16 @@ public class DictTemplate extends Template { return this.extra(Const.COLOR, colors); } + /** + * 添加 loading + * + * @param loading loading + * @return this + */ + public DictTemplate loading(Object... loading) { + return this.extra(Const.LOADING, loading); + } + /** * 添加额外值 * diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-server-module-entity-do.java.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-server-module-entity-do.java.vm index 25166243..39ec31ca 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-server-module-entity-do.java.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-server-module-entity-do.java.vm @@ -60,6 +60,7 @@ public class ${entity} { #end ## ---------- BEGIN 字段循环遍历 ---------- #foreach($field in ${table.fields}) +#if("$!field.propertyName" != "id") #if(${field.keyFlag}) #set($keyPropertyName=${field.propertyName}) @@ -88,5 +89,6 @@ public class ${entity} { #end private ${field.propertyType} ${field.propertyName}; #end +#end } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-card-list.vue.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-card-list.vue.vm index d0be119d..81142dbf 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-card-list.vue.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-card-list.vue.vm @@ -133,14 +133,14 @@ const cardColLayout = useCardColLayout(); const pagination = useCardPagination(); + const { loading, setLoading } = useLoading(); const queryOrder = useQueryOrder(TableName, ASC); const { cardFieldConfig, fieldsHook } = useCardFieldConfig(TableName, fieldConfig); - const { loading, setLoading } = useLoading(); #if($dictMap.entrySet().size() > 0) const { toOptions, getDictValue } = useDictStore(); #end - const list = ref<${vue.featureEntity}QueryResponse[]>([]); + const list = ref>([]); const formRef = ref(); const formModel = reactive<${vue.featureEntity}QueryRequest>({ searchValue: undefined, diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-table.vue.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-table.vue.vm index 909163ed..0b0b2bce 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-table.vue.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-components-table.vue.vm @@ -172,9 +172,9 @@ const rowSelection = useRowSelection(); #end const pagination = useTablePagination(); + const { loading, setLoading } = useLoading(); const queryOrder = useQueryOrder(TableName, ASC); const { tableColumns, columnsHook } = useTableColumns(TableName, columns); - const { loading, setLoading } = useLoading(); #if($dictMap.entrySet().size() > 0) const { toOptions, getDictValue } = useDictStore(); #end diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-card.fields.ts.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-card.fields.ts.vm index 38ac51c9..60313e3b 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-card.fields.ts.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-card.fields.ts.vm @@ -30,6 +30,7 @@ const fieldConfig = { render: ({ record }) => { return dateFormat(new Date(record.createTime)); }, + default: true, }, { label: '修改时间', dataIndex: 'updateTime', @@ -41,10 +42,17 @@ const fieldConfig = { label: '创建人', dataIndex: 'creator', slotName: 'creator', + width: 148, + ellipsis: true, + tooltip: true, + default: true, }, { label: '修改人', dataIndex: 'updater', slotName: 'updater', + width: 148, + ellipsis: true, + tooltip: true, } ] as CardField[] } as CardFieldConfig; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-const.ts.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-const.ts.vm index bf109351..c961baa6 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-const.ts.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-const.ts.vm @@ -1,4 +1,4 @@ -export const TABLE_NAME = '$table.name'; +export const TableName = '$table.name'; #if($dictMap.entrySet().size() > 0) #foreach($enumEntity in $dictMap.entrySet()) diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-form.rules.ts.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-form.rules.ts.vm index ec72e63f..c59dbe55 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-form.rules.ts.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-form.rules.ts.vm @@ -1,4 +1,5 @@ import type { FieldRule } from '@arco-design/web-vue'; + #foreach($field in ${table.fields}) #if("$!field.propertyName" != "id") #if(${field.propertyType} == 'String' && "$field.metaInfo.jdbcType" != "LONGVARCHAR") diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-table.columns.ts.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-table.columns.ts.vm index d9af843a..94c7f49e 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-table.columns.ts.vm +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-vue-views-types-table.columns.ts.vm @@ -19,6 +19,8 @@ const columns = [ minWidth: 238, ellipsis: true, tooltip: true, + #elseif(${field.propertyType} == 'Integer' || ${field.propertyType} == 'Long') + width: 120, #elseif(${field.propertyType} == 'Date') width: 180, render: ({ record }) => { @@ -35,6 +37,7 @@ const columns = [ render: ({ record }) => { return dateFormat(new Date(record.createTime)); }, + default: true, }, { title: '修改时间', dataIndex: 'updateTime', @@ -48,6 +51,7 @@ const columns = [ title: '创建人', dataIndex: 'creator', slotName: 'creator', + default: true, }, { title: '修改人', dataIndex: 'updater', @@ -58,6 +62,7 @@ const columns = [ width: 130, align: 'center', fixed: 'right', + default: true, }, ] as TableColumnData[]; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionMockRedisAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionMockRedisAutoConfiguration.java index be3188ec..559ac1c6 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionMockRedisAutoConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionMockRedisAutoConfiguration.java @@ -24,7 +24,8 @@ package org.dromara.visor.framework.redis.configuration; import com.github.fppt.jedismock.RedisServer; import org.dromara.visor.common.constant.AutoConfigureOrderConst; -import org.dromara.visor.common.interfaces.Locker; +import org.dromara.visor.common.lock.EmptyLocker; +import org.dromara.visor.common.lock.Locker; import org.dromara.visor.common.utils.LockerUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -35,7 +36,6 @@ import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import java.net.InetAddress; -import java.util.function.Supplier; /** * MockRedis @@ -79,18 +79,7 @@ public class OrionMockRedisAutoConfiguration { */ @Bean public Locker redisLocker() { - Locker locker = new Locker() { - @Override - public boolean tryLock(String key, Runnable run) { - run.run(); - return true; - } - - @Override - public T tryLock(String key, Supplier call) { - return call.get(); - } - }; + EmptyLocker locker = new EmptyLocker(); LockerUtils.setDelegate(locker); return locker; } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionRedisAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionRedisAutoConfiguration.java index 55ca9b83..49016f60 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionRedisAutoConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/configuration/OrionRedisAutoConfiguration.java @@ -24,7 +24,7 @@ package org.dromara.visor.framework.redis.configuration; import cn.orionsec.kit.lang.define.cache.key.CacheKeyDefine; import org.dromara.visor.common.constant.AutoConfigureOrderConst; -import org.dromara.visor.common.interfaces.Locker; +import org.dromara.visor.common.lock.Locker; import org.dromara.visor.common.utils.LockerUtils; import org.dromara.visor.framework.redis.configuration.config.RedissonConfig; import org.dromara.visor.framework.redis.core.lock.RedisLocker; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/lock/RedisLocker.java b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/lock/RedisLocker.java index 03d83c75..876fc88f 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/lock/RedisLocker.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/lock/RedisLocker.java @@ -22,12 +22,14 @@ */ package org.dromara.visor.framework.redis.core.lock; +import cn.orionsec.kit.lang.able.Executable; import cn.orionsec.kit.lang.utils.Exceptions; import lombok.extern.slf4j.Slf4j; -import org.dromara.visor.common.interfaces.Locker; +import org.dromara.visor.common.lock.Locker; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; /** @@ -40,6 +42,8 @@ import java.util.function.Supplier; @Slf4j public class RedisLocker implements Locker { + private static final String LOCK_KEY_PREFIX = "lock:"; + private final RedissonClient redissonClient; public RedisLocker(RedissonClient redissonClient) { @@ -47,37 +51,154 @@ public class RedisLocker implements Locker { } @Override - public boolean tryLock(String key, Runnable run) { + public boolean tryLockExecute(String key, Executable executable) { + return this.tryLockExecute(key, 0, executable); + } + + @Override + public boolean tryLockExecute(String key, long timeout, Executable executable) { // 获取锁 - RLock lock = redissonClient.getLock(key); + RLock lock = this.getLock(key); // 未获取到直接返回 - if (!lock.tryLock()) { - log.info("RedisLocker.tryLock failed {}", key); + if (this.tryLock(lock, timeout)) { return false; } // 执行 try { - run.run(); + executable.exec(); } finally { - lock.unlock(); + this.unlockSafe(lock); } return true; } @Override - public T tryLock(String key, Supplier call) { + public T tryLockExecute(String key, Supplier callable) { + return this.tryLockExecute(key, 0, callable); + } + + @Override + public T tryLockExecute(String key, long timeout, Supplier callable) { // 获取锁 - RLock lock = redissonClient.getLock(key); + RLock lock = this.getLock(key); // 未获取到直接返回 - if (!lock.tryLock()) { - log.info("RedisLocker.tryLock failed {}", key); + if (this.tryLock(lock, timeout)) { throw Exceptions.lock(); } // 执行 try { - return call.get(); + return callable.get(); } finally { + this.unlockSafe(lock); + } + } + + @Override + public void lockExecute(String key, Executable executable) { + this.lockExecute(key, 0, executable); + } + + @Override + public void lockExecute(String key, long timeout, Executable executable) { + // 获取锁 + RLock lock = this.getLock(key); + this.lock(lock, timeout); + // 执行 + try { + executable.exec(); + } finally { + this.unlockSafe(lock); + } + } + + @Override + public T lockExecute(String key, Supplier callable) { + return this.lockExecute(key, 0, callable); + } + + @Override + public T lockExecute(String key, long timeout, Supplier callable) { + // 获取锁 + RLock lock = this.getLock(key); + this.lock(lock, timeout); + // 执行 + try { + return callable.get(); + } finally { + this.unlockSafe(lock); + } + } + + /** + * 获取锁 + * + * @param key key + * @return lock + */ + private RLock getLock(String key) { + return redissonClient.getLock(LOCK_KEY_PREFIX + key); + } + + /** + * 尝试上锁 + * + * @param lock lock + * @param timeout timeout + * @return locked + */ + private boolean tryLock(RLock lock, long timeout) { + boolean result; + try { + if (timeout == 0) { + result = lock.tryLock(); + } else { + result = lock.tryLock(timeout, TimeUnit.MILLISECONDS); + } + if (!result) { + log.warn("RedisLocker.tryLock failed {}", lock.getName()); + } + } catch (InterruptedException e) { + log.error("RedisLocker.tryLock timed out {}", lock.getName(), e); + throw Exceptions.lock(e); + } catch (Exception e) { + log.error("RedisLocker.tryLock error {}", lock.getName(), e); + throw Exceptions.lock(e); + } + return result; + } + + /** + * 上锁 + * + * @param lock lock + * @param timeout timeout + */ + private void lock(RLock lock, long timeout) { + try { + if (timeout == 0) { + lock.lock(); + } else { + lock.lock(timeout, TimeUnit.MILLISECONDS); + } + } catch (Exception e) { + log.error("RedisLocker.lock lock error {}", lock.getName(), e); + throw Exceptions.lock(e); + } + } + + /** + * 安全的释放锁 + * + * @param lock lock + */ + private void unlockSafe(RLock lock) { + if (!lock.isHeldByCurrentThread()) { + return; + } + try { lock.unlock(); + } catch (Exception e) { + log.warn("RedisLocker.unlock failed {}", lock.getName(), e); } } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/utils/RedisStrings.java b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/utils/RedisStrings.java index 5cc8a1cd..65c18d9f 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/utils/RedisStrings.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-redis/src/main/java/org/dromara/visor/framework/redis/core/utils/RedisStrings.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.function.Consumer; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -49,6 +50,42 @@ public class RedisStrings extends RedisUtils { private RedisStrings() { } + /** + * 获取值 + * + * @param key key + * @return value + */ + public static String get(String key) { + return redisTemplate.opsForValue().get(key); + } + + /** + * 获取值 + * + * @param define define + * @return value + */ + public static String get(CacheKeyDefine define) { + return get(define.getKey()); + } + + /** + * 获取值 + * + * @param key key + * @param mapper mapper + * @param T + * @return value + */ + public static T get(String key, Function mapper) { + String value = redisTemplate.opsForValue().get(key); + if (value == null) { + return null; + } + return mapper.apply(value); + } + /** * 获取 json * @@ -56,11 +93,7 @@ public class RedisStrings extends RedisUtils { * @return JSONObject */ public static JSONObject getJson(String key) { - String value = redisTemplate.opsForValue().get(key); - if (value == null) { - return null; - } - return JSON.parseObject(value); + return get(key, JSON::parseObject); } /** @@ -95,57 +128,7 @@ public class RedisStrings extends RedisUtils { * @return T */ public static T getJson(String key, Class type) { - String value = redisTemplate.opsForValue().get(key); - if (value == null) { - return null; - } - return (T) JSON.parseObject(value, type); - } - - /** - * 获取 json 列表 - * - * @param keys keys - * @return cache - */ - public static List getJsonList(Collection keys) { - List values = redisTemplate.opsForValue().multiGet(keys); - if (values == null) { - return new ArrayList<>(); - } - return values.stream() - .map(JSON::parseObject) - .collect(Collectors.toList()); - } - - /** - * 获取 json 列表 - * - * @param keys keys - * @param define define - * @param T - * @return cache - */ - public static List getJsonList(Collection keys, CacheKeyDefine define) { - return getJsonList(keys, (Class) define.getType()); - } - - /** - * 获取 json 列表 - * - * @param keys keys - * @param type type - * @param T - * @return cache - */ - public static List getJsonList(Collection keys, Class type) { - List values = redisTemplate.opsForValue().multiGet(keys); - if (values == null) { - return new ArrayList<>(); - } - return values.stream() - .map(s -> JSON.parseObject(s, type)) - .collect(Collectors.toList()); + return get(key, s -> JSON.parseObject(s, type)); } /** @@ -155,11 +138,7 @@ public class RedisStrings extends RedisUtils { * @return JSONArray */ public static JSONArray getJsonArray(String key) { - String value = redisTemplate.opsForValue().get(key); - if (value == null) { - return null; - } - return JSON.parseArray(value); + return get(key, JSON::parseArray); } /** @@ -194,11 +173,69 @@ public class RedisStrings extends RedisUtils { * @return T */ public static List getJsonArray(String key, Class type) { - String value = redisTemplate.opsForValue().get(key); - if (value == null) { - return null; + return get(key, s -> JSON.parseArray(s, type)); + } + + /** + * 获取 json 列表 + * + * @param keys keys + * @return cache + */ + public static List getList(Collection keys) { + return getList(keys, Function.identity()); + } + + /** + * 获取 json 列表 + * + * @param keys keys + * @param mapper mapper + * @param T + * @return cache + */ + public static List getList(Collection keys, Function mapper) { + List values = redisTemplate.opsForValue().multiGet(keys); + if (values == null) { + return new ArrayList<>(); } - return JSON.parseArray(value, type); + return values.stream() + .map(mapper) + .collect(Collectors.toList()); + } + + /** + * 获取 json 列表 + * + * @param keys keys + * @return cache + */ + public static List getJsonList(Collection keys) { + return getList(keys, JSON::parseObject); + } + + /** + * 获取 json 列表 + * + * @param keys keys + * @param define define + * @param T + * @return cache + */ + public static List getJsonList(Collection keys, CacheKeyDefine define) { + return getList(keys, s -> JSON.parseObject(s, (Class) define.getType())); + } + + /** + * 获取 json 列表 + * + * @param keys keys + * @param type type + * @param T + * @return cache + */ + public static List getJsonList(Collection keys, Class type) { + return getList(keys, s -> JSON.parseObject(s, type)); } /** @@ -208,13 +245,7 @@ public class RedisStrings extends RedisUtils { * @return cache */ public static List getJsonArrayList(Collection keys) { - List values = redisTemplate.opsForValue().multiGet(keys); - if (values == null) { - return new ArrayList<>(); - } - return values.stream() - .map(JSON::parseArray) - .collect(Collectors.toList()); + return getList(keys, JSON::parseArray); } /** @@ -226,7 +257,7 @@ public class RedisStrings extends RedisUtils { * @return cache */ public static List> getJsonArrayList(Collection keys, CacheKeyDefine define) { - return getJsonArrayList(keys, (Class) define.getType()); + return getList(keys, s -> JSON.parseArray(s, (Class) define.getType())); } /** @@ -238,13 +269,7 @@ public class RedisStrings extends RedisUtils { * @return cache */ public static List> getJsonArrayList(Collection keys, Class type) { - List values = redisTemplate.opsForValue().multiGet(keys); - if (values == null) { - return new ArrayList<>(); - } - return values.stream() - .map(s -> JSON.parseArray(s, type)) - .collect(Collectors.toList()); + return getList(keys, s -> JSON.parseArray(s, type)); } /** diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/org/dromara/visor/framework/security/core/handler/AuthenticationEntryPointHandler.java b/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/org/dromara/visor/framework/security/core/handler/AuthenticationEntryPointHandler.java index 6e96dbf6..3f50e731 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/org/dromara/visor/framework/security/core/handler/AuthenticationEntryPointHandler.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/org/dromara/visor/framework/security/core/handler/AuthenticationEntryPointHandler.java @@ -46,6 +46,7 @@ public class AuthenticationEntryPointHandler implements AuthenticationEntryPoint @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException { + log.warn("AuthenticationEntryPoint-commence-401 {}", request.getRequestURI()); log.debug("AuthenticationEntryPoint-commence-unauthorized {}", request.getRequestURI(), e); Servlets.writeHttpWrapper(response, ErrorCode.UNAUTHORIZED.getWrapper()); } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/configuration/OrionStorageAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/configuration/OrionStorageAutoConfiguration.java index 195ab9fb..9ef12898 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/configuration/OrionStorageAutoConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/configuration/OrionStorageAutoConfiguration.java @@ -23,7 +23,7 @@ package org.dromara.visor.framework.storage.configuration; import org.dromara.visor.common.constant.AutoConfigureOrderConst; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.framework.storage.configuration.config.LocalStorageConfig; import org.dromara.visor.framework.storage.configuration.config.LogsStorageConfig; import org.dromara.visor.framework.storage.core.client.local.LocalFileClient; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/core/client/AbstractFileClient.java b/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/core/client/AbstractFileClient.java index 05f7a896..506701ec 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/core/client/AbstractFileClient.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-storage/src/main/java/org/dromara/visor/framework/storage/core/client/AbstractFileClient.java @@ -26,7 +26,7 @@ import cn.orionsec.kit.lang.utils.io.Files1; import cn.orionsec.kit.lang.utils.io.Streams; import cn.orionsec.kit.lang.utils.time.Dates; import org.dromara.visor.common.constant.Const; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import java.io.InputStream; import java.io.OutputStream; diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-test/src/main/java/org/dromara/visor/framework/test/configuration/OrionMockRedisTestConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-test/src/main/java/org/dromara/visor/framework/test/configuration/OrionMockRedisTestConfiguration.java index 7ffe8d85..b94e4231 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-test/src/main/java/org/dromara/visor/framework/test/configuration/OrionMockRedisTestConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-test/src/main/java/org/dromara/visor/framework/test/configuration/OrionMockRedisTestConfiguration.java @@ -23,7 +23,8 @@ package org.dromara.visor.framework.test.configuration; import com.github.fppt.jedismock.RedisServer; -import org.dromara.visor.common.interfaces.Locker; +import org.dromara.visor.common.lock.EmptyLocker; +import org.dromara.visor.common.lock.Locker; import org.dromara.visor.common.utils.LockerUtils; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -33,7 +34,6 @@ import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Profile; import java.net.InetAddress; -import java.util.function.Supplier; /** * 单元测试 redis mock server 初始化 @@ -66,18 +66,7 @@ public class OrionMockRedisTestConfiguration { */ @Bean public Locker unitTestLocker() { - Locker locker = new Locker() { - @Override - public boolean tryLock(String key, Runnable run) { - run.run(); - return true; - } - - @Override - public T tryLock(String key, Supplier call) { - return call.get(); - } - }; + EmptyLocker locker = new EmptyLocker(); LockerUtils.setDelegate(locker); return locker; } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/OrionWebAutoConfiguration.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/OrionWebAutoConfiguration.java index 46b53817..3c90dcbe 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/OrionWebAutoConfiguration.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/OrionWebAutoConfiguration.java @@ -28,7 +28,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.dromara.visor.common.constant.AutoConfigureOrderConst; import org.dromara.visor.common.constant.FilterOrderConst; import org.dromara.visor.common.web.WebFilterCreator; +import org.dromara.visor.framework.web.configuration.config.ExposeApiConfig; import org.dromara.visor.framework.web.core.aspect.DemoDisableApiAspect; +import org.dromara.visor.framework.web.core.aspect.ExposeApiAspect; import org.dromara.visor.framework.web.core.filter.TraceIdFilter; import org.dromara.visor.framework.web.core.handler.GlobalExceptionHandler; import org.dromara.visor.framework.web.core.handler.WrapperResultHandler; @@ -37,6 +39,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.http.MediaType; @@ -50,6 +53,7 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.nio.charset.StandardCharsets; @@ -67,8 +71,12 @@ import java.util.List; */ @AutoConfiguration @AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_WEB) +@EnableConfigurationProperties(ExposeApiConfig.class) public class OrionWebAutoConfiguration implements WebMvcConfigurer { + @Value("${orion.prefix}") + private String orionPrefix; + @Value("${orion.api.prefix}") private String orionApiPrefix; @@ -77,7 +85,14 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer { // 公共 api 前缀 AntPathMatcher antPathMatcher = new AntPathMatcher("."); configurer.addPathPrefix(orionApiPrefix, clazz -> clazz.isAnnotationPresent(RestController.class) - && antPathMatcher.match("org.dromara.visor.**.controller.**", clazz.getPackage().getName())); + && antPathMatcher.match("org.dromara.visor.module.**.controller.**", clazz.getPackage().getName())); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 公共模板前缀 + registry.addResourceHandler(orionPrefix + "/template/**") + .addResourceLocations("classpath:/public/template/"); } /** @@ -171,4 +186,13 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer { return new DemoDisableApiAspect(); } + /** + * @param config config + * @return 对外服务 api 切面 + */ + @Bean + public ExposeApiAspect exposeApiAspect(ExposeApiConfig config) { + return new ExposeApiAspect(config); + } + } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/config/ExposeApiConfig.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/config/ExposeApiConfig.java new file mode 100644 index 00000000..49e39feb --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/configuration/config/ExposeApiConfig.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.web.configuration.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 对外服务配置属性 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 19:57 + */ +@Data +@ConfigurationProperties("orion.api.expose") +public class ExposeApiConfig { + + /** + * 对外服务请求头 + */ + private String header; + + /** + * 对外服务请求值 + */ + private String token; + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/annotation/ExposeApi.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/annotation/ExposeApi.java new file mode 100644 index 00000000..a51ea6c3 --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/annotation/ExposeApi.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.web.core.annotation; + +import javax.annotation.security.PermitAll; +import java.lang.annotation.*; + +/** + * 对外服务 api 注解 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 9:59 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@PermitAll +public @interface ExposeApi { + + /** + * @return 请求来源 + */ + String source() default ""; + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/DemoDisableApiAspect.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/DemoDisableApiAspect.java index 2dc45e96..54bf5724 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/DemoDisableApiAspect.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/DemoDisableApiAspect.java @@ -22,7 +22,6 @@ */ package org.dromara.visor.framework.web.core.aspect; -import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @@ -39,7 +38,6 @@ import org.springframework.core.annotation.Order; * @since 2024/5/21 16:52 */ @Aspect -@Slf4j @Order(BeanOrderConst.DEMO_DISABLE_API_ASPECT) public class DemoDisableApiAspect { diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/ExposeApiAspect.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/ExposeApiAspect.java new file mode 100644 index 00000000..d413438b --- /dev/null +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/aspect/ExposeApiAspect.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.framework.web.core.aspect; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.dromara.visor.common.constant.BeanOrderConst; +import org.dromara.visor.common.constant.ErrorCode; +import org.dromara.visor.framework.web.configuration.config.ExposeApiConfig; +import org.dromara.visor.framework.web.core.annotation.ExposeApi; +import org.springframework.core.annotation.Order; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Optional; + +/** + * 对外服务 api 切面 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 16:52 + */ +@Slf4j +@Aspect +@Order(BeanOrderConst.EXPOSE_API_ASPECT) +public class ExposeApiAspect { + + private final ExposeApiConfig config; + + public ExposeApiAspect(ExposeApiConfig config) { + this.config = config; + } + + @Pointcut("@annotation(e)") + public void exposeApi(ExposeApi e) { + } + + @Before(value = "exposeApi(e)", argNames = "e") + public void beforeExposeApi(ExposeApi e) { + // 获取请求 + HttpServletRequest request = Optional.ofNullable(RequestContextHolder.getRequestAttributes()) + .map(s -> (ServletRequestAttributes) s) + .map(ServletRequestAttributes::getRequest) + .orElse(null); + if (request == null) { + throw ErrorCode.EXPOSE_UNAUTHORIZED.exception(); + } + // 验证对外服务参数 + if (!config.getToken().equals(request.getHeader(config.getHeader()))) { + log.warn("expose api unauthorized, url: {}", request.getRequestURI()); + throw ErrorCode.EXPOSE_UNAUTHORIZED.exception(); + } + } + +} diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/handler/GlobalExceptionHandler.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/handler/GlobalExceptionHandler.java index 0a47cd58..cbfaf0b2 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/handler/GlobalExceptionHandler.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/org/dromara/visor/framework/web/core/handler/GlobalExceptionHandler.java @@ -149,6 +149,7 @@ public class GlobalExceptionHandler { } @ExceptionHandler(value = { + LockException.class, TimeoutException.class, java.util.concurrent.TimeoutException.class }) diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 996c79b1..ec187a88 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,4 +1,11 @@ { + "groups": [ + { + "name": "orion.api.expose", + "type": "org.dromara.visor.framework.web.configuration.config.ExposeApiConfig", + "sourceType": "org.dromara.visor.framework.web.configuration.config.ExposeApiConfig" + } + ], "properties": [ { "name": "orion.version", @@ -25,6 +32,16 @@ "name": "orion.api.cors", "type": "java.lang.Boolean", "description": "是否开启 cors 过滤器." + }, + { + "name": "orion.api.expose.header", + "type": "java.lang.String", + "description": "对外服务请求头." + }, + { + "name": "orion.api.expose.token", + "type": "java.lang.String", + "description": "对外服务请求值." } ] } \ No newline at end of file diff --git a/orion-visor-framework/pom.xml b/orion-visor-framework/pom.xml index 209522eb..7cec0d7f 100644 --- a/orion-visor-framework/pom.xml +++ b/orion-visor-framework/pom.xml @@ -21,17 +21,18 @@ orion-visor-spring-boot-starter-swagger orion-visor-spring-boot-starter-datasource orion-visor-spring-boot-starter-mybatis + orion-visor-spring-boot-starter-cipher orion-visor-spring-boot-starter-config orion-visor-spring-boot-starter-job orion-visor-spring-boot-starter-websocket orion-visor-spring-boot-starter-redis orion-visor-spring-boot-starter-desensitize - orion-visor-spring-boot-starter-encrypt orion-visor-spring-boot-starter-log orion-visor-spring-boot-starter-storage orion-visor-spring-boot-starter-security orion-visor-spring-boot-starter-monitor orion-visor-spring-boot-starter-test + orion-visor-spring-boot-starter-influxdb orion-visor-spring-boot-starter-biz-operator-log diff --git a/orion-visor-launch/pom.xml b/orion-visor-launch/pom.xml index fa4e9ee6..177d1b91 100644 --- a/orion-visor-launch/pom.xml +++ b/orion-visor-launch/pom.xml @@ -63,6 +63,11 @@ orion-visor-module-terminal-service ${revision} + + org.dromara.visor + orion-visor-module-monitor-service + ${revision} + @@ -91,7 +96,7 @@ org.dromara.visor - orion-visor-spring-boot-starter-encrypt + orion-visor-spring-boot-starter-cipher org.dromara.visor @@ -125,6 +130,10 @@ org.dromara.visor orion-visor-spring-boot-starter-monitor + + org.dromara.visor + orion-visor-spring-boot-starter-influxdb + org.dromara.visor orion-visor-spring-boot-starter-biz-operator-log diff --git a/orion-visor-launch/src/main/java/org/dromara/visor/launch/LaunchApplication.java b/orion-visor-launch/src/main/java/org/dromara/visor/launch/LaunchApplication.java index fae60a26..a69d47ba 100644 --- a/orion-visor-launch/src/main/java/org/dromara/visor/launch/LaunchApplication.java +++ b/orion-visor-launch/src/main/java/org/dromara/visor/launch/LaunchApplication.java @@ -32,7 +32,9 @@ import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.stereotype.Component; +import java.util.Objects; import java.util.Optional; /** @@ -60,7 +62,7 @@ public class LaunchApplication { */ public static class CustomBeanNameGenerator implements BeanNameGenerator { - private static final String BEAN_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Component"; + private static final String BEAN_ANNOTATION_CLASS_NAME = Component.class.getName(); @Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { @@ -68,12 +70,12 @@ public class LaunchApplication { if (definition instanceof AnnotatedBeanDefinition) { AnnotationMetadata metadata = ((AnnotatedBeanDefinition) definition).getMetadata(); // 处理自定义 bean 名称 - return Optional.of(metadata) + return Objects.requireNonNull(Optional.of(metadata) .map(s -> s.getAnnotationAttributes(BEAN_ANNOTATION_CLASS_NAME)) .map(s -> s.get(Const.VALUE)) .map(Object::toString) .filter(Strings::isNotBlank) - .orElseGet(definition::getBeanClassName); + .orElseGet(definition::getBeanClassName)); } else { // 非注解形式默认使用默认名称 return BeanDefinitionReaderUtils.generateBeanName(definition, registry); diff --git a/orion-visor-launch/src/main/resources/application-dev.yaml b/orion-visor-launch/src/main/resources/application-dev.yaml index 09ff44f0..312c7a46 100644 --- a/orion-visor-launch/src/main/resources/application-dev.yaml +++ b/orion-visor-launch/src/main/resources/application-dev.yaml @@ -20,6 +20,12 @@ spring: threads: 2 netty-threads: 2 minimum-idle-size: 2 + influxdb: + enabled: ${INFLUXDB_ENABLED:true} + url: http://${INFLUXDB_HOST:127.0.0.1}:${INFLUXDB_PORT:8086} + org: ${INFLUXDB_ORG:orion-visor} + bucket: ${INFLUXDB_BUCKET:metrics} + token: ${INFLUXDB_TOKEN:Data@123456} boot: admin: client: diff --git a/orion-visor-launch/src/main/resources/application-prod.yaml b/orion-visor-launch/src/main/resources/application-prod.yaml index c86b4f11..c6cf2897 100644 --- a/orion-visor-launch/src/main/resources/application-prod.yaml +++ b/orion-visor-launch/src/main/resources/application-prod.yaml @@ -30,6 +30,12 @@ spring: threads: 4 netty-threads: 4 minimum-idle-size: 4 + influxdb: + enabled: ${INFLUXDB_ENABLED:true} + url: http://${INFLUXDB_HOST:127.0.0.1}:${INFLUXDB_PORT:8086} + org: ${INFLUXDB_ORG:orion-visor} + bucket: ${INFLUXDB_BUCKET:metrics} + token: ${INFLUXDB_TOKEN:Data@123456} quartz: properties: org: @@ -65,9 +71,15 @@ knife4j: orion: # 是否为演示模式 demo: ${DEMO_MODE:false} + api: + # 是否允许跨域 + cors: ${API_CORS:true} + expose: + # 暴露接口请求头值 + token: ${API_EXPOSE_TOKEN:pmqeHOyZaumHm0Wt} logging: printer: - mode: ROW + mode: PRETTY encrypt: aes: # 加密密钥 diff --git a/orion-visor-launch/src/main/resources/application.yaml b/orion-visor-launch/src/main/resources/application.yaml index a84f28e7..c04432cc 100644 --- a/orion-visor-launch/src/main/resources/application.yaml +++ b/orion-visor-launch/src/main/resources/application.yaml @@ -13,9 +13,9 @@ spring: # 文件上传相关配置项 multipart: # 单个文件大小 - max-file-size: 16MB + max-file-size: 128MB # 消息体大小 - max-request-size: 32MB + max-request-size: 128MB mvc: pathmatch: matching-strategy: ANT_PATH_MATCHER @@ -170,6 +170,12 @@ orion: prefix: ${orion.prefix}/api # 是否允许跨域 cors: true + # 对外服务 + expose: + # 暴露接口请求头 + header: X-Server-Token + # 暴露接口请求头值 + token: 96QEPoOChlMfAEPn websocket: # 公共 websocket 前缀 prefix: ${orion.prefix}/keep-alive @@ -202,14 +208,17 @@ orion: terminal: group: "terminal - 终端模块" path: "terminal" + monitor: + group: "monitor - 监控模块" + path: "monitor" logging: # 全局日志打印 printer: mode: PRETTY expression: 'execution (* org.dromara.visor..*.controller..*.*(..))' headers: - - user-agent,accept - - content-type + - User-Agent,Accept + - X-Agent-Version # 下面引用了 需要注意 field: ignore: diff --git a/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java b/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java index 93d05ef7..fe8edd6f 100644 --- a/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java +++ b/orion-visor-launch/src/test/java/org/dromara/visor/launch/ReplaceVersion.java @@ -39,17 +39,17 @@ import java.util.function.Function; */ public class ReplaceVersion { - private static final String TARGET_VERSION = "2.4.2"; + private static final String TARGET_VERSION = "2.4.3"; - private static final String REPLACE_VERSION = "2.4.3"; + private static final String REPLACE_VERSION = "2.5.0"; private static final String PATH = new File("").getAbsolutePath(); private static final String[] DOCKER_FILES = new String[]{ "docker/docker-build.sh", "docker/project-build.sh", - "docker-compose.yml", - "docker-compose-testing.yml" + "docker-compose.yaml", + "docker-compose-testing.yaml" }; private static final String[] POM_FILES = new String[]{ diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/pom.xml b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/pom.xml index b9ddc97a..f8b19f9c 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/pom.xml +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/pom.xml @@ -20,6 +20,11 @@ org.dromara.visor orion-visor-common + + org.dromara.visor + orion-visor-module-infra-provider + ${revision} + \ No newline at end of file diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostAgentApi.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostAgentApi.java new file mode 100644 index 00000000..49c8cde6 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostAgentApi.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.api; + +import org.dromara.visor.module.asset.entity.dto.host.HostAgentLogDTO; + +import java.util.List; +import java.util.Map; + +/** + * 主机探针对外服务 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/9/1 21:14 + */ +public interface HostAgentApi { + + /** + * 查询主机探针安装日志 + * + * @param hostIdList hostIdList + * @return rows + */ + List selectAgentInstallLog(List hostIdList); + + /** + * 获取缓存名称 + * + * @param agentKeyList agentKeyList + * @return nameMap + */ + Map getCacheNameByAgentKey(List agentKeyList); + + /** + * 获取探针版本 + * + * @return version + */ + String getAgentVersion(); + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostApi.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostApi.java index 33a4dc1e..cc745ff4 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostApi.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/api/HostApi.java @@ -22,7 +22,9 @@ */ package org.dromara.visor.module.asset.api; +import cn.orionsec.kit.lang.define.wrapper.DataGrid; import org.dromara.visor.module.asset.entity.dto.host.HostDTO; +import org.dromara.visor.module.asset.entity.dto.host.HostQueryDTO; import java.util.List; @@ -51,4 +53,37 @@ public interface HostApi { */ List selectByIdList(List idList); + /** + * 通过 id 查询 agentKey + * + * @param id id + * @return agentKey + */ + String selectAgentKeyById(Long id); + + /** + * 分页查询主机信息 + * + * @param query query + * @return rows + */ + DataGrid getHostPage(HostQueryDTO query); + + + /** + * 通过 agentKey 查询 + * + * @param agentKey agentKey + * @return row + */ + HostDTO selectByAgentKey(String agentKey); + + /** + * 通过 agentKey 查询 + * + * @param agentKeys agentKeys + * @return row + */ + List selectByAgentKeys(List agentKeys); + } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostAgentLogDTO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostAgentLogDTO.java new file mode 100644 index 00000000..daeff621 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostAgentLogDTO.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.dto.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * 主机探针安装日志 业务响应对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/9/1 17:34 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostAgentInstallLogDTO", description = "主机探针安装日志 业务响应对象") +public class HostAgentLogDTO implements Serializable { + + @Schema(description = "id") + private Long id; + + @Schema(description = "hostId") + private Long hostId; + + @Schema(description = "类型") + private String type; + + @Schema(description = "状态") + private String status; + + @Schema(description = "消息") + private String message; + + @Schema(description = "创建时间") + private Date createTime; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostBaseDTO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostBaseDTO.java index e9fba21f..6b0a3bf8 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostBaseDTO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostBaseDTO.java @@ -67,7 +67,7 @@ public class HostBaseDTO implements Serializable { @Schema(description = "主机地址") private String address; - @Schema(description = "主机端口") - private Integer port; + @Schema(description = "agentKey") + private String agentKey; } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostDTO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostDTO.java index eaaf3346..06b6da2d 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostDTO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostDTO.java @@ -27,9 +27,11 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.dromara.visor.module.infra.entity.dto.tag.TagDTO; import java.io.Serializable; import java.util.Date; +import java.util.List; import java.util.Set; /** @@ -69,12 +71,24 @@ public class HostDTO implements Serializable { @Schema(description = "主机地址") private String address; - @Schema(description = "主机端口") - private Integer port; - @Schema(description = "主机状态") private String status; + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "探针版本") + private String agentVersion; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + + @Schema(description = "探针切换在线状态时间") + private Date agentOnlineChangeTime; + @Schema(description = "描述") private String description; @@ -93,6 +107,9 @@ public class HostDTO implements Serializable { @Schema(description = "是否收藏") private Boolean favorite; + @Schema(description = "tags") + private List tags; + @Schema(description = "分组 id") private Set groupIdList; @@ -114,7 +131,7 @@ public class HostDTO implements Serializable { .name(this.name) .code(this.code) .address(this.address) - .port(this.port) + .agentKey(this.agentKey) .build(); } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostQueryDTO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostQueryDTO.java new file mode 100644 index 00000000..126c0aa4 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/entity/dto/host/HostQueryDTO.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.dto.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.visor.common.entity.BaseQueryRequest; + +import javax.validation.constraints.Size; +import java.util.List; + +/** + * 主机 查询请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023-9-11 14:16 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(name = "HostQueryDTO", description = "主机 查询请求对象") +public class HostQueryDTO extends BaseQueryRequest { + + @Schema(description = "搜索") + private String searchValue; + + @Schema(description = "id") + private Long id; + + @Schema(description = "id") + private List idList; + + @Size(max = 8) + @Schema(description = "主机类型") + private String type; + + @Size(max = 64) + @Schema(description = "主机名称") + private String name; + + @Size(max = 64) + @Schema(description = "主机编码") + private String code; + + @Size(max = 128) + @Schema(description = "主机地址") + private String address; + + @Size(max = 12) + @Schema(description = "系统类型") + private String osType; + + @Size(max = 12) + @Schema(description = "系统架构") + private String archType; + + @Size(max = 8) + @Schema(description = "主机状态") + private String status; + + @Size(max = 255) + @Schema(description = "描述") + private String description; + + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + + @Schema(description = "通过探针排序") + private Boolean orderByAgent; + + @Schema(description = "tag") + private List tags; + + @Schema(description = "是否查询分组信息") + private Boolean queryGroup; + + @Schema(description = "是否查询 tag 信息") + private Boolean queryTag; + + @Schema(description = "是否查询规格信息") + private Boolean querySpec; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/AgentInstallStatusEnum.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/AgentInstallStatusEnum.java new file mode 100644 index 00000000..69d07dfa --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/AgentInstallStatusEnum.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 探针安装状态 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/13 23:31 + */ +@Getter +@AllArgsConstructor +public enum AgentInstallStatusEnum { + + /** + * 未安装 + */ + NOT_INSTALL(0), + + /** + * 已安装 + */ + INSTALLED(1), + + ; + + private final Integer status; + + public static AgentInstallStatusEnum of(Integer status) { + if (status == null) { + return NOT_INSTALL; + } + for (AgentInstallStatusEnum value : AgentInstallStatusEnum.values()) { + if (value.status.equals(status)) { + return value; + } + } + return NOT_INSTALL; + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/AgentOnlineStatusEnum.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/AgentOnlineStatusEnum.java new file mode 100644 index 00000000..cd94e89c --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/AgentOnlineStatusEnum.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 探针在线状态 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/13 23:31 + */ +@Getter +@AllArgsConstructor +public enum AgentOnlineStatusEnum { + + /** + * 离线 + */ + OFFLINE(0), + + /** + * 在线 + */ + ONLINE(1), + + ; + + private final Integer value; + + public static AgentOnlineStatusEnum of(Integer value) { + if (value == null) { + return OFFLINE; + } + for (AgentOnlineStatusEnum e : AgentOnlineStatusEnum.values()) { + if (e.value.equals(value)) { + return e; + } + } + return OFFLINE; + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostOsTypeEnum.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostOsTypeEnum.java index ca4fc5a1..50051da4 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostOsTypeEnum.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostOsTypeEnum.java @@ -39,22 +39,24 @@ public enum HostOsTypeEnum { /** * linux */ - LINUX(".sh"), + LINUX(".sh", ""), /** * windows */ - WINDOWS(".cmd"), + WINDOWS(".cmd", ".exe"), /** * darwin */ - DARWIN(".sh"), + DARWIN(".sh", ""), ; private final String scriptSuffix; + private final String binarySuffix; + public boolean is(String type) { if (type == null) { return false; diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostTypeEnum.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostTypeEnum.java index e4bf6760..09765a0e 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostTypeEnum.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-provider/src/main/java/org/dromara/visor/module/asset/enums/HostTypeEnum.java @@ -76,6 +76,12 @@ public enum HostTypeEnum { return null; } + /** + * 获取类型 + * + * @param types types + * @return types + */ public static List split(String types) { if (types == null) { return new ArrayList<>(); @@ -87,6 +93,16 @@ public enum HostTypeEnum { .collect(Collectors.toList()); } + /** + * 是否包含此类型 + * + * @param types types + * @return contains + */ + public boolean contains(String types) { + return split(types).contains(this.name()); + } + @SuppressWarnings("unchecked") public T parse(String config) { return (T) JSON.parseObject(config, this.clazz); diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/pom.xml b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/pom.xml index 8f09d18d..c0e1beaf 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/pom.xml +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/pom.xml @@ -37,6 +37,11 @@ orion-visor-module-exec-provider ${revision} + + org.dromara.visor + orion-visor-module-monitor-provider + ${revision} + @@ -61,7 +66,7 @@ org.dromara.visor - orion-visor-spring-boot-starter-encrypt + orion-visor-spring-boot-starter-cipher org.dromara.visor diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostAgentApiImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostAgentApiImpl.java new file mode 100644 index 00000000..e5d31a5c --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostAgentApiImpl.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.api.impl; + +import cn.orionsec.kit.lang.define.cache.TimedCache; +import cn.orionsec.kit.lang.define.cache.TimedCacheBuilder; +import cn.orionsec.kit.lang.utils.Strings; +import cn.orionsec.kit.lang.utils.collect.Lists; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.framework.redis.core.utils.RedisStrings; +import org.dromara.visor.module.asset.api.HostAgentApi; +import org.dromara.visor.module.asset.convert.HostAgentLogProviderConvert; +import org.dromara.visor.module.asset.dao.HostAgentLogDAO; +import org.dromara.visor.module.asset.dao.HostDAO; +import org.dromara.visor.module.asset.define.cache.HostCacheKeyDefine; +import org.dromara.visor.module.asset.entity.domain.HostDO; +import org.dromara.visor.module.asset.entity.dto.host.HostAgentLogDTO; +import org.dromara.visor.module.asset.service.HostAgentService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 主机探针对外服务 实现 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/9/1 21:18 + */ +@Service +public class HostAgentApiImpl implements HostAgentApi { + + private static final TimedCache AGENT_NAME_CACHE = TimedCacheBuilder.create() + .expiredDelay(Const.MS_S_60 * 30) + .checkDelay(Const.MS_S_60) + .build(); + + @Resource + private HostDAO hostDAO; + + @Resource + private HostAgentLogDAO hostAgentLogDAO; + + @Resource + private HostAgentService hostAgentService; + + @Override + public List selectAgentInstallLog(List hostIdList) { + if (Lists.isEmpty(hostIdList)) { + return Lists.empty(); + } + // 查询缓存 + List keys = hostIdList.stream() + .map(HostCacheKeyDefine.HOST_INSTALL_LOG::format) + .collect(Collectors.toList()); + List logIdList = RedisStrings.getList(keys) + .stream() + .filter(Strings::isNotBlank) + .map(Long::parseLong) + .collect(Collectors.toList()); + if (logIdList.isEmpty()) { + return Lists.empty(); + } + // 查询数据库 + return hostAgentLogDAO.selectBatchIds(logIdList) + .stream() + .map(HostAgentLogProviderConvert.MAPPER::to) + .collect(Collectors.toList()); + } + + @Override + public Map getCacheNameByAgentKey(List agentKeyList) { + Map result = new HashMap<>(); + List queryList = new ArrayList<>(); + // 查询缓存 + for (String agentKey : agentKeyList) { + String name = AGENT_NAME_CACHE.get(agentKey); + if (name != null) { + result.put(agentKey, name); + } else { + queryList.add(agentKey); + } + } + // 查询数据库 + if (!queryList.isEmpty()) { + // 查询数据 + hostDAO.of() + .createWrapper() + .select(HostDO::getName, HostDO::getAgentKey) + .in(HostDO::getAgentKey, queryList) + .then() + .list() + .forEach(s -> result.put(s.getAgentKey(), s.getName())); + for (String agentKey : queryList) { + result.putIfAbsent(agentKey, Const.EMPTY); + AGENT_NAME_CACHE.put(agentKey, result.get(agentKey)); + } + } + return result; + } + + @Override + public String getAgentVersion() { + return hostAgentService.getAgentVersion(); + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostApiImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostApiImpl.java index 419a98f6..b18b1407 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostApiImpl.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/api/impl/HostApiImpl.java @@ -22,12 +22,17 @@ */ package org.dromara.visor.module.asset.api.impl; +import cn.orionsec.kit.lang.define.wrapper.DataGrid; import cn.orionsec.kit.lang.utils.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.dromara.visor.module.asset.api.HostApi; import org.dromara.visor.module.asset.convert.HostProviderConvert; import org.dromara.visor.module.asset.dao.HostDAO; +import org.dromara.visor.module.asset.entity.domain.HostDO; import org.dromara.visor.module.asset.entity.dto.host.HostDTO; +import org.dromara.visor.module.asset.entity.dto.host.HostQueryDTO; +import org.dromara.visor.module.asset.entity.request.host.HostQueryRequest; +import org.dromara.visor.module.asset.service.HostService; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -48,6 +53,9 @@ public class HostApiImpl implements HostApi { @Resource private HostDAO hostDAO; + @Resource + private HostService hostService; + @Override public HostDTO selectById(Long id) { return HostProviderConvert.MAPPER.to(hostDAO.selectById(id)); @@ -64,4 +72,40 @@ public class HostApiImpl implements HostApi { .collect(Collectors.toList()); } + @Override + public String selectAgentKeyById(Long id) { + return hostDAO.of() + .createWrapper() + .select(HostDO::getAgentKey) + .eq(HostDO::getId, id) + .then() + .getOne(HostDO::getAgentKey); + } + + @Override + public DataGrid getHostPage(HostQueryDTO query) { + // 转换 + HostQueryRequest queryRequest = HostProviderConvert.MAPPER.to(query); + // 查询 + return hostService.getHostPage(queryRequest).map(HostProviderConvert.MAPPER::to); + } + + @Override + public HostDTO selectByAgentKey(String agentKey) { + return hostDAO.of() + .createWrapper() + .eq(HostDO::getAgentKey, agentKey) + .then() + .getOne(HostProviderConvert.MAPPER::to); + } + + @Override + public List selectByAgentKeys(List agentKeys) { + return hostDAO.of() + .createWrapper() + .in(HostDO::getAgentKey, agentKeys) + .then() + .list(HostProviderConvert.MAPPER::to); + } + } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostAgentController.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostAgentController.java new file mode 100644 index 00000000..e409bba3 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostAgentController.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.framework.biz.operator.log.core.annotation.OperatorLog; +import org.dromara.visor.framework.log.core.annotation.IgnoreLog; +import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; +import org.dromara.visor.framework.web.core.annotation.DemoDisableApi; +import org.dromara.visor.framework.web.core.annotation.RestWrapper; +import org.dromara.visor.module.asset.define.operator.HostOperatorType; +import org.dromara.visor.module.asset.entity.request.host.HostAgentInstallRequest; +import org.dromara.visor.module.asset.entity.request.host.HostAgentInstallStatusUpdateRequest; +import org.dromara.visor.module.asset.entity.vo.HostAgentLogVO; +import org.dromara.visor.module.asset.entity.vo.HostAgentStatusVO; +import org.dromara.visor.module.asset.service.HostAgentLogService; +import org.dromara.visor.module.asset.service.HostAgentService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 主机探针端点 api + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 14:33 + */ +@Tag(name = "asset - 主机探针") +@Slf4j +@Validated +@RestWrapper +@RestController +@RequestMapping("/asset/host-agent") +public class HostAgentController { + + @Resource + private HostAgentService hostAgentService; + + @Resource + private HostAgentLogService hostAgentLogService; + + @IgnoreLog(IgnoreLogMode.ALL) + @GetMapping("/status") + @Operation(summary = "查询探针状态") + @Parameter(name = "idList", description = "idList", required = true) + @PreAuthorize("@ss.hasPermission('asset:host:query')") + public List getAgentStatus(@RequestParam("idList") List idList) { + return hostAgentService.getAgentStatus(idList); + } + + @IgnoreLog(IgnoreLogMode.ALL) + @GetMapping("/install-status") + @Operation(summary = "查询探针安装状态") + @Parameter(name = "idList", description = "idList", required = true) + @PreAuthorize("@ss.hasPermission('asset:host:query')") + public List getAgentInstallLogStatus(@RequestParam("idList") List idList) { + return hostAgentLogService.getAgentInstallLogStatus(idList); + } + + @DemoDisableApi + @OperatorLog(HostOperatorType.INSTALL_AGENT) + @PostMapping("/install") + @Operation(summary = "安装主机探针") + @PreAuthorize("@ss.hasPermission('asset:host:install-agent')") + public Boolean installAgent(@Validated @RequestBody HostAgentInstallRequest request) { + hostAgentService.installAgent(request); + return true; + } + + @DemoDisableApi + @OperatorLog(HostOperatorType.UPDATE_AGENT_INSTALL_STATUS) + @PutMapping("/update-install-status") + @Operation(summary = "修改探针安装状态") + @PreAuthorize("@ss.hasPermission('asset:host:install-agent')") + public Boolean updateAgentInstallStatus(@Validated @RequestBody HostAgentInstallStatusUpdateRequest request) { + hostAgentLogService.updateStatus(request.getId(), request.getStatus(), request.getMessage()); + return true; + } + + @DemoDisableApi + @OperatorLog(HostOperatorType.UPLOAD_AGENT_RELEASE) + @PostMapping("/upload-agent-release") + @Operation(summary = "上传探针发布包") + @PreAuthorize("@ss.hasPermission('asset:host:install-agent')") + public String uploadAgentRelease(@RequestParam("file") MultipartFile file) { + // 上传 + hostAgentService.uploadAgentRelease(file); + // 获取最新版本 + return hostAgentService.getAgentVersion(); + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostAgentEndpointController.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostAgentEndpointController.java new file mode 100644 index 00000000..14beda8d --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostAgentEndpointController.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.controller; + +import com.alibaba.fastjson.JSONObject; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.CustomHeaderConst; +import org.dromara.visor.common.constant.ExtraFieldConst; +import org.dromara.visor.framework.log.core.annotation.IgnoreLog; +import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; +import org.dromara.visor.framework.web.core.annotation.ExposeApi; +import org.dromara.visor.framework.web.core.annotation.RestWrapper; +import org.dromara.visor.module.asset.entity.vo.HostOnlineAgentConfigVO; +import org.dromara.visor.module.asset.service.HostAgentEndpointService; +import org.dromara.visor.module.asset.service.HostExtraService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * 主机探针端点 api + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 14:33 + */ +@Tag(name = "asset - 主机探针端点") +@Slf4j +@Validated +@RestWrapper +@RestController +@RequestMapping("/host/agent-endpoint") +public class HostAgentEndpointController { + + @Resource + private HostExtraService hostExtraService; + + @Resource + private HostAgentEndpointService hostAgentEndpointService; + + @ExposeApi + @GetMapping("/set-online") + @Operation(summary = "设置探针已上线") + public HostOnlineAgentConfigVO setAgentOnline(@RequestHeader(CustomHeaderConst.AGENT_KEY_HEADER) String agentKey, + @RequestHeader(CustomHeaderConst.AGENT_VERSION_HEADER) String version) { + return hostAgentEndpointService.setAgentOnline(agentKey, version); + } + + @ExposeApi + @GetMapping("/set-offline") + @Operation(summary = "设置探针已下线") + public Boolean setAgentOffline(@RequestHeader(CustomHeaderConst.AGENT_KEY_HEADER) String agentKey) { + hostAgentEndpointService.setAgentOffline(agentKey); + return true; + } + + @ExposeApi + @IgnoreLog(IgnoreLogMode.RET) + @GetMapping("/heartbeat") + @Operation(summary = "设置探针心跳") + public Boolean setAgentHeartbeat(@RequestHeader(CustomHeaderConst.AGENT_KEY_HEADER) String key) { + hostAgentEndpointService.setAgentHeartbeat(key); + return true; + } + + @ExposeApi + @PostMapping("/sync-host-spec") + @Operation(summary = "同步主机规格") + public Boolean syncHostSpec(@RequestHeader(CustomHeaderConst.AGENT_KEY_HEADER) String key, + @RequestParam(ExtraFieldConst.TASK_ID) String taskId, + @RequestBody JSONObject spec) { + hostExtraService.syncHostSpec(key, taskId, spec); + return true; + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostController.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostController.java index ad09fc43..e8d13d33 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostController.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/controller/HostController.java @@ -118,8 +118,9 @@ public class HostController { @Operation(summary = "通过 id 查询主机") @Parameter(name = "id", description = "id", required = true) @PreAuthorize("@ss.hasPermission('asset:host:query')") - public HostVO getHost(@RequestParam("id") Long id) { - return hostService.getHostById(id); + public HostVO getHost(@RequestParam("id") Long id, + @RequestParam(value = "base", required = false) Boolean base) { + return hostService.getHostById(id, base); } @IgnoreLog(IgnoreLogMode.RET) diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostAgentLogConvert.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostAgentLogConvert.java new file mode 100644 index 00000000..ca0f4744 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostAgentLogConvert.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.convert; + +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; +import org.dromara.visor.module.asset.entity.vo.HostAgentLogVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 主机探针日志 对象转换器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023-9-11 14:16 + */ +@Mapper +public interface HostAgentLogConvert { + + HostAgentLogConvert MAPPER = Mappers.getMapper(HostAgentLogConvert.class); + + HostAgentLogVO to(HostAgentLogDO domain); + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostAgentLogProviderConvert.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostAgentLogProviderConvert.java new file mode 100644 index 00000000..e828371c --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostAgentLogProviderConvert.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.convert; + +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; +import org.dromara.visor.module.asset.entity.dto.host.HostAgentLogDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 主机探针日志 对外对象转换器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023-9-11 14:16 + */ +@Mapper +public interface HostAgentLogProviderConvert { + + HostAgentLogProviderConvert MAPPER = Mappers.getMapper(HostAgentLogProviderConvert.class); + + HostAgentLogDTO to(HostAgentLogDO domain); + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostConvert.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostConvert.java index 55fc70e1..1f4ff1ef 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostConvert.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostConvert.java @@ -28,6 +28,7 @@ import org.dromara.visor.module.asset.entity.dto.HostCacheDTO; import org.dromara.visor.module.asset.entity.request.host.HostCreateRequest; import org.dromara.visor.module.asset.entity.request.host.HostQueryRequest; import org.dromara.visor.module.asset.entity.request.host.HostUpdateRequest; +import org.dromara.visor.module.asset.entity.vo.HostAgentStatusVO; import org.dromara.visor.module.asset.entity.vo.HostBaseVO; import org.dromara.visor.module.asset.entity.vo.HostVO; import org.mapstruct.Mapper; @@ -61,6 +62,8 @@ public interface HostConvert { HostBaseVO toBase(HostDO domain); + HostAgentStatusVO toAgentStatus(HostDO domain); + HostCreateRequest toCreate(HostUpdateRequest request); List toList(List domain); diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostProviderConvert.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostProviderConvert.java index 13071c56..00f40637 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostProviderConvert.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/convert/HostProviderConvert.java @@ -26,6 +26,8 @@ import org.dromara.visor.common.mapstruct.StringConversion; import org.dromara.visor.module.asset.entity.domain.HostDO; import org.dromara.visor.module.asset.entity.dto.host.HostBaseDTO; import org.dromara.visor.module.asset.entity.dto.host.HostDTO; +import org.dromara.visor.module.asset.entity.dto.host.HostQueryDTO; +import org.dromara.visor.module.asset.entity.request.host.HostQueryRequest; import org.dromara.visor.module.asset.entity.vo.HostVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -42,6 +44,8 @@ public interface HostProviderConvert { HostProviderConvert MAPPER = Mappers.getMapper(HostProviderConvert.class); + HostQueryRequest to(HostQueryDTO dto); + HostDO to(HostDTO host); HostDTO to(HostDO domain); diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostAgentLogDAO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostAgentLogDAO.java new file mode 100644 index 00000000..4c8d4f84 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostAgentLogDAO.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.dromara.visor.framework.mybatis.core.mapper.IMapper; +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; + +/** + * 主机探针日志 Mapper 接口 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-28 09:55 + */ +@Mapper +public interface HostAgentLogDAO extends IMapper { + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostDAO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostDAO.java index 0a2e7916..80842317 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostDAO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostDAO.java @@ -24,8 +24,10 @@ package org.dromara.visor.module.asset.dao; import org.apache.ibatis.annotations.Mapper; import org.dromara.visor.framework.mybatis.core.mapper.IMapper; +import org.dromara.visor.framework.mybatis.core.query.Conditions; import org.dromara.visor.module.asset.entity.domain.HostDO; +import java.util.Date; import java.util.List; /** @@ -57,4 +59,47 @@ public interface HostDAO extends IMapper { .list(HostDO::getId); } + /** + * 通过 agentKey 查询 id + * + * @param agentKey agentKey + * @return id + */ + default Long selectIdByAgentKey(String agentKey) { + return this.of() + .createWrapper() + .select(HostDO::getId) + .eq(HostDO::getAgentKey, agentKey) + .then() + .getOne(HostDO::getId); + } + + /** + * 通过 agentKey 查询 id + * + * @param agentKeys agentKeys + * @return id + */ + default List selectIdByAgentKeys(List agentKeys) { + return this.of() + .createWrapper() + .select(HostDO::getId, HostDO::getAgentKey) + .in(HostDO::getAgentKey, agentKeys) + .then() + .list(); + } + + /** + * 更新探针信息 + * + * @param keys agentKeyList + * @param update update + * @return effect + */ + default int updateByAgentKeys(List keys, HostDO update) { + update.setUpdateTime(new Date()); + // 更新 + return this.update(update, Conditions.in(HostDO::getAgentKey, keys)); + } + } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostIdentityDAO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostIdentityDAO.java index 7c36b924..83088e1d 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostIdentityDAO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/dao/HostIdentityDAO.java @@ -48,6 +48,7 @@ public interface HostIdentityDAO extends IMapper { */ default int setKeyWithNull(List keyIdList) { LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate() + .setSql("type = IF(type = 'KEY', 'PASSWORD', type)") .set(HostIdentityDO::getKeyId, null) .in(HostIdentityDO::getKeyId, keyIdList); return this.update(null, updateWrapper); diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/AssetThreadPools.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/AssetThreadPools.java new file mode 100644 index 00000000..b38fe855 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/AssetThreadPools.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.define; + +import cn.orionsec.kit.lang.define.thread.ExecutorBuilder; +import cn.orionsec.kit.lang.utils.Systems; +import org.dromara.visor.common.constant.Const; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 执行线程池 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/1/3 11:21 + */ +public interface AssetThreadPools { + + /** + * 批量执行主机命令线程池 + */ + ThreadPoolExecutor AGENT_INSTALL = ExecutorBuilder.create() + .namedThreadFactory("agent-install-") + .corePoolSize(Systems.PROCESS_NUM) + .maxPoolSize(Systems.PROCESS_NUM) + .keepAliveTime(Const.MS_S_60) + .workQueue(new LinkedBlockingQueue<>()) + .allowCoreThreadTimeout(true) + .build(); + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/cache/HostCacheKeyDefine.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/cache/HostCacheKeyDefine.java index 9d412b53..b7f4b10f 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/cache/HostCacheKeyDefine.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/cache/HostCacheKeyDefine.java @@ -64,4 +64,12 @@ public interface HostCacheKeyDefine { .timeout(8, TimeUnit.HOURS) .build(); + CacheKeyDefine HOST_INSTALL_LOG = new CacheKeyBuilder() + .key("host:inst-log:{}") + .desc("最新的主机安装记录 ${hostId}") + .noPrefix() + .type(Long.class) + .struct(RedisCacheStruct.STRING) + .build(); + } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/operator/HostOperatorType.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/operator/HostOperatorType.java index f0e614ad..2b579eb7 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/operator/HostOperatorType.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/define/operator/HostOperatorType.java @@ -50,6 +50,12 @@ public class HostOperatorType extends InitializingOperatorTypes { public static final String UPDATE_SPEC = "host:update-spec"; + public static final String INSTALL_AGENT = "host:install-agent"; + + public static final String UPDATE_AGENT_INSTALL_STATUS = "host:update-install-status"; + + public static final String UPLOAD_AGENT_RELEASE = "host:upload-agent-release"; + @Override public OperatorType[] types() { return new OperatorType[]{ @@ -59,6 +65,9 @@ public class HostOperatorType extends InitializingOperatorTypes { new OperatorType(M, UPDATE_STATUS, "修改主机状态 ${name} - ${status}"), new OperatorType(M, UPDATE_CONFIG, "修改主机配置 ${name} - ${type}"), new OperatorType(M, UPDATE_SPEC, "修改主机规格信息 ${name}"), + new OperatorType(L, INSTALL_AGENT, "安装主机探针"), + new OperatorType(L, UPDATE_AGENT_INSTALL_STATUS, "修改探针安装状态为 ${status}"), + new OperatorType(H, UPLOAD_AGENT_RELEASE, "上传探针发布包 ${name} ${signShort}"), }; } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostAgentLogDO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostAgentLogDO.java new file mode 100644 index 00000000..7788ff23 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostAgentLogDO.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.dromara.visor.framework.mybatis.core.domain.BaseDO; + +/** + * 主机探针日志 实体对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-28 09:55 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName(value = "host_agent_log", autoResultMap = true) +@Schema(name = "HostAgentLogDO", description = "主机探针日志 实体对象") +public class HostAgentLogDO extends BaseDO { + + private static final long serialVersionUID = 1L; + + @Schema(description = "主机id") + @TableField("host_id") + private Long hostId; + + @Schema(description = "agentKey") + @TableField("agent_key") + private String agentKey; + + @Schema(description = "类型") + @TableField("type") + private String type; + + @Schema(description = "状态") + @TableField("status") + private String status; + + @Schema(description = "消息") + @TableField("message") + private String message; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostDO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostDO.java index c12a40c1..79119828 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostDO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/domain/HostDO.java @@ -32,6 +32,8 @@ import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import org.dromara.visor.framework.mybatis.core.domain.BaseDO; +import java.util.Date; + /** * 主机 实体对象 * @@ -78,6 +80,26 @@ public class HostDO extends BaseDO { @TableField("status") private String status; + @Schema(description = "agentKey") + @TableField("agent_key") + private String agentKey; + + @Schema(description = "探针版本") + @TableField("agent_version") + private String agentVersion; + + @Schema(description = "探针安装状态") + @TableField("agent_install_status") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + @TableField("agent_online_status") + private Integer agentOnlineStatus; + + @Schema(description = "探针切换在线状态时间") + @TableField("agent_online_change_time") + private Date agentOnlineChangeTime; + @Schema(description = "主机描述") @TableField("description") private String description; diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/HostCacheDTO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/HostCacheDTO.java index f82eda5c..2aafbe45 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/HostCacheDTO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/dto/HostCacheDTO.java @@ -66,12 +66,12 @@ public class HostCacheDTO implements LongCacheIdModel, Serializable { @Schema(description = "主机地址") private String address; - @Schema(description = "主机端口") - private Integer port; - @Schema(description = "主机状态") private String status; + @Schema(description = "agentKey") + private String agentKey; + @Schema(description = "主机描述") private String description; diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostAgentInstallRequest.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostAgentInstallRequest.java new file mode 100644 index 00000000..a6981f41 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostAgentInstallRequest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * 主机 安装探针请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023-9-11 14:16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostAgentInstallRequest", description = "主机 安装探针请求对象") +public class HostAgentInstallRequest { + + @NotEmpty + @Schema(description = "id") + private List idList; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostAgentInstallStatusUpdateRequest.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostAgentInstallStatusUpdateRequest.java new file mode 100644 index 00000000..5bf821c9 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostAgentInstallStatusUpdateRequest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +/** + * 主机安装探针更新状态请求 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023-9-11 14:16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostAgentInstallStatusUpdateRequest", description = "主机安装探针更新状态请求") +public class HostAgentInstallStatusUpdateRequest { + + @NotNull + @Schema(description = "id") + private Long id; + + @NotNull + @Schema(description = "状态") + private String status; + + @Size(max = 1000) + @Schema(description = "消息") + private String message; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostQueryRequest.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostQueryRequest.java index 0099ceaf..6bf632a6 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostQueryRequest.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/request/host/HostQueryRequest.java @@ -23,7 +23,8 @@ package org.dromara.visor.module.asset.entity.request.host; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.Data; +import lombok.EqualsAndHashCode; import org.dromara.visor.common.entity.BaseQueryRequest; import javax.validation.constraints.Size; @@ -37,9 +38,6 @@ import java.util.List; * @since 2023-9-11 14:16 */ @Data -@Builder -@NoArgsConstructor -@AllArgsConstructor @EqualsAndHashCode(callSuper = true) @Schema(name = "HostQueryRequest", description = "主机 查询请求对象") public class HostQueryRequest extends BaseQueryRequest { @@ -50,6 +48,9 @@ public class HostQueryRequest extends BaseQueryRequest { @Schema(description = "id") private Long id; + @Schema(description = "id") + private List idList; + @Size(max = 8) @Schema(description = "主机类型") private String type; @@ -78,13 +79,25 @@ public class HostQueryRequest extends BaseQueryRequest { @Schema(description = "主机状态") private String status; - @Schema(description = "tag") - private List tags; - @Size(max = 255) @Schema(description = "描述") private String description; + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + + @Schema(description = "通过探针排序") + private Boolean orderByAgent; + + @Schema(description = "tag") + private List tags; + @Schema(description = "是否查询分组信息") private Boolean queryGroup; diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostAgentLogVO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostAgentLogVO.java new file mode 100644 index 00000000..32b90bae --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostAgentLogVO.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * 主机探针日志 视图响应对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-28 09:55 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostAgentLogVO", description = "主机探针日志 视图响应对象") +public class HostAgentLogVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "主机id") + private Long hostId; + + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "类型") + private String type; + + @Schema(description = "状态") + private String status; + + @Schema(description = "消息") + private String message; + + @Schema(description = "创建时间") + private Date createTime; + + @Schema(description = "修改时间") + private Date updateTime; + + @Schema(description = "创建人") + private String creator; + + @Schema(description = "修改人") + private String updater; + + @Schema(description = "探针状态") + private HostAgentStatusVO agentStatus; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostAgentStatusVO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostAgentStatusVO.java new file mode 100644 index 00000000..d0d0ceee --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostAgentStatusVO.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 主机探针状态 视图响应对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-28 09:55 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostAgentStatusVO", description = "主机探针状态 视图响应对象") +public class HostAgentStatusVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "探针版本") + private String agentVersion; + + @Schema(description = "最新版本") + private String latestVersion; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostOnlineAgentConfigVO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostOnlineAgentConfigVO.java new file mode 100644 index 00000000..84d5852d --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostOnlineAgentConfigVO.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 主机密钥 视图响应对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023-9-20 11:55 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "HostOnlineAgentConfigVO", description = "主机上线探针配置 响应对象") +public class HostOnlineAgentConfigVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "是否已同步过规格") + private Boolean specSynced; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostVO.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostVO.java index fed4d555..623155ca 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostVO.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/entity/vo/HostVO.java @@ -72,12 +72,21 @@ public class HostVO implements Serializable { @Schema(description = "主机地址") private String address; - @Schema(description = "主机端口") - private Integer port; - @Schema(description = "主机状态") private String status; + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "探针版本") + private String agentVersion; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + @Schema(description = "描述") private String description; diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/enums/AgentLogStatusEnum.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/enums/AgentLogStatusEnum.java new file mode 100644 index 00000000..629ba2d9 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/enums/AgentLogStatusEnum.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.enums; + +/** + * 探针日志状态 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/28 10:50 + */ +public enum AgentLogStatusEnum { + + /** + * 等待中 + */ + WAIT, + + /** + * 安装中 + */ + RUNNING, + + /** + * 成功 + */ + SUCCESS, + + /** + * 失败 + */ + FAILED, + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/enums/AgentLogTypeEnum.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/enums/AgentLogTypeEnum.java new file mode 100644 index 00000000..4a695033 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/enums/AgentLogTypeEnum.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.enums; + +/** + * 探针日志类型 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/28 10:50 + */ +public enum AgentLogTypeEnum { + + /** + * 下线 + */ + OFFLINE, + + /** + * 上线 + */ + ONLINE, + + /** + * 安装 + */ + INSTALL, + + /** + * 启动 + */ + START, + + /** + * 停止 + */ + STOP, + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/AbstractAgentInstaller.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/AbstractAgentInstaller.java new file mode 100644 index 00000000..38c8a3db --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/AbstractAgentInstaller.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.handler.agent.intstall; + +import cn.orionsec.kit.lang.utils.Strings; +import cn.orionsec.kit.lang.utils.Valid; +import cn.orionsec.kit.lang.utils.io.FileReaders; +import cn.orionsec.kit.lang.utils.io.Streams; +import cn.orionsec.kit.net.host.SessionStore; +import cn.orionsec.kit.net.host.sftp.SftpExecutor; +import cn.orionsec.kit.net.host.ssh.command.CommandExecutor; +import cn.orionsec.kit.spring.SpringHolder; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; +import org.dromara.visor.common.constant.FileConst; +import org.dromara.visor.common.session.config.SshConnectConfig; +import org.dromara.visor.common.session.ssh.SessionStores; +import org.dromara.visor.common.utils.PathUtils; +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; +import org.dromara.visor.module.asset.enums.AgentLogStatusEnum; +import org.dromara.visor.module.asset.enums.HostOsTypeEnum; +import org.dromara.visor.module.asset.handler.agent.model.AgentInstallParams; +import org.dromara.visor.module.asset.service.HostAgentLogService; +import org.dromara.visor.module.asset.service.HostConnectService; + +import java.io.IOException; + +/** + * 探针安装器 基类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/29 11:12 + */ +@Slf4j +public abstract class AbstractAgentInstaller implements AgentInstaller { + + private static final String REPLACEMENT = "$$"; + + private static final HostAgentLogService hostAgentLogService = SpringHolder.getBean(HostAgentLogService.class); + + private static final HostConnectService hostConnectService = SpringHolder.getBean(HostConnectService.class); + + protected final Long logId; + + protected final AgentInstallParams params; + + protected final String startScriptName; + + protected final String uploadAgentName; + + protected String agentHomePath; + + protected HostAgentLogDO record; + + protected SshConnectConfig sshConfig; + + protected SessionStore sessionStore; + + protected CommandExecutor commandExecutor; + + protected SftpExecutor sftpExecutor; + + public AbstractAgentInstaller(AgentInstallParams params) { + this.params = params; + this.logId = params.getLogId(); + this.startScriptName = Const.START + HostOsTypeEnum.of(params.getOsType()).getScriptSuffix(); + this.uploadAgentName = FileConst.INSTANCE_AGENT_NAME + HostOsTypeEnum.of(params.getOsType()).getBinarySuffix(); + } + + @Override + public void run() { + log.info("AgentInstaller install start {}", logId); + // 查询记录 + this.record = hostAgentLogService.selectById(logId); + Valid.notNull(record, "AgentInstaller record is null {}", logId); + Valid.eq(record.getStatus(), AgentLogStatusEnum.WAIT.name(), "AgentInstaller record status is not WAIT {}", logId); + try { + // 更新状态 + this.updateStatus(AgentLogStatusEnum.RUNNING, null); + // 打开会话 + this.initSession(); + log.info("AgentInstaller install session init {}", logId); + // 上传文件 + this.uploadFile(); + log.info("AgentInstaller install upload finish {}", logId); + // 启动探针 + this.startAgent(); + log.info("AgentInstaller install stated {}", logId); + // 更新状态 + this.updateStatus(AgentLogStatusEnum.SUCCESS, null); + } catch (Exception e) { + // 更新状态 + log.error("AgentInstaller install error {}", logId, e); + this.updateStatus(AgentLogStatusEnum.FAILED, ErrorMessage.getErrorMessage(e, 1000)); + } finally { + this.close(); + } + } + + /** + * 初始化会话 + */ + private void initSession() { + // 获取 ssh 配置 + this.sshConfig = hostConnectService.getSshConnectConfig(params.getHostId()); + // 设置探针家目录 + this.agentHomePath = this.getAgentHomePath(); + // 打开会话 + this.sessionStore = SessionStores.openSessionStore(sshConfig); + // 打开 sftp + this.sftpExecutor = sessionStore.getSftpExecutor(sshConfig.getFileNameCharset()); + sftpExecutor.connect(); + } + + /** + * 上传文件 + * + * @throws IOException IOException + */ + protected abstract void uploadFile() throws IOException; + + /** + * 启动 agent + */ + protected abstract void startAgent() throws IOException; + + /** + * 获取探针家目录 + * + * @return path + */ + protected String getAgentHomePath() { + return PathUtils.buildAppPath(HostOsTypeEnum.WINDOWS.name().equals(params.getOsType()), + sshConfig.getUsername(), + FileConst.INSTANCE_AGENT_PATH) + Const.SLASH; + } + + /** + * 替换文件内容 + * + * @param path path + * @return content + */ + protected String replaceContent(String path) { + // 读取文件 + byte[] contentBytes = FileReaders.readAllBytesFast(path); + // 格式化文件 + return Strings.format(new String(contentBytes), REPLACEMENT, params.getReplaceVars()); + } + + /** + * 更新状态 + * + * @param status 状态 + * @param message 消息 + */ + protected void updateStatus(AgentLogStatusEnum status, String message) { + log.info("AgentInstaller update status {}, {}", logId, status); + hostAgentLogService.updateStatus(logId, status.name(), message); + } + + @Override + public void close() { + Streams.close(sftpExecutor); + Streams.close(commandExecutor); + Streams.close(sessionStore); + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/AgentInstaller.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/AgentInstaller.java new file mode 100644 index 00000000..0011da0e --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/AgentInstaller.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.handler.agent.intstall; + +import cn.orionsec.kit.lang.able.SafeCloseable; +import org.dromara.visor.module.asset.define.AssetThreadPools; +import org.dromara.visor.module.asset.enums.HostOsTypeEnum; +import org.dromara.visor.module.asset.handler.agent.model.AgentInstallParams; + +/** + * 探针安装器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/29 10:28 + */ +public interface AgentInstaller extends Runnable, SafeCloseable { + + /** + * 启动安装 + * + * @param params params + */ + static void start(AgentInstallParams params) { + AgentInstaller installer; + if (HostOsTypeEnum.WINDOWS.name().equals(params.getOsType())) { + // windows 安装 + installer = new WindowsAgentInstaller(params); + } else { + // 其他安装 + installer = new LinuxAgentInstaller(params); + } + AssetThreadPools.AGENT_INSTALL.execute(installer); + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/LinuxAgentInstaller.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/LinuxAgentInstaller.java new file mode 100644 index 00000000..856a29bf --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/LinuxAgentInstaller.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.handler.agent.intstall; + +import cn.orionsec.kit.lang.utils.Exceptions; +import cn.orionsec.kit.net.host.ssh.command.CommandExecutors; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.FileConst; +import org.dromara.visor.module.asset.handler.agent.model.AgentInstallParams; + +import java.io.IOException; + +/** + * linux 探针安装器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/29 11:12 + */ +@Slf4j +public class LinuxAgentInstaller extends AbstractAgentInstaller { + + public LinuxAgentInstaller(AgentInstallParams params) { + super(params); + } + + @Override + protected void uploadFile() throws IOException { + // 写入配置文件 + sftpExecutor.write(agentHomePath + FileConst.CONFIG_YAML, this.replaceContent(params.getConfigFilePath())); + log.info("写入配置文件成功"); + // 写入启动脚本 + sftpExecutor.write(agentHomePath + startScriptName, this.replaceContent(params.getStartScriptPath())); + log.info("写入启动脚本成功"); + // 上传探针文件 + sftpExecutor.uploadFile(agentHomePath + uploadAgentName, params.getAgentFilePath()); + log.info("上传探针文件成功"); + // 脚本提权 + sftpExecutor.changeMode(agentHomePath + startScriptName, 777); + log.info("脚本提权成功"); + // 探针提权 + sftpExecutor.changeMode(agentHomePath + uploadAgentName, 777); + log.info("探针提权成功"); + } + + @Override + protected void startAgent() throws IOException { + String command = "cd " + agentHomePath + " && sh " + startScriptName; + log.info("LinuxAgentInstaller command: {}", command); + this.commandExecutor = sessionStore.getCommandExecutor(command); + this.commandExecutor.pty(false); + byte[] result = CommandExecutors.getCommandOutputResult(this.commandExecutor); + // 如果不是成功启动则抛异常 + if (!commandExecutor.isSuccessExit()) { + throw Exceptions.app("exit: " + commandExecutor.getExitCode() + ". " + new String(result)); + } + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/WindowsAgentInstaller.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/WindowsAgentInstaller.java new file mode 100644 index 00000000..a9fab0db --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/intstall/WindowsAgentInstaller.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.handler.agent.intstall; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.FileConst; +import org.dromara.visor.module.asset.handler.agent.model.AgentInstallParams; + +import java.io.IOException; + +/** + * windows 探针安装器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/29 11:12 + */ +@Slf4j +public class WindowsAgentInstaller extends AbstractAgentInstaller { + + public WindowsAgentInstaller(AgentInstallParams params) { + super(params); + } + + @Override + protected void uploadFile() throws IOException { + // 写入配置文件 + sftpExecutor.write(Const.SLASH + agentHomePath + FileConst.CONFIG_YAML, this.replaceContent(params.getConfigFilePath())); + log.info("写入配置文件成功"); + // 写入启动脚本 + sftpExecutor.write(Const.SLASH + agentHomePath + startScriptName, this.replaceContent(params.getStartScriptPath())); + log.info("写入启动脚本成功"); + // 上传探针文件 + sftpExecutor.uploadFile(Const.SLASH + agentHomePath + uploadAgentName, params.getAgentFilePath()); + log.info("上传探针文件成功"); + } + + @Override + protected void startAgent() { + // TODO + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/model/AgentInstallParams.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/model/AgentInstallParams.java new file mode 100644 index 00000000..ff06fd29 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/agent/model/AgentInstallParams.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.handler.agent.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * 探针安装参数 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/28 18:01 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AgentInstallParams { + + /** + * logId + */ + private Long logId; + + /** + * hostId + */ + private Long hostId; + + /** + * 系统类型 + */ + private String osType; + + /** + * agentKey + */ + private String agentKey; + + /** + * 配置文件路径 + */ + private String configFilePath; + + /** + * 探针文件路径 + */ + private String agentFilePath; + + /** + * 启动脚本路径 + */ + private String startScriptPath; + + /** + * 替换变量 + */ + private Map replaceVars; + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/model/HostSpecExtraModel.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/model/HostSpecExtraModel.java index e0eafb63..42982e9a 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/model/HostSpecExtraModel.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/model/HostSpecExtraModel.java @@ -41,6 +41,11 @@ import java.util.List; @AllArgsConstructor public class HostSpecExtraModel implements GenericsDataModel { + /** + * 是否已同步 + */ + private Boolean synced; + /** * sn */ @@ -51,10 +56,20 @@ public class HostSpecExtraModel implements GenericsDataModel { */ private String osName; + /** + * cpu 数量 + */ + private String cpuCount; + /** * cpu 核心数 */ - private Integer cpuCore; + private Integer cpuPhysicalCore; + + /** + * cpu 线程数 + */ + private Integer cpuLogicalCore; /** * cpu 频率 @@ -72,7 +87,7 @@ public class HostSpecExtraModel implements GenericsDataModel { private Double memorySize; /** - * 硬盘大小 + * 磁盘大小 */ private Double diskSize; @@ -89,17 +104,17 @@ public class HostSpecExtraModel implements GenericsDataModel { /** * 公网 ip 列表 */ - private List publicIpAddress; + private List publicIpAddresses; /** * 内网 ip 列表 */ - private List privateIpAddress; + private List privateIpAddresses; /** * 负责人 */ - private String chargePerson; + private String ownerPerson; /** * 创建时间 @@ -131,6 +146,11 @@ public class HostSpecExtraModel implements GenericsDataModel { */ private String label; + /** + * 键 + */ + private String key; + /** * 值 */ diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/strategy/HostSpecExtraStrategy.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/strategy/HostSpecExtraStrategy.java index 5d4019c4..1b790973 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/strategy/HostSpecExtraStrategy.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/handler/host/extra/strategy/HostSpecExtraStrategy.java @@ -45,4 +45,9 @@ public class HostSpecExtraStrategy extends AbstractGenericsDataStrategy getAgentInstallLogStatus(List idList); + + /** + * 更新日志状态 + * + * @param id id + * @param status status + * @param message message + */ + void updateStatus(Long id, String status, String message); + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostAgentService.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostAgentService.java new file mode 100644 index 00000000..72a7d9d4 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostAgentService.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.service; + +import org.dromara.visor.module.asset.entity.request.host.HostAgentInstallRequest; +import org.dromara.visor.module.asset.entity.vo.HostAgentStatusVO; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * 主机探针 服务类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/27 16:06 + */ +public interface HostAgentService { + + /** + * 获取探针状态 + * + * @param idList idList + * @return rows + */ + List getAgentStatus(List idList); + + /** + * 安装探针 + * + * @param request request + */ + void installAgent(HostAgentInstallRequest request); + + /** + * 上传探针发布包 + * + * @param file file + */ + void uploadAgentRelease(MultipartFile file); + + /** + * 获取探针版本 + * + * @return version + */ + String getAgentVersion(); + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostExtraService.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostExtraService.java index 6d9a2ae5..5a167bf3 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostExtraService.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostExtraService.java @@ -22,6 +22,7 @@ */ package org.dromara.visor.module.asset.service; +import com.alibaba.fastjson.JSONObject; import org.dromara.visor.common.handler.data.model.GenericsDataModel; import org.dromara.visor.module.asset.entity.request.host.HostExtraUpdateRequest; import org.dromara.visor.module.asset.handler.host.extra.HostExtraItemEnum; @@ -83,4 +84,13 @@ public interface HostExtraService { */ void copyHostExtra(Long originId, Long newId); + /** + * 同步主机规格 + * + * @param key key + * @param taskId taskId + * @param spec spec + */ + void syncHostSpec(String key, String taskId, JSONObject spec); + } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostService.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostService.java index f9f33e10..13767252 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostService.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/HostService.java @@ -83,10 +83,11 @@ public interface HostService { /** * 通过 id 查询主机 * - * @param id id + * @param id id + * @param base base * @return row */ - HostVO getHostById(Long id); + HostVO getHostById(Long id, Boolean base); /** * 查询主机 diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentEndpointServiceImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentEndpointServiceImpl.java new file mode 100644 index 00000000..a3cb9f1f --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentEndpointServiceImpl.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.service.impl; + +import cn.orionsec.kit.lang.utils.Booleans; +import cn.orionsec.kit.lang.utils.Valid; +import cn.orionsec.kit.lang.utils.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; +import org.dromara.visor.module.asset.dao.HostAgentLogDAO; +import org.dromara.visor.module.asset.dao.HostDAO; +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; +import org.dromara.visor.module.asset.entity.domain.HostDO; +import org.dromara.visor.module.asset.entity.vo.HostOnlineAgentConfigVO; +import org.dromara.visor.module.asset.enums.AgentInstallStatusEnum; +import org.dromara.visor.module.asset.enums.AgentLogStatusEnum; +import org.dromara.visor.module.asset.enums.AgentLogTypeEnum; +import org.dromara.visor.module.asset.enums.AgentOnlineStatusEnum; +import org.dromara.visor.module.asset.handler.host.extra.HostExtraItemEnum; +import org.dromara.visor.module.asset.handler.host.extra.model.HostSpecExtraModel; +import org.dromara.visor.module.asset.service.HostAgentEndpointService; +import org.dromara.visor.module.asset.service.HostExtraService; +import org.dromara.visor.module.monitor.api.MonitorHostApi; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 监控探针端点 服务实现类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/27 16:07 + */ +@Slf4j +@Service +public class HostAgentEndpointServiceImpl implements HostAgentEndpointService { + + /** + * 标记离线阈值 + * 上报间隔(60s) * 2 + 5s + */ + private static final int MARK_OFFLINE_THRESHOLD = (60 * 2 + 5) * 1000; + + private static final ConcurrentHashMap ONLINE_STATUS_CACHE = new ConcurrentHashMap<>(); + + private static final ConcurrentHashMap HEARTBEAT_RECV_CACHE = new ConcurrentHashMap<>(); + + @Resource + private HostDAO hostDAO; + + @Resource + private HostAgentLogDAO hostAgentLogDAO; + + @Resource + private HostExtraService hostExtraService; + + @Resource + private MonitorHostApi monitorHostApi; + + /** + * 初始化主机在线状态 + */ + @PostConstruct + public void initHostOnlineStatus() { + List hosts = hostDAO.selectList(null); + for (HostDO host : hosts) { + Integer agentOnlineStatus = host.getAgentOnlineStatus(); + if (agentOnlineStatus != null) { + ONLINE_STATUS_CACHE.put(host.getAgentKey(), agentOnlineStatus); + } + } + } + + @Override + public HostOnlineAgentConfigVO setAgentOnline(String agentKey, String version) { + log.info("HostAgentEndpointService setAgentOnline agentKey: {}. version: {}", agentKey, version); + try { + // 查询主机信息 + Long hostId = hostDAO.selectIdByAgentKey(agentKey); + Valid.notNull(hostId, ErrorMessage.HOST_ABSENT); + // 查询主机规格信息 + HostSpecExtraModel spec = hostExtraService.getHostExtra(Const.SYSTEM_USER_ID, hostId, HostExtraItemEnum.SPEC); + Boolean synced = Optional.ofNullable(spec) + .map(HostSpecExtraModel::getSynced) + .map(Booleans::isTrue) + .orElse(false); + // 提前修正缓存 + ONLINE_STATUS_CACHE.put(agentKey, AgentOnlineStatusEnum.ONLINE.getValue()); + // 设置心跳 + this.setAgentHeartbeat(agentKey); + // 修改状态 + HostDO update = HostDO.builder() + .agentVersion(version) + .agentOnlineStatus(AgentOnlineStatusEnum.ONLINE.getValue()) + .agentOnlineChangeTime(new Date()) + .agentInstallStatus(AgentInstallStatusEnum.INSTALLED.getStatus()) + .build(); + hostDAO.updateByAgentKeys(Lists.singleton(agentKey), update); + // 插入日志 + HostAgentLogDO agentLog = HostAgentLogDO.builder() + .hostId(hostId) + .agentKey(agentKey) + .type(AgentLogTypeEnum.ONLINE.name()) + .status(AgentLogStatusEnum.SUCCESS.name()) + .build(); + hostAgentLogDAO.insert(agentLog); + // 返回 + return HostOnlineAgentConfigVO.builder() + .specSynced(synced) + .build(); + } catch (Exception e) { + // 由心跳修正 + ONLINE_STATUS_CACHE.put(agentKey, AgentOnlineStatusEnum.OFFLINE.getValue()); + throw e; + } + } + + @Override + public void setAgentOffline(String agentKey) { + log.info("HostAgentEndpointService setAgentOffline agentKey: {}", agentKey); + // 查询主机信息 + Long hostId = hostDAO.selectIdByAgentKey(agentKey); + Valid.notNull(hostId, ErrorMessage.HOST_ABSENT); + // 修改缓存 + ONLINE_STATUS_CACHE.put(agentKey, AgentOnlineStatusEnum.OFFLINE.getValue()); + HEARTBEAT_RECV_CACHE.put(agentKey, 0L); + // 修改状态 + HostDO update = HostDO.builder() + .agentOnlineStatus(AgentOnlineStatusEnum.OFFLINE.getValue()) + .agentOnlineChangeTime(new Date()) + .build(); + hostDAO.updateByAgentKeys(Lists.singleton(agentKey), update); + // 插入日志 + HostAgentLogDO agentLog = HostAgentLogDO.builder() + .hostId(hostId) + .agentKey(agentKey) + .type(AgentLogTypeEnum.OFFLINE.name()) + .status(AgentLogStatusEnum.SUCCESS.name()) + .build(); + hostAgentLogDAO.insert(agentLog); + // 设置监控上下文为已下线 + monitorHostApi.setAgentOffline(Lists.singleton(agentKey)); + } + + @Override + public void setAgentHeartbeat(String agentKey) { + // 设置心跳时间 + HEARTBEAT_RECV_CACHE.put(agentKey, System.currentTimeMillis()); + } + + @Override + public void checkHeartbeat() { + long now = System.currentTimeMillis(); + List markOnlineList = new ArrayList<>(); + List markOfflineList = new ArrayList<>(); + // 状态检查 + ONLINE_STATUS_CACHE.forEach((key, status) -> { + // 上次心跳时间 + Long lastHeartbeatTime = HEARTBEAT_RECV_CACHE.getOrDefault(key, 0L); + // 超过阈值标记离线 + if (now - lastHeartbeatTime > MARK_OFFLINE_THRESHOLD) { + // 如果当前状态是在线则标记离线 + if (AgentOnlineStatusEnum.ONLINE.getValue().equals(status)) { + markOfflineList.add(key); + } + } else { + // 如果当前状态是离线则标记在线 + if (AgentOnlineStatusEnum.OFFLINE.getValue().equals(status)) { + markOnlineList.add(key); + } + } + }); + // 更新在线状态 + if (!markOnlineList.isEmpty()) { + this.markOnlineStatus(markOnlineList, AgentOnlineStatusEnum.ONLINE); + } + // 更新离线状态 + if (!markOfflineList.isEmpty()) { + this.markOnlineStatus(markOfflineList, AgentOnlineStatusEnum.OFFLINE); + } + } + + /** + * 标记在线状态 + * + * @param agentKeyList agentKeyList + * @param status status + */ + private void markOnlineStatus(List agentKeyList, AgentOnlineStatusEnum status) { + if (Lists.isEmpty(agentKeyList)) { + return; + } + log.info("HostAgentEndpointService mark {}. count: {}, keys: {}", status, agentKeyList.size(), agentKeyList); + // 更新数据 + HostDO update = HostDO.builder() + .agentOnlineStatus(status.getValue()) + .agentOnlineChangeTime(new Date()) + .build(); + int effect = hostDAO.updateByAgentKeys(agentKeyList, update); + // 更新缓存 + agentKeyList.forEach(s -> ONLINE_STATUS_CACHE.put(s, status.getValue())); + log.info("HostAgentEndpointService mark {}. effect: {}", status, effect); + // 插入日志 + List logList = hostDAO.selectIdByAgentKeys(agentKeyList) + .stream() + .map(s -> { + HostAgentLogDO agentLog = HostAgentLogDO.builder() + .hostId(s.getId()) + .agentKey(s.getAgentKey()) + .status(AgentLogStatusEnum.SUCCESS.name()) + .build(); + if (AgentOnlineStatusEnum.ONLINE.equals(status)) { + agentLog.setType(AgentLogTypeEnum.ONLINE.name()); + } else { + agentLog.setType(AgentLogTypeEnum.OFFLINE.name()); + } + return agentLog; + }).collect(Collectors.toList()); + if (!logList.isEmpty()) { + hostAgentLogDAO.insertBatch(logList); + } + // 设置监控上下文为已下线 + if (AgentOnlineStatusEnum.OFFLINE.equals(status)) { + monitorHostApi.setAgentOffline(agentKeyList); + } + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentLogServiceImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentLogServiceImpl.java new file mode 100644 index 00000000..e75ece0a --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentLogServiceImpl.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.service.impl; + +import cn.orionsec.kit.lang.function.Functions; +import cn.orionsec.kit.lang.utils.collect.Lists; +import org.dromara.visor.module.asset.convert.HostAgentLogConvert; +import org.dromara.visor.module.asset.dao.HostAgentLogDAO; +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; +import org.dromara.visor.module.asset.entity.vo.HostAgentLogVO; +import org.dromara.visor.module.asset.entity.vo.HostAgentStatusVO; +import org.dromara.visor.module.asset.enums.AgentLogStatusEnum; +import org.dromara.visor.module.asset.service.HostAgentLogService; +import org.dromara.visor.module.asset.service.HostAgentService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 主机探针日志 服务实现类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/9/2 16:31 + */ +@Service +public class HostAgentLogServiceImpl implements HostAgentLogService { + + @Resource + private HostAgentLogDAO hostAgentLogDAO; + + @Resource + private HostAgentService hostAgentService; + + @Override + public HostAgentLogDO selectById(Long id) { + return hostAgentLogDAO.selectById(id); + } + + @Override + public List getAgentInstallLogStatus(List idList) { + if (Lists.isEmpty(idList)) { + return Lists.empty(); + } + // 查询日志 + List records = hostAgentLogDAO.selectBatchIds(idList) + .stream() + .map(HostAgentLogConvert.MAPPER::to) + .collect(Collectors.toList()); + // 如果是已完成需要查询 + List successRecords = records.stream() + .filter(s -> AgentLogStatusEnum.SUCCESS.name().equals(s.getStatus())) + .collect(Collectors.toList()); + if (!successRecords.isEmpty()) { + // 完成后查询主机信息 + List hostIdList = successRecords.stream() + .map(HostAgentLogVO::getHostId) + .distinct() + .collect(Collectors.toList()); + // 查询状态信息 + Map agentStatusMap = hostAgentService.getAgentStatus(hostIdList) + .stream() + .collect(Collectors.toMap(HostAgentStatusVO::getId, + Function.identity(), + Functions.right())); + // 设置状态信息 + for (HostAgentLogVO successRecord : successRecords) { + successRecord.setAgentStatus(agentStatusMap.get(successRecord.getHostId())); + } + } + return records; + } + + @Override + public void updateStatus(Long id, String status, String message) { + HostAgentLogDO update = HostAgentLogDO.builder() + .id(id) + .status(status) + .message(message) + .build(); + hostAgentLogDAO.updateById(update); + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentServiceImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentServiceImpl.java new file mode 100644 index 00000000..5b45b621 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostAgentServiceImpl.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.service.impl; + +import cn.orionsec.kit.lang.utils.Exceptions; +import cn.orionsec.kit.lang.utils.Strings; +import cn.orionsec.kit.lang.utils.collect.Lists; +import cn.orionsec.kit.lang.utils.collect.Maps; +import cn.orionsec.kit.lang.utils.crypto.enums.HashDigest; +import cn.orionsec.kit.lang.utils.io.FileReaders; +import cn.orionsec.kit.lang.utils.io.Files1; +import cn.orionsec.kit.lang.utils.io.compress.CompressTypeEnum; +import cn.orionsec.kit.lang.utils.io.compress.FileDecompressor; +import cn.orionsec.kit.lang.utils.net.IPs; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; +import org.dromara.visor.common.constant.ExtraFieldConst; +import org.dromara.visor.common.constant.FileConst; +import org.dromara.visor.common.utils.PathUtils; +import org.dromara.visor.common.utils.Valid; +import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; +import org.dromara.visor.framework.redis.core.utils.RedisStrings; +import org.dromara.visor.module.asset.convert.HostConvert; +import org.dromara.visor.module.asset.dao.HostAgentLogDAO; +import org.dromara.visor.module.asset.dao.HostDAO; +import org.dromara.visor.module.asset.define.cache.HostCacheKeyDefine; +import org.dromara.visor.module.asset.entity.domain.HostAgentLogDO; +import org.dromara.visor.module.asset.entity.domain.HostDO; +import org.dromara.visor.module.asset.entity.request.host.HostAgentInstallRequest; +import org.dromara.visor.module.asset.entity.vo.HostAgentStatusVO; +import org.dromara.visor.module.asset.enums.*; +import org.dromara.visor.module.asset.handler.agent.intstall.AgentInstaller; +import org.dromara.visor.module.asset.handler.agent.model.AgentInstallParams; +import org.dromara.visor.module.asset.service.HostAgentService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 主机探针 服务实现类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/28 10:10 + */ +@Slf4j +@Service +public class HostAgentServiceImpl implements HostAgentService { + + private String localVersion; + + @Value("${orion.api.expose.token}") + private String exposeToken; + + @Resource + private HostDAO hostDAO; + + @Resource + private HostAgentLogDAO hostAgentLogDAO; + + /** + * 读取本地探针版本 + */ + @PostConstruct + public void readLocalAgentVersion() { + log.info("HostAgentService-readLocalAgentVersion start"); + // 文件路径 + String path = PathUtils.getOrionPath(FileConst.INSTANCE_AGENT_RELEASE + Const.SLASH + FileConst.VERSION); + log.info("HostAgentService-readLocalAgentVersion path: {}", path); + try { + if (!Files1.isFile(path)) { + log.error("HostAgentService-readLocalAgentVersion not file"); + return; + } + // 读取文件内容 + byte[] bytes = FileReaders.readAllBytesFast(path); + this.localVersion = new String(bytes).trim(); + log.info("HostAgentService-readLocalAgentVersion version: {}", localVersion); + } catch (Exception e) { + log.error("HostAgentService-readLocalAgentVersion error", e); + } + } + + @Override + public List getAgentStatus(List idList) { + if (Lists.isEmpty(idList)) { + return Lists.empty(); + } + return hostDAO.of() + .createWrapper() + .select(HostDO::getId, + HostDO::getAgentVersion, + HostDO::getAgentInstallStatus, + HostDO::getAgentOnlineStatus) + .in(HostDO::getId, idList) + .then() + .stream() + .map(HostConvert.MAPPER::toAgentStatus) + .peek(s -> s.setLatestVersion(localVersion)) + .collect(Collectors.toList()); + } + + @Override + public void installAgent(HostAgentInstallRequest request) { + // 查询主机信息 + List idList = request.getIdList(); + List hosts = hostDAO.selectBatchIds(idList); + Valid.eq(hosts.size(), idList.size(), ErrorMessage.HOST_ABSENT); + + // 检查并创建安装任务参数 + List installTaskParams = this.createInstallTaskParams(hosts); + + // 查询当前状态 + boolean hasRunning = hostAgentLogDAO.of() + .createWrapper() + .in(HostAgentLogDO::getHostId, idList) + .eq(HostAgentLogDO::getType, AgentLogTypeEnum.INSTALL.name()) + .in(HostAgentLogDO::getStatus, AgentLogStatusEnum.WAIT.name(), AgentLogStatusEnum.RUNNING.name()) + .then() + .present(); + Valid.isFalse(hasRunning, ErrorMessage.ILLEGAL_STATUS); + + // 创建日志记录 + List agentLogs = hosts.stream() + .map(s -> HostAgentLogDO.builder() + .hostId(s.getId()) + .agentKey(s.getAgentKey()) + .type(AgentLogTypeEnum.INSTALL.name()) + .status(AgentLogStatusEnum.WAIT.name()) + .build()) + .collect(Collectors.toList()); + hostAgentLogDAO.insertBatch(agentLogs); + + // 设置缓存 + for (HostAgentLogDO agentLog : agentLogs) { + String key = HostCacheKeyDefine.HOST_INSTALL_LOG.format(agentLog.getHostId()); + RedisStrings.set(key, HostCacheKeyDefine.HOST_INSTALL_LOG, agentLog.getId()); + } + + // 获取替换变量 + Map replaceVars = this.getReplaceVars(); + + // 提交任务 + for (int i = 0; i < installTaskParams.size(); i++) { + AgentInstallParams params = installTaskParams.get(i); + HostAgentLogDO agentLog = agentLogs.get(i); + params.setLogId(agentLog.getId()); + params.setReplaceVars(this.getHostReplaceVars(replaceVars, params)); + // 执行任务 + AgentInstaller.start(params); + } + } + + @Override + public void uploadAgentRelease(MultipartFile file) { + // 检查文件名 + String fileName = Optional.of(file) + .map(MultipartFile::getOriginalFilename) + .map(String::toLowerCase) + .orElse(Const.EMPTY); + Valid.notBlank(fileName, ErrorMessage.FILE_EXTENSION_TYPE); + Valid.isTrue(fileName.endsWith(Const.SUFFIX_TAR_GZ), ErrorMessage.FILE_EXTENSION_TYPE); + // 保存文件 + String releaseDir = PathUtils.getOrionPath(FileConst.INSTANCE_AGENT_RELEASE); + String releaseTempDir = PathUtils.getOrionPath(FileConst.INSTANCE_AGENT_RELEASE_TEMP); + File releaseTempFile = new File(releaseTempDir + Const.SLASH + FileConst.INSTANCE_AGENT_RELEASE_TAR_GZ); + log.info("HostAgentService.installAgent start releaseTempDir: {}, releaseTempFile: {}", releaseTempDir, releaseTempFile.getAbsolutePath()); + try { + // 创建目录 + Files1.mkdirs(releaseTempFile.getParentFile()); + // 传输文件 + file.transferTo(releaseTempFile); + } catch (IOException e) { + throw Exceptions.app(ErrorMessage.FILE_UPLOAD_ERROR, e); + } + // 计算签名 + try { + String sign = Files1.sign(releaseTempFile, HashDigest.SHA256); + OperatorLogs.add(ExtraFieldConst.SIGN, sign); + OperatorLogs.add(ExtraFieldConst.SIGN_SHORT, sign.substring(0, 8)); + log.error("HostAgentService.installAgent calc sha256 sign: {}", sign); + } catch (Exception e) { + log.error("HostAgentService.installAgent calc sha256 error", e); + throw Exceptions.app(ErrorMessage.CALC_SIGN_FAILED, e); + } + // 解压缩文件 + try { + FileDecompressor decompressor = CompressTypeEnum.TAR_GZ.decompressor().get(); + decompressor.setDecompressFile(releaseTempFile); + decompressor.setDecompressTargetPath(releaseTempDir); + decompressor.decompress(); + log.info("HostAgentService.installAgent decompress success"); + } catch (Exception e) { + log.error("HostAgentService.installAgent decompress error", e); + throw Exceptions.app(ErrorMessage.CALC_SIGN_FAILED, e); + } + // 获取全部文件 + List decompressFiles = Files1.listFiles(releaseTempDir); + log.info("HostAgentService.installAgent decompressFiles: {}", Lists.map(decompressFiles, File::getName)); + // 检查版本文件 + String versionFile = releaseTempDir + Const.SLASH + FileConst.VERSION; + Valid.isTrue(Files1.isFile(versionFile), ErrorMessage.DECOMPRESS_FILE_ABSENT + Const.SPACE + FileConst.VERSION); + // 移动文件 + for (File decompressFile : decompressFiles) { + String releaseFile = releaseDir + Const.SLASH + decompressFile.getName(); + // 删除原始文件 + Files1.deleteFile(releaseFile); + // 复制文件 + Files1.copy(decompressFile.getAbsolutePath(), releaseFile); + log.info("HostAgentService.installAgent move: {}", releaseFile); + } + // 删除临时文件夹 + Files1.delete(releaseTempDir); + // 重新加载版本 + this.readLocalAgentVersion(); + } + + @Override + public String getAgentVersion() { + return localVersion; + } + + /** + * 检查并创建安装任务参数 + * + * @param hosts hosts + * @return taskParams + */ + private List createInstallTaskParams(List hosts) { + List taskParams = new ArrayList<>(); + // 待检查的文件列表 + Set checkFileList = new HashSet<>(); + // 任务参数 + for (HostDO host : hosts) { + // 是否启用 + Valid.eq(HostStatusEnum.ENABLED.name(), host.getStatus(), ErrorMessage.HOST_NOT_ENABLED, host.getName()); + // 是否支持 ssh + boolean supportSsh = HostTypeEnum.SSH.contains(host.getTypes()); + Valid.isTrue(supportSsh, ErrorMessage.PLEASE_CHECK_HOST_SSH, host.getName()); + // 文件名称 + HostOsTypeEnum os = HostOsTypeEnum.of(host.getOsType()); + String agentFileName = Strings.format(FileConst.INSTANCE_AGENT_FILE_FORMAT, + os.name().toLowerCase(), + host.getArchType().toLowerCase(), + os.getBinarySuffix()); + // 安装参数 + AgentInstallParams params = AgentInstallParams.builder() + .hostId(host.getId()) + .osType(host.getOsType()) + .agentKey(host.getAgentKey()) + .agentFilePath(PathUtils.getOrionPath(FileConst.INSTANCE_AGENT_RELEASE + Const.SLASH + agentFileName)) + .configFilePath(PathUtils.getOrionPath(FileConst.INSTANCE_AGENT_RELEASE + Const.SLASH + FileConst.CONFIG_YAML)) + .startScriptPath(PathUtils.getOrionPath(FileConst.INSTANCE_AGENT_RELEASE + Const.SLASH + Const.START + os.getScriptSuffix())) + .build(); + taskParams.add(params); + // 添加待检查文件 + checkFileList.add(params.getAgentFilePath()); + checkFileList.add(params.getStartScriptPath()); + checkFileList.add(params.getConfigFilePath()); + } + + // 检查文件是否存在 + for (String file : checkFileList) { + Valid.isTrue(Files1.isFile(file), ErrorMessage.FILE_ABSENT + Const.SPACE + file); + } + return taskParams; + } + + /** + * 获取替换变量 + * + * @return vars + */ + private Map getReplaceVars() { + Map map = new HashMap<>(); + map.put("SERVER_HOST", IPs.IP); + map.put("SERVER_TOKEN", exposeToken); + return map; + } + + /** + * 获取主机替换变量 + * + * @param vars vars + * @return vars + */ + private Map getHostReplaceVars(Map vars, AgentInstallParams params) { + vars = Maps.newMap(vars); + vars.put("AGENT_KEY", params.getAgentKey()); + return vars; + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostConnectServiceImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostConnectServiceImpl.java index 647a5451..c369de68 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostConnectServiceImpl.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostConnectServiceImpl.java @@ -476,6 +476,7 @@ public class HostConnectServiceImpl implements HostConnectService { config.setHostName(host.getName()); config.setHostCode(host.getCode()); config.setHostAddress(host.getAddress()); + config.setAgentKey(host.getAgentKey()); } } diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostExtraServiceImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostExtraServiceImpl.java index 3add637b..0e7cb714 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostExtraServiceImpl.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostExtraServiceImpl.java @@ -23,10 +23,15 @@ package org.dromara.visor.module.asset.service.impl; import cn.orionsec.kit.lang.utils.Strings; +import cn.orionsec.kit.lang.utils.collect.Lists; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.handler.data.model.GenericsDataModel; import org.dromara.visor.common.utils.Valid; import org.dromara.visor.framework.security.core.utils.SecurityUtils; +import org.dromara.visor.module.asset.dao.HostDAO; import org.dromara.visor.module.asset.entity.request.host.HostExtraUpdateRequest; import org.dromara.visor.module.asset.handler.host.extra.HostExtraItemEnum; import org.dromara.visor.module.asset.handler.host.extra.model.HostSpecExtraModel; @@ -53,6 +58,9 @@ import java.util.stream.Collectors; @Service public class HostExtraServiceImpl implements HostExtraService { + @Resource + private HostDAO hostDAO; + @Resource private DataExtraApi dataExtraApi; @@ -146,6 +154,44 @@ public class HostExtraServiceImpl implements HostExtraService { dataExtraApi.addExtraItems(newItems, DataExtraTypeEnum.HOST); } + @Override + public void syncHostSpec(String key, String taskId, JSONObject spec) { + try { + // 查询主机id + Long id = hostDAO.selectIdByAgentKey(key); + Valid.notNull(id, ErrorMessage.HOST_ABSENT); + // 设置已同步标识 + spec.put(Const.SYNCED, true); + // 查询配置信息 + String newSpec; + HostSpecExtraModel beforeSpec = this.getHostSpecMap(Lists.singleton(id)).get(id); + if (beforeSpec == null) { + // 新增 + newSpec = spec.toString(); + } else { + // 合并 + JSONObject beforeSpecValue = JSON.parseObject(beforeSpec.serial()); + spec.forEach((k, v) -> { + if (v != null) { + beforeSpecValue.put(k, v); + } + }); + newSpec = beforeSpecValue.toJSONString(); + } + // 修改规格 + DataExtraSetDTO update = new DataExtraSetDTO(); + update.setUserId(Const.SYSTEM_USER_ID); + update.setRelId(id); + update.setItem(HostExtraItemEnum.SPEC.name()); + update.setValue(newSpec); + dataExtraApi.setExtraItem(update, DataExtraTypeEnum.HOST); + // 回调成功 + } catch (Exception e) { + // 回调失败 + throw e; + } + } + /** * 检查配置项并且转为视图 (不存在则初始化默认值) * diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostServiceImpl.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostServiceImpl.java index b5a2c178..4d10c694 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostServiceImpl.java +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/service/impl/HostServiceImpl.java @@ -23,6 +23,7 @@ package org.dromara.visor.module.asset.service.impl; import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import cn.orionsec.kit.lang.id.UUIds; import cn.orionsec.kit.lang.utils.Booleans; import cn.orionsec.kit.lang.utils.Strings; import cn.orionsec.kit.lang.utils.collect.Lists; @@ -36,6 +37,7 @@ import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.enums.EnableStatus; import org.dromara.visor.common.utils.Valid; import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; +import org.dromara.visor.framework.mybatis.core.query.DataQuery; import org.dromara.visor.framework.redis.core.utils.RedisMaps; import org.dromara.visor.framework.redis.core.utils.barrier.CacheBarriers; import org.dromara.visor.module.asset.convert.HostConvert; @@ -46,6 +48,7 @@ import org.dromara.visor.module.asset.entity.domain.HostDO; import org.dromara.visor.module.asset.entity.dto.HostCacheDTO; import org.dromara.visor.module.asset.entity.request.host.*; import org.dromara.visor.module.asset.entity.vo.HostVO; +import org.dromara.visor.module.asset.enums.AgentInstallStatusEnum; import org.dromara.visor.module.asset.enums.HostStatusEnum; import org.dromara.visor.module.asset.handler.host.extra.HostExtraItemEnum; import org.dromara.visor.module.asset.handler.host.extra.model.HostSpecExtraModel; @@ -63,6 +66,7 @@ import org.dromara.visor.module.infra.enums.DataExtraTypeEnum; import org.dromara.visor.module.infra.enums.DataGroupTypeEnum; import org.dromara.visor.module.infra.enums.FavoriteTypeEnum; import org.dromara.visor.module.infra.enums.TagTypeEnum; +import org.dromara.visor.module.monitor.api.MonitorHostApi; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -116,13 +120,19 @@ public class HostServiceImpl implements HostService { @Resource private DataExtraApi dataExtraApi; + @Resource + private MonitorHostApi monitorHostApi; + @Override @Transactional(rollbackFor = Exception.class) public Long createHost(HostCreateRequest request) { log.info("HostService-createHost request: {}", JSON.toJSONString(request)); // 转换 HostDO record = HostConvert.MAPPER.to(request); + // 设置默认值 record.setStatus(HostStatusEnum.ENABLED.name()); + record.setAgentKey(UUIds.random32()); + record.setAgentInstallStatus(AgentInstallStatusEnum.NOT_INSTALL.getStatus()); // 查询数据是否冲突 this.checkHostNamePresent(record); this.checkHostCodePresent(record); @@ -230,7 +240,13 @@ public class HostServiceImpl implements HostService { @Override @SneakyThrows - public HostVO getHostById(Long id) { + public HostVO getHostById(Long id, Boolean base) { + // 查询主机基础信息 + if (Booleans.isTrue(base)) { + HostDO record = hostDAO.selectById(id); + Valid.notNull(record, ErrorMessage.HOST_ABSENT); + return HostConvert.MAPPER.to(record); + } // 查询 tag 信息 Future> tagFuture = tagRelApi.getRelTagsAsync(TagTypeEnum.HOST, id); // 查询分组信息 @@ -238,10 +254,13 @@ public class HostServiceImpl implements HostService { // 查询主机 HostDO record = hostDAO.selectById(id); Valid.notNull(record, ErrorMessage.HOST_ABSENT); + // 查询规格 + HostSpecExtraModel spec = hostExtraService.getHostExtra(Const.SYSTEM_USER_ID, id, HostExtraItemEnum.SPEC); // 转换 HostVO vo = HostConvert.MAPPER.to(record); vo.setTags(tagFuture.get()); vo.setGroupIdList(groupIdFuture.get()); + vo.setSpec(spec); return vo; } @@ -283,12 +302,20 @@ public class HostServiceImpl implements HostService { if (wrapper == null) { return DataGrid.of(Lists.empty()); } - // 查询 - DataGrid hosts = hostDAO.of() + // 完整条件 + DataQuery query = hostDAO.of() .wrapper(wrapper) - .page(request) - .order(request, HostDO::getId) - .dataGrid(HostConvert.MAPPER::to); + .page(request); + if (Booleans.isTrue(request.getOrderByAgent())) { + // 通过 agentInstallStatus 进行排序 + query.order(false, HostDO::getAgentInstallStatus); + query.order(false, HostDO::getAgentOnlineStatus); + } else { + // 通过 id 进行排序 + query.order(request, HostDO::getId); + } + // 查询数据 + DataGrid hosts = query.dataGrid(HostConvert.MAPPER::to); // 查询拓展信息 this.setExtraInfo(request, hosts.getRows()); return hosts; @@ -343,6 +370,8 @@ public class HostServiceImpl implements HostService { favoriteApi.deleteByRelIdList(FavoriteTypeEnum.HOST, idList); // 删除额外配置 dataExtraApi.deleteByRelIdList(DataExtraTypeEnum.HOST, idList); + // 删除监控主机 + monitorHostApi.deleteByHostIdList(idList); } @Override @@ -396,9 +425,13 @@ public class HostServiceImpl implements HostService { } // 基础条件 wrapper.eq(HostDO::getId, request.getId()) + .in(HostDO::getId, request.getIdList()) .eq(HostDO::getOsType, request.getOsType()) .eq(HostDO::getArchType, request.getArchType()) .eq(HostDO::getStatus, request.getStatus()) + .eq(HostDO::getAgentKey, request.getAgentKey()) + .eq(HostDO::getAgentInstallStatus, request.getAgentInstallStatus()) + .eq(HostDO::getAgentOnlineStatus, request.getAgentOnlineStatus()) .like(HostDO::getName, request.getName()) .like(HostDO::getCode, request.getCode()) .like(HostDO::getAddress, request.getAddress()) diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/task/AgentHeartbeatCheckTask.java b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/task/AgentHeartbeatCheckTask.java new file mode 100644 index 00000000..dbad8171 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/org/dromara/visor/module/asset/task/AgentHeartbeatCheckTask.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.asset.task; + +import org.dromara.visor.module.asset.service.HostAgentEndpointService; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 探针心跳检查任务 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/4/15 23:50 + */ +@Component +public class AgentHeartbeatCheckTask { + + @Resource + private HostAgentEndpointService hostAgentEndpointService; + + /** + * 每分钟检测心跳 + */ + @Scheduled(initialDelay = 65000, fixedRate = 60000) + public void checkHeartbeat() { + hostAgentEndpointService.checkHeartbeat(); + } + +} diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostAgentLogMapper.xml b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostAgentLogMapper.xml new file mode 100644 index 00000000..003e5aeb --- /dev/null +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostAgentLogMapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + id, host_id, agent_key, type, status, message, create_time, update_time, creator, updater, deleted + + + diff --git a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostMapper.xml b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostMapper.xml index 6e205c27..83e65934 100644 --- a/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostMapper.xml +++ b/orion-visor-modules/orion-visor-module-asset/orion-visor-module-asset-service/src/main/resources/mapper/HostMapper.xml @@ -12,6 +12,11 @@ + + + + + @@ -22,7 +27,7 @@ - id, types, os_type, arch_type, name, code, address, status, description, create_time, update_time, creator, updater, deleted + id, types, os_type, arch_type, name, code, address, status, agent_key, agent_version, agent_install_status, agent_online_status, agent_online_change_time, description, create_time, update_time, creator, updater, deleted diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/controller/UploadTaskController.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/controller/UploadTaskController.java index d189fff1..eb622ca9 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/controller/UploadTaskController.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/controller/UploadTaskController.java @@ -113,7 +113,8 @@ public class UploadTaskController { @Operation(summary = "查询上传状态") @Parameter(name = "id", description = "id", required = true) @PreAuthorize("@ss.hasPermission('exec:upload-task:query')") - public List getUploadTaskStatus(@RequestParam("idList") List idList, @RequestParam("queryFiles") Boolean queryFiles) { + public List getUploadTaskStatus(@RequestParam("idList") List idList, + @RequestParam("queryFiles") Boolean queryFiles) { return uploadTaskService.getUploadTaskStatus(idList, queryFiles); } diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/define/ExecThreadPools.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/define/ExecThreadPools.java index cfa7362b..81e78ae2 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/define/ExecThreadPools.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/define/ExecThreadPools.java @@ -29,7 +29,7 @@ import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; /** - * 资产线程池 + * 执行线程池 * * @author Jiahang Li * @version 1.0.0 diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/command/handler/BaseExecCommandHandler.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/command/handler/BaseExecCommandHandler.java index f40411cc..bcb81f31 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/command/handler/BaseExecCommandHandler.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/command/handler/BaseExecCommandHandler.java @@ -44,7 +44,7 @@ import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.constant.FileConst; import org.dromara.visor.common.enums.BooleanBit; import org.dromara.visor.common.enums.EndpointDefine; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.common.session.config.SshConnectConfig; import org.dromara.visor.common.session.ssh.SessionStores; import org.dromara.visor.common.utils.PathUtils; @@ -408,6 +408,7 @@ public abstract class BaseExecCommandHandler implements IExecCommandHandler { params.put("hostAddress", connectConfig.getHostAddress()); params.put("hostPort", connectConfig.getHostPort()); params.put("hostUsername", connectConfig.getUsername()); + params.put("agentKey", connectConfig.getAgentKey()); params.put("hostUuid", uuid); params.put("hostUuidShort", uuid.replace("-", Strings.EMPTY)); params.put("osType", connectConfig.getOsType()); diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/log/tracker/ExecLogTracker.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/log/tracker/ExecLogTracker.java index 483c8360..a261a12b 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/log/tracker/ExecLogTracker.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/exec/log/tracker/ExecLogTracker.java @@ -38,7 +38,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.ErrorMessage; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.common.utils.Valid; import org.dromara.visor.framework.websocket.core.utils.WebSockets; import org.dromara.visor.module.common.config.AppLogConfig; diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/upload/uploader/FileUploader.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/upload/uploader/FileUploader.java index c18b7080..49cb140c 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/upload/uploader/FileUploader.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/handler/upload/uploader/FileUploader.java @@ -35,7 +35,7 @@ import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.constant.ExtraFieldConst; import org.dromara.visor.common.enums.EndpointDefine; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.common.session.config.SshConnectConfig; import org.dromara.visor.common.session.ssh.SessionStores; import org.dromara.visor.common.utils.PathUtils; diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/ExecLogServiceImpl.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/ExecLogServiceImpl.java index 6c7483ff..e872a4f4 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/ExecLogServiceImpl.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/ExecLogServiceImpl.java @@ -39,7 +39,7 @@ import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.constant.FileConst; import org.dromara.visor.common.enums.EndpointDefine; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.common.utils.SqlUtils; import org.dromara.visor.common.utils.Valid; import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/UploadTaskServiceImpl.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/UploadTaskServiceImpl.java index 26e1531a..072bb330 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/UploadTaskServiceImpl.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/service/impl/UploadTaskServiceImpl.java @@ -35,7 +35,7 @@ import lombok.extern.slf4j.Slf4j; import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.enums.EndpointDefine; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.common.security.LoginUser; import org.dromara.visor.common.utils.SqlUtils; import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; @@ -372,10 +372,9 @@ public class UploadTaskServiceImpl implements UploadTaskService { // 检查主机数量 Valid.eq(hosts.size(), hostIdList.size(), ErrorMessage.HOST_ABSENT); // 检查主机状态 - boolean allEnabled = hosts.stream() - .map(HostDTO::getStatus) - .allMatch(s -> HostStatusEnum.ENABLED.name().equals(s)); - Valid.isTrue(allEnabled, ErrorMessage.HOST_NOT_ENABLED); + for (HostDTO host : hosts) { + Valid.eq(HostStatusEnum.ENABLED.name(), host.getStatus(), ErrorMessage.HOST_NOT_ENABLED, host.getName()); + } return hosts; } diff --git a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/task/ExecLogFileAutoClearTask.java b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/task/ExecLogFileAutoClearTask.java index 8e9e9c83..5f243940 100644 --- a/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/task/ExecLogFileAutoClearTask.java +++ b/orion-visor-modules/orion-visor-module-exec/orion-visor-module-exec-service/src/main/java/org/dromara/visor/module/exec/task/ExecLogFileAutoClearTask.java @@ -70,7 +70,7 @@ public class ExecLogFileAutoClearTask { return; } // 获取锁并执行 - LockerUtils.tryLock(LOCK_KEY, this::doClear); + LockerUtils.tryLockExecute(LOCK_KEY, this::doClear); log.info("ExecLogFileAutoClearTask.clear finish"); } diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/org/dromara/visor/module/infra/api/SystemUserApi.java b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/org/dromara/visor/module/infra/api/SystemUserApi.java index 07bdc5e8..e705fb68 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/org/dromara/visor/module/infra/api/SystemUserApi.java +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/org/dromara/visor/module/infra/api/SystemUserApi.java @@ -33,6 +33,14 @@ import org.dromara.visor.module.infra.entity.dto.user.SystemUserDTO; */ public interface SystemUserApi { + /** + * 通过用户名查询 id + * + * @param username username + * @return id + */ + Long getIdByUsername(String username); + /** * 通过 id 查询用户名 * diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/api/impl/SystemUserApiImpl.java b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/api/impl/SystemUserApiImpl.java index de95ba5a..2745c662 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/api/impl/SystemUserApiImpl.java +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/api/impl/SystemUserApiImpl.java @@ -44,6 +44,16 @@ public class SystemUserApiImpl implements SystemUserApi { @Resource private SystemUserDAO systemUserDAO; + @Override + public Long getIdByUsername(String username) { + return systemUserDAO.of() + .createWrapper() + .select(SystemUserDO::getId) + .eq(SystemUserDO::getUsername, username) + .then() + .getOne(SystemUserDO::getId); + } + @Override public String getUsernameById(Long id) { return systemUserDAO.of() diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/controller/DictKeyController.java b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/controller/DictKeyController.java index de2dff02..f991c4fa 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/controller/DictKeyController.java +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/controller/DictKeyController.java @@ -27,6 +27,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.validator.group.Page; import org.dromara.visor.framework.biz.operator.log.core.annotation.OperatorLog; import org.dromara.visor.framework.log.core.annotation.IgnoreLog; import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; @@ -92,7 +93,7 @@ public class DictKeyController { @PostMapping("/query") @Operation(summary = "分页查询全部字典配置项") @PreAuthorize("@ss.hasPermission('infra:dict-key:query')") - public DataGrid getDictKeyPage(@Validated @RequestBody DictKeyQueryRequest request) { + public DataGrid getDictKeyPage(@Validated(Page.class) @RequestBody DictKeyQueryRequest request) { return dictKeyService.getDictKeyPage(request); } diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/FileUploadMessageDispatcher.java b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/FileUploadMessageDispatcher.java index b901508c..ccb09581 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/FileUploadMessageDispatcher.java +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/FileUploadMessageDispatcher.java @@ -27,7 +27,7 @@ import cn.orionsec.kit.lang.utils.io.Streams; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.dromara.visor.common.constant.ExtraFieldConst; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.framework.websocket.core.utils.WebSockets; import org.dromara.visor.module.infra.entity.dto.FileUploadTokenDTO; import org.dromara.visor.module.infra.handler.upload.enums.FileUploadOperatorType; diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/handler/FileUploadHandler.java b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/handler/FileUploadHandler.java index 92fb91dc..7d9182b9 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/handler/FileUploadHandler.java +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/handler/upload/handler/FileUploadHandler.java @@ -25,7 +25,7 @@ package org.dromara.visor.module.infra.handler.upload.handler; import cn.orionsec.kit.lang.utils.io.Streams; import com.alibaba.fastjson.JSON; import org.dromara.visor.common.constant.Const; -import org.dromara.visor.common.interfaces.FileClient; +import org.dromara.visor.common.file.FileClient; import org.dromara.visor.framework.websocket.core.utils.WebSockets; import org.dromara.visor.module.infra.handler.upload.enums.FileUploadReceiverType; import org.dromara.visor.module.infra.handler.upload.model.FileUploadResponse; diff --git a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/task/TagAutoClearTask.java b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/task/TagAutoClearTask.java index 3c617637..a82ac8c3 100644 --- a/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/task/TagAutoClearTask.java +++ b/orion-visor-modules/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/org/dromara/visor/module/infra/task/TagAutoClearTask.java @@ -56,7 +56,7 @@ public class TagAutoClearTask { public void clear() { log.info("TagAutoClearTask.clear start"); // 获取锁并执行 - LockerUtils.tryLock(LOCK_KEY, tagService::clearUnusedTag); + LockerUtils.tryLockExecute(LOCK_KEY, tagService::clearUnusedTag); log.info("TagAutoClearTask.clear finish"); } diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/pom.xml b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/pom.xml new file mode 100644 index 00000000..222fb39f --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/pom.xml @@ -0,0 +1,26 @@ + + + + org.dromara.visor + orion-visor-module-monitor + ${revision} + + + 4.0.0 + orion-visor-module-monitor-provider + jar + + 项目监控模块 + https://github.com/dromara/orion-visor + + + + + org.dromara.visor + orion-visor-common + + + + \ No newline at end of file diff --git a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/Locker.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/src/main/java/org/dromara/visor/module/monitor/api/MonitorHostApi.java similarity index 65% rename from orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/Locker.java rename to orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/src/main/java/org/dromara/visor/module/monitor/api/MonitorHostApi.java index d08705ea..ecfd6898 100644 --- a/orion-visor-common/src/main/java/org/dromara/visor/common/interfaces/Locker.java +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/src/main/java/org/dromara/visor/module/monitor/api/MonitorHostApi.java @@ -20,36 +20,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.dromara.visor.common.interfaces; +package org.dromara.visor.module.monitor.api; -import java.util.function.Supplier; +import java.util.List; /** - * 分布式锁 + * 监控主机对外服务 * * @author Jiahang Li * @version 1.0.0 - * @since 2024/5/16 12:24 + * @since 2025/8/19 15:48 */ -public interface Locker { +public interface MonitorHostApi { /** - * 尝试获取锁 + * 设置探针为下线状态 * - * @param key key - * @param run run - * @return 是否获取到锁 + * @param agentKeyList agentKeyList */ - boolean tryLock(String key, Runnable run); + void setAgentOffline(List agentKeyList); /** - * 尝试获取锁 + * 删除监控主机 * - * @param key key - * @param call call - * @param T - * @return 执行结果 + * @param hostIdList hostIdList + * @return effect */ - T tryLock(String key, Supplier call); + Integer deleteByHostIdList(List hostIdList); } diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/src/main/java/org/dromara/visor/module/monitor/entity/dto/.gitkeep b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-provider/src/main/java/org/dromara/visor/module/monitor/entity/dto/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/pom.xml b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/pom.xml new file mode 100644 index 00000000..2c112e37 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/pom.xml @@ -0,0 +1,110 @@ + + + + org.dromara.visor + orion-visor-module-monitor + ${revision} + + + 4.0.0 + orion-visor-module-monitor-service + jar + + 项目监控模块 + https://github.com/dromara/orion-visor + + + + + org.dromara.visor + orion-visor-common + + + + + org.dromara.visor + orion-visor-module-common + ${revision} + + + + + org.dromara.visor + orion-visor-module-infra-provider + ${revision} + + + org.dromara.visor + orion-visor-module-asset-provider + ${revision} + + + org.dromara.visor + orion-visor-module-monitor-provider + ${revision} + + + + + org.dromara.visor + orion-visor-spring-boot-starter-web + + + org.dromara.visor + orion-visor-spring-boot-starter-websocket + + + org.dromara.visor + orion-visor-spring-boot-starter-log + + + org.dromara.visor + orion-visor-spring-boot-starter-biz-operator-log + + + org.dromara.visor + orion-visor-spring-boot-starter-desensitize + + + org.dromara.visor + orion-visor-spring-boot-starter-security + + + org.dromara.visor + orion-visor-spring-boot-starter-redis + + + org.dromara.visor + orion-visor-spring-boot-starter-mybatis + + + org.dromara.visor + orion-visor-spring-boot-starter-storage + + + org.dromara.visor + orion-visor-spring-boot-starter-job + + + org.dromara.visor + orion-visor-spring-boot-starter-test + + + org.dromara.visor + orion-visor-spring-boot-starter-influxdb + + + + + + + + com.github.wvengen + proguard-maven-plugin + + + + + \ No newline at end of file diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/api/impl/MonitorHostApiImpl.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/api/impl/MonitorHostApiImpl.java new file mode 100644 index 00000000..29c6a93d --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/api/impl/MonitorHostApiImpl.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.api.impl; + +import cn.orionsec.kit.lang.utils.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.module.monitor.api.MonitorHostApi; +import org.dromara.visor.module.monitor.dao.MonitorHostDAO; +import org.dromara.visor.module.monitor.define.context.MonitorContext; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 监控主机对外服务实现 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/19 15:48 + */ +@Slf4j +@Service +public class MonitorHostApiImpl implements MonitorHostApi { + + @Resource + private MonitorHostDAO monitorHostDAO; + + @Resource + private MonitorContext monitorContext; + + @Override + public void setAgentOffline(List agentKeyList) { + // 下线后删除指标 + agentKeyList.forEach(s -> monitorContext.setAgentMetrics(s, null)); + } + + @Override + public Integer deleteByHostIdList(List hostIdList) { + log.info("MonitorHostApi.deleteByHostIdList start hostIdList: {}", hostIdList); + if (Lists.isEmpty(hostIdList)) { + return Const.N_0; + } + // 通过 hostId 删除 + int effect = monitorHostDAO.deleteByHostIdList(hostIdList); + log.info("MonitorHostApi.deleteByHostIdList finish effect: {}", effect); + return effect; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/constant/MetricsConst.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/constant/MetricsConst.java new file mode 100644 index 00000000..d4b16946 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/constant/MetricsConst.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.constant; + +/** + * 指标常量 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/15 17:23 + */ +public interface MetricsConst { + + String CPU_USER_SECONDS_TOTAL = "cpu_user_seconds_total"; + String CPU_SYSTEM_SECONDS_TOTAL = "cpu_system_seconds_total"; + String CPU_TOTAL_SECONDS_TOTAL = "cpu_total_seconds_total"; + + String MEM_USED_BYTES_TOTAL = "mem_used_bytes_total"; + String MEM_USED_PERCENT = "mem_used_percent"; + String MEM_SWAP_USED_BYTES_TOTAL = "mem_swap_used_bytes_total"; + String MEM_SWAP_USED_PERCENT = "mem_swap_used_percent"; + + String LOAD1 = "load1"; + String LOAD5 = "load5"; + String LOAD15 = "load15"; + String LOAD1_CORE_RATIO = "load1_core_ratio"; + String LOAD5_CORE_RATIO = "load5_core_ratio"; + String LOAD15_CORE_RATIO = "load15_core_ratio"; + + String DISK_FS_USED_BYTES_TOTAL = "disk_fs_used_bytes_total"; + String DISK_FS_USED_PERCENT = "disk_fs_used_percent"; + String DISK_FS_INODES_USED_PERCENT = "disk_fs_inodes_used_percent"; + + String DISK_IO_READ_BYTES_TOTAL = "disk_io_read_bytes_total"; + String DISK_IO_WRITE_BYTES_TOTAL = "disk_io_write_bytes_total"; + String DISK_IO_READS_TOTAL = "disk_io_reads_total"; + String DISK_IO_WRITES_TOTAL = "disk_io_writes_total"; + String DISK_IO_READ_BYTES_PER_SECOND = "disk_io_read_bytes_per_second"; + String DISK_IO_WRITE_BYTES_PER_SECOND = "disk_io_write_bytes_per_second"; + String DISK_IO_READS_PER_SECOND = "disk_io_reads_per_second"; + String DISK_IO_WRITES_PER_SECOND = "disk_io_writes_per_second"; + + String NET_SENT_BYTES_TOTAL = "net_sent_bytes_total"; + String NET_RECV_BYTES_TOTAL = "net_recv_bytes_total"; + String NET_SENT_PACKETS_TOTAL = "net_sent_packets_total"; + String NET_RECV_PACKETS_TOTAL = "net_recv_packets_total"; + String NET_SENT_BYTES_PER_SECOND = "net_sent_bytes_per_second"; + String NET_RECV_BYTES_PER_SECOND = "net_recv_bytes_per_second"; + String NET_SENT_PACKETS_PER_SECOND = "net_sent_packets_per_second"; + String NET_RECV_PACKETS_PER_SECOND = "net_recv_packets_per_second"; + + String NET_TCP_CONNECTIONS = "net_tcp_connections"; + String NET_UDP_CONNECTIONS = "net_udp_connections"; + String NET_INET_CONNECTIONS = "net_inet_connections"; + String NET_ALL_CONNECTIONS = "net_all_connections"; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorAgentEndpointController.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorAgentEndpointController.java new file mode 100644 index 00000000..b1e5fba2 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorAgentEndpointController.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.CustomHeaderConst; +import org.dromara.visor.framework.log.core.annotation.IgnoreLog; +import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; +import org.dromara.visor.framework.web.core.annotation.ExposeApi; +import org.dromara.visor.framework.web.core.annotation.RestWrapper; +import org.dromara.visor.module.monitor.entity.dto.HostMetaDTO; +import org.dromara.visor.module.monitor.entity.dto.MetricsDataDTO; +import org.dromara.visor.module.monitor.service.MonitorAgentEndpointService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * 监控探针端点 api + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 14:33 + */ +@Tag(name = "monitor - 监控探针端点") +@Slf4j +@Validated +@RestWrapper +@RestController +@RequestMapping("/monitor/agent-endpoint") +public class MonitorAgentEndpointController { + + @Resource + private MonitorAgentEndpointService monitorAgentEndpointService; + + @ExposeApi + @IgnoreLog(IgnoreLogMode.ALL) + @PostMapping("/metrics") + @Operation(summary = "上报指标数据") + public Boolean addMetrics(@RequestHeader(CustomHeaderConst.AGENT_KEY_HEADER) String key, + @RequestBody MetricsDataDTO data) { + monitorAgentEndpointService.addMetrics(key, data); + return true; + } + + @ExposeApi + @PostMapping("/sync-host-meta") + @Operation(summary = "上线时同步主机元数据") + public Boolean syncHostMeta(@RequestHeader(CustomHeaderConst.AGENT_KEY_HEADER) String key, + @RequestBody HostMetaDTO data) { + monitorAgentEndpointService.syncHostMeta(key, data); + return true; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorHostController.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorHostController.java new file mode 100644 index 00000000..2e83692f --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorHostController.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.controller; + +import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.entity.chart.TimeChartSeries; +import org.dromara.visor.common.validator.group.Key; +import org.dromara.visor.common.validator.group.Page; +import org.dromara.visor.framework.biz.operator.log.core.annotation.OperatorLog; +import org.dromara.visor.framework.log.core.annotation.IgnoreLog; +import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; +import org.dromara.visor.framework.web.core.annotation.DemoDisableApi; +import org.dromara.visor.framework.web.core.annotation.RestWrapper; +import org.dromara.visor.module.monitor.define.operator.MonitorHostOperatorType; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostChartRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostQueryRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostSwitchUpdateRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostMetricsDataVO; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO; +import org.dromara.visor.module.monitor.service.MonitorHostService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 监控主机 api + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Tag(name = "monitor - 监控主机服务") +@Slf4j +@Validated +@RestWrapper +@RestController +@RequestMapping("/monitor/monitor-host") +public class MonitorHostController { + + @Resource + private MonitorHostService monitorHostService; + + @IgnoreLog(IgnoreLogMode.RET) + @PostMapping("/query") + @Operation(summary = "分页查询监控主机") + @PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')") + public DataGrid getMonitorHostPage(@Validated(Page.class) @RequestBody MonitorHostQueryRequest request) { + return monitorHostService.getMonitorHostPage(request); + } + + @IgnoreLog(IgnoreLogMode.RET) + @PostMapping("/metrics") + @Operation(summary = "查询监控指标") + @PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')") + public List getMonitorHostMetrics(@Validated(Key.class) @RequestBody MonitorHostQueryRequest request) { + return monitorHostService.getMonitorHostMetrics(request.getAgentKeyList()); + } + + @IgnoreLog(IgnoreLogMode.RET) + @PostMapping("/chart") + @Operation(summary = "查询监控指标") + @PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')") + public List getMonitorHostChart(@Validated @RequestBody MonitorHostChartRequest request) { + return monitorHostService.getMonitorHostChart(request); + } + + @DemoDisableApi + @OperatorLog(MonitorHostOperatorType.UPDATE) + @PutMapping("/update") + @Operation(summary = "更新监控主机") + @PreAuthorize("@ss.hasPermission('monitor:monitor-host:update')") + public Integer updateMonitorHost(@Validated @RequestBody MonitorHostUpdateRequest request) { + return monitorHostService.updateMonitorHostById(request); + } + + @DemoDisableApi + @OperatorLog(MonitorHostOperatorType.UPDATE_SWITCH) + @PutMapping("/update-switch") + @Operation(summary = "更新监控主机告警开关") + @PreAuthorize("@ss.hasAnyPermission('monitor:monitor-host:update', 'monitor:monitor-host:update-switch')") + public Integer updateMonitorHostAlarmSwitch(@Validated @RequestBody MonitorHostSwitchUpdateRequest request) { + return monitorHostService.updateMonitorHostAlarmSwitch(request); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorMetricsController.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorMetricsController.java new file mode 100644 index 00000000..905c09b0 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/controller/MonitorMetricsController.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.controller; + +import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.validator.group.Page; +import org.dromara.visor.framework.biz.operator.log.core.annotation.OperatorLog; +import org.dromara.visor.framework.log.core.annotation.IgnoreLog; +import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; +import org.dromara.visor.framework.web.core.annotation.DemoDisableApi; +import org.dromara.visor.framework.web.core.annotation.RestWrapper; +import org.dromara.visor.module.monitor.define.operator.MonitorMetricsOperatorType; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsCreateRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsQueryRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorMetricsVO; +import org.dromara.visor.module.monitor.service.MonitorMetricsService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 监控指标 api + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Tag(name = "monitor - 监控指标服务") +@Slf4j +@Validated +@RestWrapper +@RestController +@RequestMapping("/monitor/monitor-metrics") +public class MonitorMetricsController { + + @Resource + private MonitorMetricsService monitorMetricsService; + + @DemoDisableApi + @OperatorLog(MonitorMetricsOperatorType.CREATE) + @PostMapping("/create") + @Operation(summary = "创建监控指标") + @PreAuthorize("@ss.hasPermission('monitor:monitor-metrics:create')") + public Long createMonitorMetrics(@Validated @RequestBody MonitorMetricsCreateRequest request) { + return monitorMetricsService.createMonitorMetrics(request); + } + + @DemoDisableApi + @OperatorLog(MonitorMetricsOperatorType.UPDATE) + @PutMapping("/update") + @Operation(summary = "更新监控指标") + @PreAuthorize("@ss.hasPermission('monitor:monitor-metrics:update')") + public Integer updateMonitorMetrics(@Validated @RequestBody MonitorMetricsUpdateRequest request) { + return monitorMetricsService.updateMonitorMetricsById(request); + } + + @IgnoreLog(IgnoreLogMode.RET) + @GetMapping("/list") + @Operation(summary = "查询全部监控指标") + @PreAuthorize("@ss.hasPermission('monitor:monitor-metrics:query')") + public List getMonitorMetricsList() { + return monitorMetricsService.getMonitorMetricsList(); + } + + @IgnoreLog(IgnoreLogMode.RET) + @PostMapping("/query") + @Operation(summary = "分页查询监控指标") + @PreAuthorize("@ss.hasPermission('monitor:monitor-metrics:query')") + public DataGrid getMonitorMetricsPage(@Validated(Page.class) @RequestBody MonitorMetricsQueryRequest request) { + return monitorMetricsService.getMonitorMetricsPage(request); + } + + @DemoDisableApi + @OperatorLog(MonitorMetricsOperatorType.DELETE) + @DeleteMapping("/delete") + @Operation(summary = "删除监控指标") + @Parameter(name = "id", description = "id", required = true) + @PreAuthorize("@ss.hasPermission('monitor:monitor-metrics:delete')") + public Integer deleteMonitorMetrics(@RequestParam("id") Long id) { + return monitorMetricsService.deleteMonitorMetricsById(id); + } + + @DemoDisableApi + @OperatorLog(MonitorMetricsOperatorType.DELETE) + @DeleteMapping("/batch-delete") + @Operation(summary = "批量删除监控指标") + @Parameter(name = "idList", description = "idList", required = true) + @PreAuthorize("@ss.hasPermission('monitor:monitor-metrics:delete')") + public Integer batchDeleteMonitorMetrics(@RequestParam("idList") List idList) { + return monitorMetricsService.deleteMonitorMetricsByIdList(idList); + } + +} + diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/convert/MonitorHostConvert.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/convert/MonitorHostConvert.java new file mode 100644 index 00000000..719be752 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/convert/MonitorHostConvert.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.convert; + +import org.dromara.visor.module.asset.entity.dto.host.HostDTO; +import org.dromara.visor.module.asset.entity.dto.host.HostQueryDTO; +import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostQueryRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * 监控主机 内部对象转换器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Mapper +public interface MonitorHostConvert { + + MonitorHostConvert MAPPER = Mappers.getMapper(MonitorHostConvert.class); + + MonitorHostDO to(MonitorHostUpdateRequest request); + + MonitorHostVO to(MonitorHostDO domain); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "hostId", source = "id") + MonitorHostVO to(HostDTO dto); + + HostQueryDTO toHostQuery(MonitorHostQueryRequest request); + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/convert/MonitorMetricsConvert.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/convert/MonitorMetricsConvert.java new file mode 100644 index 00000000..a3e7f862 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/convert/MonitorMetricsConvert.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.convert; + +import org.dromara.visor.module.monitor.entity.domain.MonitorMetricsDO; +import org.dromara.visor.module.monitor.entity.dto.MonitorMetricsCacheDTO; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsCreateRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsQueryRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorMetricsVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 监控指标 内部对象转换器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Mapper +public interface MonitorMetricsConvert { + + MonitorMetricsConvert MAPPER = Mappers.getMapper(MonitorMetricsConvert.class); + + MonitorMetricsDO to(MonitorMetricsCreateRequest request); + + MonitorMetricsDO to(MonitorMetricsUpdateRequest request); + + MonitorMetricsDO to(MonitorMetricsQueryRequest request); + + MonitorMetricsVO to(MonitorMetricsDO domain); + + List to(List list); + + MonitorMetricsVO to(MonitorMetricsCacheDTO cache); + + MonitorMetricsCacheDTO toCache(MonitorMetricsDO domain); + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/dao/MonitorHostDAO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/dao/MonitorHostDAO.java new file mode 100644 index 00000000..bde3f647 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/dao/MonitorHostDAO.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.dao; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.apache.ibatis.annotations.Mapper; +import org.dromara.visor.framework.mybatis.core.mapper.IMapper; +import org.dromara.visor.framework.mybatis.core.query.Conditions; +import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO; + +import java.util.List; + +/** + * 监控主机 Mapper 接口 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Mapper +public interface MonitorHostDAO extends IMapper { + + /** + * 通过 hostIdList 查询 + * + * @param hostIdList hostIdList + * @return rows + */ + default List selectByHostIdList(List hostIdList) { + return this.of() + .createWrapper() + .in(MonitorHostDO::getHostId, hostIdList) + .then() + .list(); + } + + /** + * 通过 agentKey 查询 + * + * @param agentKey agentKey + * @return row + */ + default MonitorHostDO selectByAgentKey(String agentKey) { + return this.of() + .createWrapper() + .eq(MonitorHostDO::getAgentKey, agentKey) + .then() + .getOne(); + } + + /** + * 通过 hostId 查询 + * + * @param hostId hostId + * @return row + */ + default MonitorHostDO selectByHostId(Long hostId) { + return this.of() + .createWrapper() + .eq(MonitorHostDO::getHostId, hostId) + .then() + .getOne(); + } + + /** + * 通过 hostIdList 删除 + * + * @param hostIdList hostIdList + * @return effect + */ + default int deleteByHostIdList(List hostIdList) { + return this.delete(Conditions.in(MonitorHostDO::getHostId, hostIdList)); + } + + /** + * 设置 policyId 为 null + * + * @param policyId policyId + * @return effect + */ + default int setPolicyIdWithNull(Long policyId) { + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate() + .set(MonitorHostDO::getPolicyId, null) + .eq(MonitorHostDO::getPolicyId, policyId); + return this.update(null, updateWrapper); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/dao/MonitorMetricsDAO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/dao/MonitorMetricsDAO.java new file mode 100644 index 00000000..e956c5c4 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/dao/MonitorMetricsDAO.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.dromara.visor.framework.mybatis.core.mapper.IMapper; +import org.dromara.visor.module.monitor.entity.domain.MonitorMetricsDO; + +/** + * 监控指标 Mapper 接口 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Mapper +public interface MonitorMetricsDAO extends IMapper { + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/cache/MonitorMetricsCacheKeyDefine.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/cache/MonitorMetricsCacheKeyDefine.java new file mode 100644 index 00000000..2bc2e58a --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/cache/MonitorMetricsCacheKeyDefine.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.define.cache; + +import cn.orionsec.kit.lang.define.cache.key.CacheKeyBuilder; +import cn.orionsec.kit.lang.define.cache.key.CacheKeyDefine; +import cn.orionsec.kit.lang.define.cache.key.struct.RedisCacheStruct; +import org.dromara.visor.module.monitor.entity.dto.MonitorMetricsCacheDTO; + +import java.util.concurrent.TimeUnit; + +/** + * 监控指标缓存 key + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +public interface MonitorMetricsCacheKeyDefine { + + CacheKeyDefine MONITOR_METRICS = new CacheKeyBuilder() + .key("monitor:metrics:list") + .desc("监控指标") + .type(MonitorMetricsCacheDTO.class) + .struct(RedisCacheStruct.HASH) + .timeout(8, TimeUnit.HOURS) + .build(); + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/context/MonitorContext.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/context/MonitorContext.java new file mode 100644 index 00000000..fbefa1b6 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/context/MonitorContext.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.define.context; + +import cn.orionsec.kit.lang.utils.Strings; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.module.monitor.dao.MonitorHostDAO; +import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO; +import org.dromara.visor.module.monitor.entity.dto.MetricsDataDTO; +import org.dromara.visor.module.monitor.entity.dto.MonitorHostConfigDTO; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 监控上下文 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/21 17:26 + */ +@Slf4j +@Component +public class MonitorContext { + + private static final int MAX_CACHE_TIME = 5 * 60 * 1000; // 5min + + private static final int CLEAN_INTERVAL = 60 * 1000; // 1min + + private static final ConcurrentHashMap LATEST_METRICS_CACHE = new ConcurrentHashMap<>(); + + private static final ConcurrentHashMap HOST_CONFIG_CACHE = new ConcurrentHashMap<>(); + + private long lastCleanTime; + + @Resource + private MonitorHostDAO monitorHostDAO; + + /** + * 初始化监控主机配置 + */ + @PostConstruct + public void initMonitorHostConfig() { + List hosts = monitorHostDAO.selectList(null); + for (MonitorHostDO host : hosts) { + String config = host.getMonitorConfig(); + if (Strings.isBlank(config)) { + continue; + } + // 设置配置缓存 + this.setMonitorHostConfig(host.getAgentKey(), JSON.parseObject(config, MonitorHostConfigDTO.class)); + } + } + + /** + * 设置指标信息 + * + * @param key key + * @param metrics metrics + */ + public void setAgentMetrics(String key, MetricsDataDTO metrics) { + if (metrics == null) { + LATEST_METRICS_CACHE.remove(key); + } else { + LATEST_METRICS_CACHE.put(key, metrics); + } + } + + /** + * 获取指标信息 + * + * @param key key + * @return metrics + */ + public MetricsDataDTO getAgentMetrics(String key) { + // 删除过期缓存 + long current = System.currentTimeMillis(); + if (current - lastCleanTime > CLEAN_INTERVAL) { + this.lastCleanTime = current; + LATEST_METRICS_CACHE.forEach((k, v) -> { + if (current - v.getTimestamp() > MAX_CACHE_TIME) { + LATEST_METRICS_CACHE.remove(k, v); + } + }); + } + return LATEST_METRICS_CACHE.get(key); + } + + /** + * 设置监控主机配置 + * + * @param agentKey agentKey + * @param config config + */ + public void setMonitorHostConfig(String agentKey, MonitorHostConfigDTO config) { + HOST_CONFIG_CACHE.put(agentKey, config); + } + + /** + * 获取监控主机配置 + * + * @param agentKey agentKey + * @return config + */ + public MonitorHostConfigDTO getMonitorHostConfig(String agentKey) { + return HOST_CONFIG_CACHE.get(agentKey); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/operator/MonitorHostOperatorType.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/operator/MonitorHostOperatorType.java new file mode 100644 index 00000000..25850dc4 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/operator/MonitorHostOperatorType.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.define.operator; + +import org.dromara.visor.framework.biz.operator.log.core.annotation.Module; +import org.dromara.visor.framework.biz.operator.log.core.factory.InitializingOperatorTypes; +import org.dromara.visor.framework.biz.operator.log.core.model.OperatorType; + +import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.M; + +/** + * 监控主机 操作日志类型 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Module("monitor:monitor-host") +public class MonitorHostOperatorType extends InitializingOperatorTypes { + + public static final String UPDATE = "monitor-host:update"; + + public static final String UPDATE_SWITCH = "monitor-host:update-switch"; + + @Override + public OperatorType[] types() { + return new OperatorType[]{ + new OperatorType(M, UPDATE, "更新监控配置 ${name}"), + new OperatorType(M, UPDATE_SWITCH, "更新监控开关 ${name}${switch}"), + }; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/operator/MonitorMetricsOperatorType.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/operator/MonitorMetricsOperatorType.java new file mode 100644 index 00000000..c50e902b --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/define/operator/MonitorMetricsOperatorType.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.define.operator; + +import org.dromara.visor.framework.biz.operator.log.core.annotation.Module; +import org.dromara.visor.framework.biz.operator.log.core.factory.InitializingOperatorTypes; +import org.dromara.visor.framework.biz.operator.log.core.model.OperatorType; + +import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.*; + +/** + * 监控指标 操作日志类型 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Module("monitor:monitor-metrics") +public class MonitorMetricsOperatorType extends InitializingOperatorTypes { + + public static final String CREATE = "monitor-metrics:create"; + + public static final String UPDATE = "monitor-metrics:update"; + + public static final String DELETE = "monitor-metrics:delete"; + + @Override + public OperatorType[] types() { + return new OperatorType[]{ + new OperatorType(L, CREATE, "创建监控指标 ${name}"), + new OperatorType(M, UPDATE, "更新监控指标 ${name}"), + new OperatorType(H, DELETE, "删除监控指标 ${count} 条"), + }; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/domain/MonitorHostDO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/domain/MonitorHostDO.java new file mode 100644 index 00000000..8216eb9d --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/domain/MonitorHostDO.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.dromara.visor.framework.mybatis.core.domain.BaseDO; + +/** + * 监控主机 实体对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName(value = "monitor_host", autoResultMap = true) +@Schema(name = "MonitorHostDO", description = "监控主机 实体对象") +public class MonitorHostDO extends BaseDO { + + private static final long serialVersionUID = 1L; + + @Schema(description = "主机id") + @TableField("host_id") + private Long hostId; + + @Schema(description = "策略id") + @TableField("policy_id") + private Long policyId; + + @Schema(description = "agentKey") + @TableField("agent_key") + private String agentKey; + + @Schema(description = "告警开关") + @TableField("alarm_switch") + private Integer alarmSwitch; + + @Schema(description = "负责人id") + @TableField("owner_user_id") + private Long ownerUserId; + + @Schema(description = "负责人用户名") + @TableField("owner_username") + private String ownerUsername; + + @Schema(description = "监控元数据") + @TableField("monitor_meta") + private String monitorMeta; + + @Schema(description = "监控配置") + @TableField("monitor_config") + private String monitorConfig; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/domain/MonitorMetricsDO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/domain/MonitorMetricsDO.java new file mode 100644 index 00000000..01b6cd6f --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/domain/MonitorMetricsDO.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.dromara.visor.framework.mybatis.core.domain.BaseDO; + +/** + * 监控指标 实体对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName(value = "monitor_metrics", autoResultMap = true) +@Schema(name = "MonitorMetricsDO", description = "监控指标 实体对象") +public class MonitorMetricsDO extends BaseDO { + + private static final long serialVersionUID = 1L; + + @Schema(description = "指标名称") + @TableField("name") + private String name; + + @Schema(description = "数据集") + @TableField("measurement") + private String measurement; + + @Schema(description = "指标项") + @TableField("value") + private String value; + + @Schema(description = "单位") + @TableField("unit") + private String unit; + + @Schema(description = "后缀") + @TableField("suffix") + private String suffix; + + @Schema(description = "指标描述") + @TableField("description") + private String description; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/HostMetaDTO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/HostMetaDTO.java new file mode 100644 index 00000000..0a40a6e1 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/HostMetaDTO.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 主机元数据 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/11 22:01 + */ +@Data +public class HostMetaDTO implements Serializable { + + /** + * CPU 列表 + */ + private List cpus; + + /** + * 磁盘名称列表 + */ + private List disks; + + /** + * 网卡名称列表 + */ + private List nets; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MetricsDTO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MetricsDTO.java new file mode 100644 index 00000000..9419ca0c --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MetricsDTO.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.dto; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 指标信息 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/11 22:00 + */ +@Data +public class MetricsDTO implements Serializable { + + /** + * 指标类型 + */ + private String type; + + /** + * 标签 + */ + private Map tags; + + /** + * 指标值 + */ + private JSONObject values; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MetricsDataDTO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MetricsDataDTO.java new file mode 100644 index 00000000..3d7a81a9 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MetricsDataDTO.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 指标数据 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/11 21:59 + */ +@Data +public class MetricsDataDTO implements Serializable { + + /** + * 时间戳 + */ + private Long timestamp; + + /** + * 指标 + */ + private List metrics; + +} + diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorHostConfigDTO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorHostConfigDTO.java new file mode 100644 index 00000000..b1e4ec16 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorHostConfigDTO.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 监控配置业务对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/13 23:34 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostConfigDTO", description = "监控配置业务对象") +public class MonitorHostConfigDTO implements Serializable { + + @Schema(description = "cpu索引名称") + private String cpuName; + + @Schema(description = "磁盘名称") + private String diskName; + + @Schema(description = "网卡名称") + private String networkName; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorHostMetaDTO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorHostMetaDTO.java new file mode 100644 index 00000000..a240c225 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorHostMetaDTO.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 监控元数据业务对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/13 23:34 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostMetaDTO", description = "监控元数据业务对象") +public class MonitorHostMetaDTO implements Serializable { + + @Schema(description = "cpu") + private List cpus; + + @Schema(description = "磁盘") + private List disks; + + @Schema(description = "网卡") + private List nets; + + @Schema(description = "内存大小") + private Long memoryBytes; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorMetricsCacheDTO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorMetricsCacheDTO.java new file mode 100644 index 00000000..acf2aec2 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/dto/MonitorMetricsCacheDTO.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.dto; + +import cn.orionsec.kit.lang.define.cache.key.model.LongCacheIdModel; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * 监控指标 缓存对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorMetricsCacheDTO", description = "监控指标 缓存对象") +public class MonitorMetricsCacheDTO implements LongCacheIdModel, Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "指标名称") + private String name; + + @Schema(description = "数据集") + private String measurement; + + @Schema(description = "指标项") + private String value; + + @Schema(description = "单位") + private String unit; + + @Schema(description = "后缀") + private String suffix; + + @Schema(description = "指标描述") + private String description; + + @Schema(description = "创建时间") + private Date createTime; + + @Schema(description = "修改时间") + private Date updateTime; + + @Schema(description = "创建人") + private String creator; + + @Schema(description = "修改人") + private String updater; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostAgentConfigUpdateRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostAgentConfigUpdateRequest.java new file mode 100644 index 00000000..0a5bc583 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostAgentConfigUpdateRequest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 监控主机配置更新请求 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/13 23:34 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostAgentConfigUpdateRequest", description = "监控主机配置更新请求") +public class MonitorHostAgentConfigUpdateRequest implements Serializable { + + @Schema(description = "cpu索引名称") + private String cpuName; + + @Schema(description = "磁盘名称") + private String diskName; + + @Schema(description = "网卡名称") + private String networkName; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostChartRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostChartRequest.java new file mode 100644 index 00000000..a16903db --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostChartRequest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.visor.common.entity.BaseQueryRequest; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * 监控主机图表 查询请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(name = "MonitorHostChartRequest", description = "监控主机图表 查询请求对象") +public class MonitorHostChartRequest extends BaseQueryRequest { + + @NotEmpty + @Schema(description = "agentKey") + private List agentKeys; + + @NotBlank + @Schema(description = "表") + private String measurement; + + @NotEmpty + @Schema(description = "字段") + private List fields; + + @NotBlank + @Schema(description = "时间窗口") + private String window; + + @NotBlank + @Schema(description = "聚合参数") + private String aggregate; + + @Schema(description = "聚合参数") + private Long start; + + @Schema(description = "聚合参数") + private Long end; + + @Schema(description = "区间") + private String range; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostMetaSyncRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostMetaSyncRequest.java new file mode 100644 index 00000000..542baf81 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostMetaSyncRequest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 监控主机 同步元数据请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostMetaSyncRequest", description = "监控主机 同步元数据请求对象") +public class MonitorHostMetaSyncRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @Schema(description = "hostId") + private Long hostId; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostQueryRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostQueryRequest.java new file mode 100644 index 00000000..d920e405 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostQueryRequest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.visor.common.entity.BaseQueryRequest; +import org.dromara.visor.common.validator.group.Key; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.util.List; + +/** + * 监控主机 查询请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(name = "MonitorHostQueryRequest", description = "监控主机 查询请求对象") +public class MonitorHostQueryRequest extends BaseQueryRequest { + + @NotEmpty(groups = Key.class) + @Schema(description = "agentKey") + private List agentKeyList; + + @Schema(description = "搜索") + private String searchValue; + + @Schema(description = "告警开关") + private Integer alarmSwitch; + + @Schema(description = "策略id") + private Long policyId; + + @Schema(description = "负责人id") + private Long ownerUserId; + + @Size(max = 64) + @Schema(description = "主机名称") + private String name; + + @Size(max = 64) + @Schema(description = "主机编码") + private String code; + + @Size(max = 128) + @Schema(description = "主机地址") + private String address; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + + @Size(max = 255) + @Schema(description = "描述") + private String description; + + @Schema(description = "tag") + private List tags; + + @Schema(description = "是否查询分组信息") + private Boolean queryGroup; + + @Schema(description = "是否查询 tag 信息") + private Boolean queryTag; + + @Schema(description = "是否查询规格信息") + private Boolean querySpec; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostSwitchUpdateRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostSwitchUpdateRequest.java new file mode 100644 index 00000000..1a4b2453 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostSwitchUpdateRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 监控主机 更新告警开关请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostSwitchUpdateRequest", description = "监控主机 更新告警开关请求对象") +public class MonitorHostSwitchUpdateRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @Schema(description = "id") + private Long id; + + @NotNull + @Schema(description = "告警开关") + private Integer alarmSwitch; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostUpdatePolicyRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostUpdatePolicyRequest.java new file mode 100644 index 00000000..8586f0c7 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostUpdatePolicyRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 监控主机 更新策略请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostUpdatePolicyRequest", description = "监控主机 更新策略请求对象") +public class MonitorHostUpdatePolicyRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @Schema(description = "id") + private Long id; + + @NotNull + @Schema(description = "策略id") + private Long policyId; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostUpdateRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostUpdateRequest.java new file mode 100644 index 00000000..af90a9eb --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/host/MonitorHostUpdateRequest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.host; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * 监控主机 更新请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostUpdateRequest", description = "监控主机 更新请求对象") +public class MonitorHostUpdateRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @Schema(description = "id") + private Long id; + + @Schema(description = "策略id") + private Long policyId; + + @Schema(description = "告警开关") + private Integer alarmSwitch; + + @Schema(description = "负责人id") + private Long ownerUserId; + + @Schema(description = "负责人用户名") + private String ownerUsername; + + @Schema(description = "元数据-cpu索引名称") + private String cpuName; + + @Schema(description = "元数据-磁盘名称") + private String diskName; + + @Schema(description = "元数据-网卡名称") + private String networkName; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsCreateRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsCreateRequest.java new file mode 100644 index 00000000..27ab3300 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsCreateRequest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.metrics; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + * 监控指标 创建请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorMetricsCreateRequest", description = "监控指标 创建请求对象") +public class MonitorMetricsCreateRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotBlank + @Size(max = 64) + @Schema(description = "指标名称") + private String name; + + @NotBlank + @Size(max = 64) + @Schema(description = "数据集") + private String measurement; + + @NotBlank + @Size(max = 128) + @Schema(description = "指标项") + private String value; + + @NotBlank + @Size(max = 8) + @Schema(description = "单位") + private String unit; + + @Size(max = 32) + @Schema(description = "后缀") + private String suffix; + + @Size(max = 128) + @Schema(description = "指标描述") + private String description; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsQueryRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsQueryRequest.java new file mode 100644 index 00000000..10c6296c --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsQueryRequest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.metrics; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import org.dromara.visor.common.entity.BaseQueryRequest; + +import javax.validation.constraints.Size; + +/** + * 监控指标 查询请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Schema(name = "MonitorMetricsQueryRequest", description = "监控指标 查询请求对象") +public class MonitorMetricsQueryRequest extends BaseQueryRequest { + + @Size(max = 64) + @Schema(description = "指标名称") + private String name; + + @Size(max = 64) + @Schema(description = "数据集") + private String measurement; + + @Size(max = 128) + @Schema(description = "指标项") + private String value; + + @Size(max = 8) + @Schema(description = "单位") + private String unit; + + @Size(max = 32) + @Schema(description = "后缀") + private String suffix; + + @Size(max = 128) + @Schema(description = "指标描述") + private String description; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsUpdateRequest.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsUpdateRequest.java new file mode 100644 index 00000000..d81a0bff --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/request/metrics/MonitorMetricsUpdateRequest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.request.metrics; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + * 监控指标 更新请求对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorMetricsUpdateRequest", description = "监控指标 更新请求对象") +public class MonitorMetricsUpdateRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @Schema(description = "id") + private Long id; + + @NotBlank + @Size(max = 64) + @Schema(description = "指标名称") + private String name; + + @NotBlank + @Size(max = 64) + @Schema(description = "数据集") + private String measurement; + + @NotBlank + @Size(max = 128) + @Schema(description = "指标项") + private String value; + + @NotBlank + @Size(max = 8) + @Schema(description = "单位") + private String unit; + + @Size(max = 32) + @Schema(description = "后缀") + private String suffix; + + @Size(max = 128) + @Schema(description = "指标描述") + private String description; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorHostMetricsDataVO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorHostMetricsDataVO.java new file mode 100644 index 00000000..965313de --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorHostMetricsDataVO.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 监控主机指标数据 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/15 16:34 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostMetricsDataVO", description = "监控主机指标数据 视图响应对象") +public class MonitorHostMetricsDataVO { + + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "是否无数据") + private Boolean noData; + + @Schema(description = "采集时间") + private Long timestamp; + + @Schema(description = "cpu名称") + private String cpuName; + + @Schema(description = "磁盘名称") + private String diskName; + + @Schema(description = "网卡名称") + private String networkName; + + @Schema(description = "cpu 使用率") + private Double cpuUsagePercent; + + @Schema(description = "内存使用率") + private Double memoryUsagePercent; + + @Schema(description = "内存使用量") + private Long memoryUsageBytes; + + @Schema(description = "load1") + private Double load1; + + @Schema(description = "load5") + private Double load5; + + @Schema(description = "load15") + private Double load15; + + @Schema(description = "磁盘使用率") + private Double diskUsagePercent; + + @Schema(description = "磁盘使用量") + private Long diskUsageBytes; + + @Schema(description = "网卡上行带宽速度") + private Double networkSentPreBytes; + + @Schema(description = "网卡下行带宽速度") + private Double networkRecvPreBytes; + + public static MonitorHostMetricsDataVO noData(String agentKey) { + return MonitorHostMetricsDataVO.builder() + .noData(true) + .agentKey(agentKey) + .build(); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorHostVO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorHostVO.java new file mode 100644 index 00000000..320bd34b --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorHostVO.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dromara.visor.module.asset.entity.dto.host.HostAgentLogDTO; +import org.dromara.visor.module.infra.entity.dto.tag.TagDTO; +import org.dromara.visor.module.monitor.entity.dto.MonitorHostConfigDTO; +import org.dromara.visor.module.monitor.entity.dto.MonitorHostMetaDTO; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 监控主机 视图响应对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorHostVO", description = "监控主机 视图响应对象") +public class MonitorHostVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "主机id") + private Long hostId; + + @Schema(description = "策略id") + private Long policyId; + + @Schema(description = "策略名称") + private String policyName; + + @Schema(description = "系统类型") + private String osType; + + @Schema(description = "主机名称") + private String name; + + @Schema(description = "主机编码") + private String code; + + @Schema(description = "主机地址") + private String address; + + @Schema(description = "主机状态") + private String status; + + @Schema(description = "agentKey") + private String agentKey; + + @Schema(description = "探针版本") + private String agentVersion; + + @Schema(description = "最新版本") + private String latestVersion; + + @Schema(description = "探针安装状态") + private Integer agentInstallStatus; + + @Schema(description = "探针在线状态") + private Integer agentOnlineStatus; + + @Schema(description = "上次切换在线状态时间") + private Date lastChangeOnlineTime; + + @Schema(description = "告警开关") + private Integer alarmSwitch; + + @Schema(description = "负责人id") + private Long ownerUserId; + + @Schema(description = "负责人用户名") + private String ownerUsername; + + @Schema(description = "tags") + private List tags; + + @Schema(description = "监控元数据") + private MonitorHostMetaDTO meta; + + @Schema(description = "监控配置") + private MonitorHostConfigDTO config; + + @Schema(description = "监控数据") + private MonitorHostMetricsDataVO metricsData; + + @Schema(description = "安装日志") + private HostAgentLogDTO installLog; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorMetricsVO.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorMetricsVO.java new file mode 100644 index 00000000..be2b0dbb --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/entity/vo/MonitorMetricsVO.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * 监控指标 视图响应对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "MonitorMetricsVO", description = "监控指标 视图响应对象") +public class MonitorMetricsVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "指标名称") + private String name; + + @Schema(description = "数据集") + private String measurement; + + @Schema(description = "指标项") + private String value; + + @Schema(description = "单位") + private String unit; + + @Schema(description = "后缀") + private String suffix; + + @Schema(description = "指标描述") + private String description; + + @Schema(description = "创建时间") + private Date createTime; + + @Schema(description = "修改时间") + private Date updateTime; + + @Schema(description = "创建人") + private String creator; + + @Schema(description = "修改人") + private String updater; + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MeasurementFieldEnum.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MeasurementFieldEnum.java new file mode 100644 index 00000000..c8936655 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MeasurementFieldEnum.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.enums; + +import lombok.Getter; +import org.apache.commons.collections4.map.HashedMap; +import org.dromara.visor.module.monitor.constant.MetricsConst; + +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * 指标度量类型 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/14 10:27 + */ +@Getter +public enum MeasurementFieldEnum { + + /** + * cpu + */ + CPU("cpu", (s) -> { + s.accept(MetricsConst.CPU_USER_SECONDS_TOTAL, double.class); + s.accept(MetricsConst.CPU_SYSTEM_SECONDS_TOTAL, double.class); + s.accept(MetricsConst.CPU_TOTAL_SECONDS_TOTAL, double.class); + }), + + /** + * 内存 + */ + MEMORY("memory", s -> { + s.accept(MetricsConst.MEM_USED_BYTES_TOTAL, long.class); + s.accept(MetricsConst.MEM_USED_PERCENT, double.class); + s.accept(MetricsConst.MEM_SWAP_USED_BYTES_TOTAL, long.class); + s.accept(MetricsConst.MEM_SWAP_USED_PERCENT, double.class); + }), + + /** + * 负载 + */ + LOAD("load", s -> { + s.accept(MetricsConst.LOAD1, double.class); + s.accept(MetricsConst.LOAD5, double.class); + s.accept(MetricsConst.LOAD15, double.class); + s.accept(MetricsConst.LOAD1_CORE_RATIO, double.class); + s.accept(MetricsConst.LOAD5_CORE_RATIO, double.class); + s.accept(MetricsConst.LOAD15_CORE_RATIO, double.class); + }), + + /** + * 磁盘 + */ + DISK("disk", s -> { + s.accept(MetricsConst.DISK_FS_USED_BYTES_TOTAL, long.class); + s.accept(MetricsConst.DISK_FS_USED_PERCENT, double.class); + s.accept(MetricsConst.DISK_FS_INODES_USED_PERCENT, double.class); + }), + + /** + * io + */ + IO("io", s -> { + s.accept(MetricsConst.DISK_IO_READ_BYTES_TOTAL, long.class); + s.accept(MetricsConst.DISK_IO_WRITE_BYTES_TOTAL, long.class); + s.accept(MetricsConst.DISK_IO_READS_TOTAL, long.class); + s.accept(MetricsConst.DISK_IO_WRITES_TOTAL, long.class); + s.accept(MetricsConst.DISK_IO_READ_BYTES_PER_SECOND, double.class); + s.accept(MetricsConst.DISK_IO_WRITE_BYTES_PER_SECOND, double.class); + s.accept(MetricsConst.DISK_IO_READS_PER_SECOND, double.class); + s.accept(MetricsConst.DISK_IO_WRITES_PER_SECOND, double.class); + }), + + /** + * 网络 + */ + NETWORK("network", s -> { + s.accept(MetricsConst.NET_SENT_BYTES_TOTAL, long.class); + s.accept(MetricsConst.NET_RECV_BYTES_TOTAL, long.class); + s.accept(MetricsConst.NET_SENT_PACKETS_TOTAL, long.class); + s.accept(MetricsConst.NET_RECV_PACKETS_TOTAL, long.class); + s.accept(MetricsConst.NET_SENT_BYTES_PER_SECOND, double.class); + s.accept(MetricsConst.NET_RECV_BYTES_PER_SECOND, double.class); + s.accept(MetricsConst.NET_SENT_PACKETS_PER_SECOND, double.class); + s.accept(MetricsConst.NET_RECV_PACKETS_PER_SECOND, double.class); + }), + + /** + * 连接数 + */ + CONNECTIONS("connections", s -> { + s.accept(MetricsConst.NET_TCP_CONNECTIONS, int.class); + s.accept(MetricsConst.NET_UDP_CONNECTIONS, int.class); + s.accept(MetricsConst.NET_INET_CONNECTIONS, int.class); + s.accept(MetricsConst.NET_ALL_CONNECTIONS, int.class); + }), + + ; + + private final String measurement; + private final Map> fields; + + MeasurementFieldEnum(String measurement, Consumer>> register) { + this.measurement = measurement; + this.fields = new HashedMap<>(); + register.accept(this.fields::put); + } + + public static MeasurementFieldEnum of(String measurement) { + if (measurement == null) { + return null; + } + for (MeasurementFieldEnum e : values()) { + if (e.measurement.equals(measurement)) { + return e; + } + } + return null; + } + + /** + * 获取度量值类型 + * + * @param measurement measurement + * @param field field + * @return type + */ + public static Class getMetricsValueType(String measurement, String field) { + MeasurementFieldEnum m = of(measurement); + if (m == null) { + return null; + } + return m.getFields().get(field); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MetricsAggregateEnum.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MetricsAggregateEnum.java new file mode 100644 index 00000000..edc58079 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MetricsAggregateEnum.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 监控指标聚合函数 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/14 10:15 + */ +@Getter +@AllArgsConstructor +public enum MetricsAggregateEnum { + + /** + * 平均值 + */ + MEAN("mean"), + + /** + * 最大值 + */ + MAX("max"), + + /** + * 最小值 + */ + MIN("min"), + + /** + * 总和 + */ + SUM("sum"), + + ; + + private final String fn; + + public static MetricsAggregateEnum of(String fn) { + if (fn == null) { + return MEAN; + } + for (MetricsAggregateEnum e : values()) { + if (e.fn.equals(fn)) { + return e; + } + } + return MEAN; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MetricsUnitEnum.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MetricsUnitEnum.java new file mode 100644 index 00000000..dd6fed4a --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MetricsUnitEnum.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.enums; + +/** + * 指标单位枚举 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/14 10:15 + */ +public enum MetricsUnitEnum { + + /** + * 字节 + */ + BYTES, + + /** + * 比特 + */ + BITS, + + /** + * 次 + */ + COUNT, + + /** + * 秒 + */ + SECONDS, + + /** + * 百分比 + */ + PER, + + /** + * 字节/秒 + */ + BYTES_S, + + /** + * 比特/秒 + */ + BITS_S, + + /** + * 次/秒 + */ + COUNT_S, + + /** + * 文本 + */ + TEXT, + + /** + * 无 + */ + NONE, + + ; + + public static MetricsUnitEnum of(String name) { + if (name == null) { + return NONE; + } + for (MetricsUnitEnum unit : values()) { + if (unit.name().equals(name)) { + return unit; + } + } + return NONE; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MonitorAlarmSwitchEnum.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MonitorAlarmSwitchEnum.java new file mode 100644 index 00000000..6d6f50e4 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/enums/MonitorAlarmSwitchEnum.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 监控告警开关枚举 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/14 11:23 + */ +@Getter +@AllArgsConstructor +public enum MonitorAlarmSwitchEnum { + + /** + * 关闭 + */ + OFF(0), + + /** + * 开启 + */ + ON(1), + + ; + + private final Integer value; + + public static MonitorAlarmSwitchEnum of(Integer value) { + if (value == null) { + return OFF; + } + for (MonitorAlarmSwitchEnum e : MonitorAlarmSwitchEnum.values()) { + if (value.equals(e.value)) { + return e; + } + } + return OFF; + } + + /** + * 是否开启 + * + * @param value value + * @return on + */ + public static boolean isOn(Integer value) { + return ON.value.equals(value); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorAgentEndpointService.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorAgentEndpointService.java new file mode 100644 index 00000000..8bfe4dc5 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorAgentEndpointService.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.service; + +import org.dromara.visor.module.monitor.entity.dto.HostMetaDTO; +import org.dromara.visor.module.monitor.entity.dto.MetricsDataDTO; + +/** + * 监控探针端点 服务类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 14:42 + */ +public interface MonitorAgentEndpointService { + + /** + * 添加监控指标 + * + * @param agentKey agentKey + * @param data data + */ + void addMetrics(String agentKey, MetricsDataDTO data); + + /** + * 上线时同步元数据 + * + * @param agentKey agentKey + * @param meta meta + */ + void syncHostMeta(String agentKey, HostMetaDTO meta); + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorHostService.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorHostService.java new file mode 100644 index 00000000..f998bd7b --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorHostService.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.service; + +import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import org.dromara.visor.common.entity.chart.TimeChartSeries; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostChartRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostQueryRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostSwitchUpdateRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostMetricsDataVO; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO; + +import java.util.List; + +/** + * 监控主机 服务类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +public interface MonitorHostService { + + /** + * 分页查询监控主机 + * + * @param request request + * @return rows + */ + DataGrid getMonitorHostPage(MonitorHostQueryRequest request); + + /** + * 获取监控主机指标数据 + * + * @param agentKeyList agentKeyList + * @return metrics + */ + List getMonitorHostMetrics(List agentKeyList); + + /** + * 获取监控主机图表数据 + * + * @param request request + * @return series + */ + List getMonitorHostChart(MonitorHostChartRequest request); + + /** + * 更新监控主机 + * + * @param request request + * @return effect + */ + Integer updateMonitorHostById(MonitorHostUpdateRequest request); + + /** + * 更新监控主机告警开关 + * + * @param request request + * @return effect + */ + Integer updateMonitorHostAlarmSwitch(MonitorHostSwitchUpdateRequest request); + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorMetricsService.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorMetricsService.java new file mode 100644 index 00000000..6d57af05 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/MonitorMetricsService.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.service; + +import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.dromara.visor.module.monitor.entity.domain.MonitorMetricsDO; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsCreateRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsQueryRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorMetricsVO; + +import java.util.List; + +/** + * 监控指标 服务类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +public interface MonitorMetricsService { + + /** + * 创建监控指标 + * + * @param request request + * @return id + */ + Long createMonitorMetrics(MonitorMetricsCreateRequest request); + + /** + * 更新监控指标 + * + * @param request request + * @return effect + */ + Integer updateMonitorMetricsById(MonitorMetricsUpdateRequest request); + + /** + * 通过缓存查询监控指标 + * + * @return rows + */ + List getMonitorMetricsList(); + + /** + * 分页查询监控指标 + * + * @param request request + * @return rows + */ + DataGrid getMonitorMetricsPage(MonitorMetricsQueryRequest request); + + /** + * 通过值获取监控指标名称 + * + * @param value value + * @return name + */ + String getMetricName(String value); + + /** + * 删除监控指标 + * + * @param id id + * @return effect + */ + Integer deleteMonitorMetricsById(Long id); + + /** + * 批量删除监控指标 + * + * @param idList idList + * @return effect + */ + Integer deleteMonitorMetricsByIdList(List idList); + + /** + * 构建查询 wrapper + * + * @param request request + * @return wrapper + */ + LambdaQueryWrapper buildQueryWrapper(MonitorMetricsQueryRequest request); + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorAgentEndpointServiceImpl.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorAgentEndpointServiceImpl.java new file mode 100644 index 00000000..bb50261d --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorAgentEndpointServiceImpl.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.service.impl; + +import cn.orionsec.kit.lang.able.Executable; +import cn.orionsec.kit.lang.utils.Strings; +import cn.orionsec.kit.lang.utils.collect.Lists; +import cn.orionsec.kit.lang.utils.collect.Maps; +import com.alibaba.fastjson.JSON; +import com.influxdb.client.domain.WritePrecision; +import com.influxdb.client.write.Point; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; +import org.dromara.visor.common.utils.LockerUtils; +import org.dromara.visor.common.utils.Valid; +import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils; +import org.dromara.visor.module.asset.api.HostApi; +import org.dromara.visor.module.asset.entity.dto.host.HostDTO; +import org.dromara.visor.module.infra.api.SystemUserApi; +import org.dromara.visor.module.monitor.dao.MonitorHostDAO; +import org.dromara.visor.module.monitor.define.context.MonitorContext; +import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO; +import org.dromara.visor.module.monitor.entity.dto.HostMetaDTO; +import org.dromara.visor.module.monitor.entity.dto.MetricsDataDTO; +import org.dromara.visor.module.monitor.entity.dto.MonitorHostConfigDTO; +import org.dromara.visor.module.monitor.enums.MonitorAlarmSwitchEnum; +import org.dromara.visor.module.monitor.service.MonitorAgentEndpointService; +import org.dromara.visor.module.monitor.utils.MetricsUtils; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 监控探针端点 服务实现类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/22 14:42 + */ +@Slf4j +@Service +public class MonitorAgentEndpointServiceImpl implements MonitorAgentEndpointService { + + private static final String LOCK_KEY_PREFIX = "monitor:online:"; + + @Resource + private MonitorHostDAO monitorHostDAO; + + @Resource + private HostApi hostApi; + + @Resource + private SystemUserApi systemUserApi; + + @Resource + private MonitorContext monitorContext; + + @Override + @Async("metricsExecutor") + public void addMetrics(String agentKey, MetricsDataDTO data) { + log.info("MonitorAgentEndpointService.addMetrics start agentKey: {}", agentKey); + // 设置数据缓存 + monitorContext.setAgentMetrics(agentKey, data); + // 数据点 + List points = data.getMetrics() + .stream() + .map(s -> MetricsUtils.createPoint(s.getType(), s.getValues()) + .addTag(Const.KEY, agentKey) + .addTags(Maps.def(s.getTags(), Maps.empty())) + .time(data.getTimestamp(), WritePrecision.MS)) + .collect(Collectors.toList()); + // 写入数据点 + InfluxdbUtils.writePoints(points); + // TODO 告警 + + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void syncHostMeta(String agentKey, HostMetaDTO meta) { + // 同步逻辑 + Executable exec = () -> { + // 查询主机是否存在 + HostDTO host = hostApi.selectByAgentKey(agentKey); + Valid.notNull(host, ErrorMessage.HOST_ABSENT); + // 查询数据 + MonitorHostDO monitorHost = monitorHostDAO.selectByAgentKey(agentKey); + MonitorHostConfigDTO newConfig = null; + if (monitorHost == null) { + // 不存在则新增 + newConfig = this.getDefaultMonitorConfig(meta); + monitorHost = MonitorHostDO.builder() + .hostId(host.getId()) + .agentKey(agentKey) + .alarmSwitch(MonitorAlarmSwitchEnum.OFF.getValue()) + .monitorMeta(JSON.toJSONString(meta)) + .monitorConfig(JSON.toJSONString(newConfig)) + .creator(host.getCreator()) + .updater(host.getCreator()) + .build(); + // 设置负责人信息 + Long userId = systemUserApi.getIdByUsername(host.getCreator()); + if (userId != null) { + monitorHost.setOwnerUserId(userId); + monitorHost.setOwnerUsername(host.getCreator()); + } + monitorHostDAO.insert(monitorHost); + } else { + // 更新数据 + MonitorHostDO update = new MonitorHostDO(); + update.setId(monitorHost.getId()); + update.setMonitorMeta(JSON.toJSONString(meta)); + // 设置默认配置 + if (Strings.isBlank(monitorHost.getMonitorConfig())) { + newConfig = this.getDefaultMonitorConfig(meta); + update.setMonitorConfig(JSON.toJSONString(newConfig)); + } + monitorHostDAO.updateById(update); + } + // 设置配置缓存 + if (newConfig != null) { + monitorContext.setMonitorHostConfig(agentKey, newConfig); + } + }; + // 获取锁并执行同步逻辑 + LockerUtils.lockExecute(LOCK_KEY_PREFIX + agentKey, Const.MS_S_10, exec); + } + + /** + * 获取默认监控配置 + * + * @param meta meta + * @return config + */ + private MonitorHostConfigDTO getDefaultMonitorConfig(HostMetaDTO meta) { + return MonitorHostConfigDTO.builder() + .cpuName(Lists.first(meta.getCpus())) + .diskName(Lists.first(meta.getDisks())) + .networkName(Lists.first(meta.getNets())) + .build(); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorHostServiceImpl.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorHostServiceImpl.java new file mode 100644 index 00000000..a87abc60 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorHostServiceImpl.java @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.service.impl; + +import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import cn.orionsec.kit.lang.function.Functions; +import cn.orionsec.kit.lang.utils.Objects1; +import cn.orionsec.kit.lang.utils.Strings; +import cn.orionsec.kit.lang.utils.collect.Lists; +import cn.orionsec.kit.lang.utils.collect.Maps; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; +import org.dromara.visor.common.constant.ExtraFieldConst; +import org.dromara.visor.common.entity.chart.TimeChartSeries; +import org.dromara.visor.common.utils.Valid; +import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; +import org.dromara.visor.framework.influxdb.core.query.FluxQueryBuilder; +import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils; +import org.dromara.visor.module.asset.api.HostAgentApi; +import org.dromara.visor.module.asset.api.HostApi; +import org.dromara.visor.module.asset.entity.dto.host.HostAgentLogDTO; +import org.dromara.visor.module.asset.entity.dto.host.HostDTO; +import org.dromara.visor.module.asset.entity.dto.host.HostQueryDTO; +import org.dromara.visor.module.asset.enums.AgentOnlineStatusEnum; +import org.dromara.visor.module.infra.api.SystemUserApi; +import org.dromara.visor.module.monitor.constant.MetricsConst; +import org.dromara.visor.module.monitor.convert.MonitorHostConvert; +import org.dromara.visor.module.monitor.dao.MonitorHostDAO; +import org.dromara.visor.module.monitor.define.context.MonitorContext; +import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO; +import org.dromara.visor.module.monitor.entity.dto.MetricsDTO; +import org.dromara.visor.module.monitor.entity.dto.MetricsDataDTO; +import org.dromara.visor.module.monitor.entity.dto.MonitorHostConfigDTO; +import org.dromara.visor.module.monitor.entity.dto.MonitorHostMetaDTO; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostChartRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostQueryRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostSwitchUpdateRequest; +import org.dromara.visor.module.monitor.entity.request.host.MonitorHostUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostMetricsDataVO; +import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO; +import org.dromara.visor.module.monitor.enums.MeasurementFieldEnum; +import org.dromara.visor.module.monitor.enums.MonitorAlarmSwitchEnum; +import org.dromara.visor.module.monitor.service.MonitorHostService; +import org.dromara.visor.module.monitor.service.MonitorMetricsService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 监控主机 服务实现类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-14 16:27 + */ +@Slf4j +@Service +public class MonitorHostServiceImpl implements MonitorHostService { + + @Resource + private MonitorHostDAO monitorHostDAO; + + @Resource + private HostApi hostApi; + + @Resource + private HostAgentApi hostAgentApi; + + @Resource + private SystemUserApi systemUserApi; + + @Resource + private MonitorMetricsService monitorMetricsService; + + @Resource + private MonitorContext monitorContext; + + @Override + public DataGrid getMonitorHostPage(MonitorHostQueryRequest request) { + // 转换查询条件 + HostQueryDTO hostQuery = MonitorHostConvert.MAPPER.toHostQuery(request); + hostQuery.setQueryTag(true); + hostQuery.setOrderByAgent(true); + List monitorHosts = null; + // 查询监控主机数据 + Integer alarmSwitch = request.getAlarmSwitch(); + Long ownerUserId = request.getOwnerUserId(); + Long policyId = request.getPolicyId(); + if (!Objects1.isAllNull(alarmSwitch, ownerUserId, policyId)) { + monitorHosts = monitorHostDAO.of() + .createValidateWrapper() + .eq(MonitorHostDO::getAlarmSwitch, alarmSwitch) + .eq(MonitorHostDO::getOwnerUserId, ownerUserId) + .eq(MonitorHostDO::getPolicyId, policyId) + .then() + .list(); + if (monitorHosts.isEmpty()) { + return new DataGrid<>(); + } + hostQuery.setIdList(Lists.map(monitorHosts, MonitorHostDO::getHostId)); + } + // 查询主机 + DataGrid hosts = hostApi.getHostPage(hostQuery); + if (hosts.isEmpty()) { + return new DataGrid<>(Lists.empty(), hosts.getTotal()); + } + List hostIdList = hosts.stream() + .map(HostDTO::getId) + .collect(Collectors.toList()); + // 若未查询过监控主机表则查询 + if (monitorHosts == null) { + monitorHosts = monitorHostDAO.selectByHostIdList(hostIdList); + } + Map monitorHostMap = monitorHosts.stream() + .collect(Collectors.toMap(MonitorHostDO::getHostId, + Function.identity(), + Functions.right())); + // TODO 查询策略名称 + + // 查询安装日志 + Map agentInstallLogMap = hostAgentApi.selectAgentInstallLog(hostIdList) + .stream() + .collect(Collectors.toMap(HostAgentLogDTO::getHostId, + Function.identity(), + Functions.right())); + String latestVersion = hostAgentApi.getAgentVersion(); + // 给主机进行赋值 + return hosts.map(s -> { + MonitorHostVO vo = MonitorHostConvert.MAPPER.to(s); + // 设置监控信息 + MonitorHostDO monitorHost = monitorHostMap.get(s.getId()); + if (monitorHost != null) { + vo.setId(monitorHost.getId()); + vo.setPolicyId(monitorHost.getPolicyId()); + vo.setAlarmSwitch(monitorHost.getAlarmSwitch()); + vo.setOwnerUserId(monitorHost.getOwnerUserId()); + vo.setOwnerUsername(monitorHost.getOwnerUsername()); + // 反序列化元数据 + vo.setMeta(JSON.parseObject(monitorHost.getMonitorMeta(), MonitorHostMetaDTO.class)); + // 反序列化配置 + vo.setConfig(JSON.parseObject(monitorHost.getMonitorConfig(), MonitorHostConfigDTO.class)); + } + // 设置安装日志 + vo.setInstallLog(agentInstallLogMap.get(s.getId())); + // 设置最新版本 + vo.setLatestVersion(latestVersion); + // 设置指标信息 + if (AgentOnlineStatusEnum.ONLINE.getValue().equals(vo.getAgentOnlineStatus())) { + vo.setMetricsData(this.getHostMetricsData(vo.getAgentKey(), vo.getConfig())); + } else { + vo.setMetricsData(MonitorHostMetricsDataVO.noData(vo.getAgentKey())); + } + return vo; + }); + } + + @Override + public List getMonitorHostMetrics(List agentKeyList) { + return agentKeyList.stream() + .map(s -> this.getHostMetricsData(s, null)) + .collect(Collectors.toList()); + } + + @Override + public List getMonitorHostChart(MonitorHostChartRequest request) { + List agentKeys = request.getAgentKeys(); + List fields = request.getFields(); + List seriesList = this.getChartSeries(request); + // 查询 agentKey 对应的名称 + Map cacheNameByAgentKey = hostAgentApi.getCacheNameByAgentKey(agentKeys); + // 封装数据 + for (TimeChartSeries series : seriesList) { + Map tags = series.getTags(); + Map sortedTags = new LinkedHashMap<>(); + String key = (String) tags.get(Const.KEY); + String field = monitorMetricsService.getMetricName((String) tags.get(Const.FIELD)); + tags.remove(Const.KEY); + tags.remove(Const.FIELD); + // 设置主机名称 + if (agentKeys.size() > 1) { + sortedTags.put(ExtraFieldConst.HOST_NAME, cacheNameByAgentKey.get(key)); + } + // 设置字段 + if (fields.size() > 1) { + sortedTags.put(ExtraFieldConst.FIELD, field); + } + sortedTags.putAll(tags); + // 为空需要添加 field (计算名称) + if (sortedTags.isEmpty()) { + sortedTags.put(ExtraFieldConst.FIELD, field); + } + series.setTags(sortedTags); + // 设置名称 + String name = sortedTags.values() + .stream() + .map(Objects::toString) + .collect(Collectors.joining("-")); + series.setName(name); + } + // 排序指标 + seriesList.sort(Comparator.comparing(TimeChartSeries::getName)); + return seriesList; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer updateMonitorHostById(MonitorHostUpdateRequest request) { + Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING); + Long policyId = request.getPolicyId(); + log.info("MonitorHostService-updateMonitorHostById id: {}, request: {}", id, JSON.toJSONString(request)); + // 查询数据 + MonitorHostDO monitorHost = monitorHostDAO.selectById(id); + Valid.notNull(monitorHost, ErrorMessage.DATA_ABSENT); + // 查询主机信息 + HostDTO host = hostApi.selectById(monitorHost.getHostId()); + Valid.notNull(host, ErrorMessage.HOST_ABSENT); + // 查询用户信息 + Optional.ofNullable(request.getOwnerUserId()) + .map(systemUserApi::getUsernameById) + .ifPresent(request::setOwnerUsername); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.NAME, host.getName()); + // 查询策略是否存在 TODO + if (policyId != null) { + + } + // 转换 + MonitorHostDO updateRecord = MonitorHostConvert.MAPPER.to(request); + // 配置信息 + MonitorHostConfigDTO config = MonitorHostConfigDTO.builder() + .cpuName(request.getCpuName()) + .diskName(request.getDiskName()) + .networkName(request.getNetworkName()) + .build(); + updateRecord.setMonitorConfig(JSON.toJSONString(config)); + // 更新 + int effect = monitorHostDAO.updateById(updateRecord); + // 更新缓存 + monitorContext.setMonitorHostConfig(host.getAgentKey(), config); + log.info("MonitorHostService-updateMonitorHostById effect: {}", effect); + return effect; + } + + @Override + public Integer updateMonitorHostAlarmSwitch(MonitorHostSwitchUpdateRequest request) { + Long id = request.getId(); + MonitorAlarmSwitchEnum alarmSwitch = MonitorAlarmSwitchEnum.of(request.getAlarmSwitch()); + // 查询数据 + MonitorHostDO monitorHost = monitorHostDAO.selectById(id); + Valid.notNull(monitorHost, ErrorMessage.DATA_ABSENT); + // 查询主机信息 + HostDTO host = hostApi.selectById(monitorHost.getHostId()); + Valid.notNull(host, ErrorMessage.HOST_ABSENT); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.NAME, host.getName()); + OperatorLogs.add(OperatorLogs.SWITCH, alarmSwitch.name()); + // 修改数据 + MonitorHostDO update = new MonitorHostDO(); + update.setId(id); + update.setAlarmSwitch(alarmSwitch.getValue()); + int effect = monitorHostDAO.updateById(update); + log.info("MonitorHostService-updateMonitorHostAlarmSwitch effect: {}", effect); + // todo 咋更新缓存 + return effect; + } + + /** + * 查询数据图表 + * + * @param request request + * @return values + */ + private List getChartSeries(MonitorHostChartRequest request) { + String measurement = request.getMeasurement(); + List agentKeys = request.getAgentKeys(); + List fields = request.getFields(); + // 获取配置信息 + List configList = agentKeys.stream() + .map(monitorContext::getMonitorHostConfig) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + // 查询主机信息 + FluxQueryBuilder query = InfluxdbUtils.query(); + // 设置时间 + String range = request.getRange(); + if (range != null) { + query.range(range); + } else { + Valid.notNull(request.getStart(), ErrorMessage.PARAM_MISSING); + Valid.notNull(request.getEnd(), ErrorMessage.PARAM_MISSING); + } + // 设置名称 + Set names = null; + if (MeasurementFieldEnum.CPU.getMeasurement().equals(measurement)) { + names = configList.stream() + .map(MonitorHostConfigDTO::getCpuName) + .collect(Collectors.toSet()); + } else if (MeasurementFieldEnum.DISK.getMeasurement().equals(measurement)) { + names = configList.stream() + .map(MonitorHostConfigDTO::getDiskName) + .collect(Collectors.toSet()); + } else if (MeasurementFieldEnum.NETWORK.getMeasurement().equals(measurement)) { + names = configList.stream() + .map(MonitorHostConfigDTO::getNetworkName) + .collect(Collectors.toSet()); + } + if (!Lists.isEmpty(names)) { + query.name(names); + } + // 设置其他查询条件 + String flux = query.measurement(measurement) + .key(agentKeys) + .fields(fields) + .aggregateWindow(request.getWindow(), request.getAggregate(), true) + .pretty() + .build(); + // 查询数据 + return InfluxdbUtils.querySeries(flux); + } + + /** + * 获取主机指标数据 + * + * @param agentKey agentKey + * @param config config + * @return data + */ + public MonitorHostMetricsDataVO getHostMetricsData(String agentKey, MonitorHostConfigDTO config) { + MetricsDataDTO metrics = monitorContext.getAgentMetrics(agentKey); + // 无数据 + if (metrics == null) { + return MonitorHostMetricsDataVO.noData(agentKey); + } + // 从缓存中获取配置 + if (config == null) { + config = monitorContext.getMonitorHostConfig(agentKey); + } + // 获取名称 + LinkedHashMap metricDefaultNameMap = metrics.getMetrics() + .stream() + .collect(Collectors.toMap( + MetricsDTO::getType, + s -> Strings.def(Maps.get(s.getTags(), Const.NAME)), + Functions.left(), + LinkedHashMap::new)); + String cpuName = Optional.ofNullable(config) + .map(MonitorHostConfigDTO::getCpuName) + .orElse(metricDefaultNameMap.get(MeasurementFieldEnum.CPU.getMeasurement())); + String diskName = Optional.ofNullable(config) + .map(MonitorHostConfigDTO::getDiskName) + .orElse(metricDefaultNameMap.get(MeasurementFieldEnum.DISK.getMeasurement())); + String networkName = Optional.ofNullable(config) + .map(MonitorHostConfigDTO::getNetworkName) + .orElse(metricDefaultNameMap.get(MeasurementFieldEnum.NETWORK.getMeasurement())); + // 指标缓存 + Map metricTypeMap = metrics.getMetrics() + .stream() + .collect(Collectors.toMap( + s -> s.getType() + "_" + Strings.def(Maps.get(s.getTags(), Const.NAME)), + MetricsDTO::getValues, + Functions.right(), + LinkedHashMap::new)); + MonitorHostMetricsDataVO data = MonitorHostMetricsDataVO.builder() + .noData(false) + .agentKey(agentKey) + .cpuName(cpuName) + .diskName(diskName) + .networkName(networkName) + .timestamp(metrics.getTimestamp()) + .build(); + // 组装指标 + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.CPU, + cpuName, MetricsConst.CPU_TOTAL_SECONDS_TOTAL, 0D, + JSONObject::getDouble, + data::setCpuUsagePercent); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.MEMORY, + null, MetricsConst.MEM_USED_BYTES_TOTAL, 0L, + JSONObject::getLong, + data::setMemoryUsageBytes); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.MEMORY, + null, MetricsConst.MEM_USED_PERCENT, 0D, + JSONObject::getDouble, + data::setMemoryUsagePercent); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.LOAD, + null, MetricsConst.LOAD1, 0D, + JSONObject::getDouble, + data::setLoad1); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.LOAD, + null, MetricsConst.LOAD5, 0D, + JSONObject::getDouble, + data::setLoad5); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.LOAD, + null, MetricsConst.LOAD15, 0D, + JSONObject::getDouble, + data::setLoad15); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.DISK, + diskName, MetricsConst.DISK_FS_USED_PERCENT, 0D, + JSONObject::getDouble, + data::setDiskUsagePercent); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.DISK, + diskName, MetricsConst.DISK_FS_USED_BYTES_TOTAL, 0L, + JSONObject::getLong, + data::setDiskUsageBytes); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.NETWORK, + networkName, MetricsConst.NET_SENT_BYTES_PER_SECOND, 0D, + JSONObject::getDouble, + data::setNetworkSentPreBytes); + this.setNamedMetricValue(metricTypeMap, MeasurementFieldEnum.NETWORK, + networkName, MetricsConst.NET_RECV_BYTES_PER_SECOND, 0D, + JSONObject::getDouble, + data::setNetworkRecvPreBytes); + return data; + } + + /** + * 设置指标值 + * + * @param metricTypeMap metricTypeMap + * @param type type + * @param name name + * @param field field + * @param defaultValue defaultValue + * @param getter getter + * @param setter setter + * @param T + */ + private void setNamedMetricValue(Map metricTypeMap, + MeasurementFieldEnum type, + String name, + String field, + T defaultValue, + BiFunction getter, + Consumer setter) { + // 获取值 + T value = Optional.of(type.getMeasurement() + "_" + Strings.def(name)) + .map(metricTypeMap::get) + .map(s -> getter.apply(s, field)) + .orElse(defaultValue); + // 设置值 + setter.accept(value); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorMetricsServiceImpl.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorMetricsServiceImpl.java new file mode 100644 index 00000000..afc9de26 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/service/impl/MonitorMetricsServiceImpl.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.service.impl; + +import cn.orionsec.kit.lang.define.wrapper.DataGrid; +import cn.orionsec.kit.lang.utils.collect.Lists; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.dromara.visor.common.constant.Const; +import org.dromara.visor.common.constant.ErrorMessage; +import org.dromara.visor.common.utils.Valid; +import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; +import org.dromara.visor.framework.redis.core.utils.RedisMaps; +import org.dromara.visor.framework.redis.core.utils.barrier.CacheBarriers; +import org.dromara.visor.module.monitor.convert.MonitorMetricsConvert; +import org.dromara.visor.module.monitor.dao.MonitorMetricsDAO; +import org.dromara.visor.module.monitor.define.cache.MonitorMetricsCacheKeyDefine; +import org.dromara.visor.module.monitor.entity.domain.MonitorMetricsDO; +import org.dromara.visor.module.monitor.entity.dto.MonitorMetricsCacheDTO; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsCreateRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsQueryRequest; +import org.dromara.visor.module.monitor.entity.request.metrics.MonitorMetricsUpdateRequest; +import org.dromara.visor.module.monitor.entity.vo.MonitorMetricsVO; +import org.dromara.visor.module.monitor.service.MonitorMetricsService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 监控指标 服务实现类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025-8-12 21:31 + */ +@Slf4j +@Service +public class MonitorMetricsServiceImpl implements MonitorMetricsService { + + private final Map metricsNameMap = new HashMap<>(); + + @Resource + private MonitorMetricsDAO monitorMetricsDAO; + + @PostConstruct + public void init() { + // 加载指标名称关联 + List metricsList = monitorMetricsDAO.selectList(null); + for (MonitorMetricsDO metrics : metricsList) { + metricsNameMap.put(metrics.getValue(), metrics.getName()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createMonitorMetrics(MonitorMetricsCreateRequest request) { + log.info("MonitorMetricsService-createMonitorMetrics request: {}", JSON.toJSONString(request)); + // 转换 + MonitorMetricsDO record = MonitorMetricsConvert.MAPPER.to(request); + // 查询数据是否冲突 + this.checkMonitorMetricsPresent(record); + // 插入 + int effect = monitorMetricsDAO.insert(record); + Long id = record.getId(); + // 删除缓存 + RedisMaps.delete(MonitorMetricsCacheKeyDefine.MONITOR_METRICS); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.ID, id); + // 修改本地缓存 + metricsNameMap.remove(record.getValue()); + metricsNameMap.put(request.getValue(), request.getName()); + log.info("MonitorMetricsService-createMonitorMetrics id: {}, effect: {}", id, effect); + return id; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer updateMonitorMetricsById(MonitorMetricsUpdateRequest request) { + Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING); + log.info("MonitorMetricsService-updateMonitorMetricsById id: {}, request: {}", id, JSON.toJSONString(request)); + // 查询 + MonitorMetricsDO record = monitorMetricsDAO.selectById(id); + Valid.notNull(record, ErrorMessage.DATA_ABSENT); + // 转换 + MonitorMetricsDO updateRecord = MonitorMetricsConvert.MAPPER.to(request); + // 查询数据是否冲突 + this.checkMonitorMetricsPresent(updateRecord); + // 更新 + int effect = monitorMetricsDAO.updateById(updateRecord); + log.info("MonitorMetricsService-updateMonitorMetricsById effect: {}", effect); + // 删除缓存 + RedisMaps.delete(MonitorMetricsCacheKeyDefine.MONITOR_METRICS); + // 修改本地缓存 + metricsNameMap.put(request.getValue(), request.getName()); + return effect; + } + + @Override + public List getMonitorMetricsList() { + // 查询缓存 + List list = RedisMaps.valuesJson(MonitorMetricsCacheKeyDefine.MONITOR_METRICS); + if (list.isEmpty()) { + // 查询数据库 + list = monitorMetricsDAO.of().list(MonitorMetricsConvert.MAPPER::toCache); + // 设置屏障 防止穿透 + CacheBarriers.checkBarrier(list, MonitorMetricsCacheDTO::new); + // 设置缓存 + RedisMaps.putAllJson(MonitorMetricsCacheKeyDefine.MONITOR_METRICS, s -> s.getId().toString(), list); + } + // 删除屏障 + CacheBarriers.removeBarrier(list); + // 转换 + return list.stream() + .map(MonitorMetricsConvert.MAPPER::to) + .sorted(Comparator.comparing(MonitorMetricsVO::getId).reversed()) + .collect(Collectors.toList()); + } + + @Override + public DataGrid getMonitorMetricsPage(MonitorMetricsQueryRequest request) { + // 条件 + LambdaQueryWrapper wrapper = this.buildQueryWrapper(request); + // 查询 + return monitorMetricsDAO.of() + .wrapper(wrapper) + .page(request) + .order(request, MonitorMetricsDO::getId) + .dataGrid(MonitorMetricsConvert.MAPPER::to); + } + + @Override + public String getMetricName(String value) { + return metricsNameMap.getOrDefault(value, value); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer deleteMonitorMetricsById(Long id) { + log.info("MonitorMetricsService-deleteMonitorMetricsById id: {}", id); + // 检查数据是否存在 + MonitorMetricsDO record = monitorMetricsDAO.selectById(id); + Valid.notNull(record, ErrorMessage.DATA_ABSENT); + // 删除 + int effect = monitorMetricsDAO.deleteById(id); + // 删除缓存 + RedisMaps.delete(MonitorMetricsCacheKeyDefine.MONITOR_METRICS, id); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.COUNT, effect); + log.info("MonitorMetricsService-deleteMonitorMetricsById id: {}, effect: {}", id, effect); + return effect; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer deleteMonitorMetricsByIdList(List idList) { + if (Lists.isEmpty(idList)) { + OperatorLogs.add(OperatorLogs.COUNT, Const.N_0); + return Const.N_0; + } + log.info("MonitorMetricsService-deleteMonitorMetricsByIdList idList: {}", idList); + int effect = monitorMetricsDAO.deleteBatchIds(idList); + // 删除缓存 + RedisMaps.delete(MonitorMetricsCacheKeyDefine.MONITOR_METRICS, idList); + // 设置日志参数 + OperatorLogs.add(OperatorLogs.COUNT, effect); + log.info("MonitorMetricsService-deleteMonitorMetricsByIdList effect: {}", effect); + return effect; + } + + @Override + public LambdaQueryWrapper buildQueryWrapper(MonitorMetricsQueryRequest request) { + return monitorMetricsDAO.wrapper() + .eq(MonitorMetricsDO::getName, request.getName()) + .eq(MonitorMetricsDO::getMeasurement, request.getMeasurement()) + .eq(MonitorMetricsDO::getValue, request.getValue()) + .eq(MonitorMetricsDO::getDescription, request.getDescription()); + } + + /** + * 检查对象是否存在 + * + * @param domain domain + */ + private void checkMonitorMetricsPresent(MonitorMetricsDO domain) { + // 构造条件 + LambdaQueryWrapper wrapper = monitorMetricsDAO.wrapper() + // 更新时忽略当前记录 + .ne(MonitorMetricsDO::getId, domain.getId()) + // 用其他字段做重复校验 + .eq(MonitorMetricsDO::getName, domain.getName()) + .eq(MonitorMetricsDO::getMeasurement, domain.getMeasurement()) + .eq(MonitorMetricsDO::getValue, domain.getValue()); + // 检查是否存在 + boolean present = monitorMetricsDAO.of(wrapper).present(); + Valid.isFalse(present, ErrorMessage.DATA_PRESENT); + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/utils/MetricsUtils.java b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/utils/MetricsUtils.java new file mode 100644 index 00000000..419b3286 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/java/org/dromara/visor/module/monitor/utils/MetricsUtils.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 - present Dromara, All rights reserved. + * + * https://visor.dromara.org + * https://visor.dromara.org.cn + * https://visor.orionsec.cn + * + * Members: + * Jiahang Li - ljh1553488six@139.com - author + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dromara.visor.module.monitor.utils; + +import cn.orionsec.kit.lang.utils.Strings; +import com.alibaba.fastjson.JSONObject; +import com.influxdb.client.write.Point; +import org.dromara.visor.module.monitor.enums.MeasurementFieldEnum; + +/** + * 指标值工具类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2025/8/11 22:46 + */ +public class MetricsUtils { + + private MetricsUtils() { + } + + /** + * 设置值 + * + * @param type type + * @param values values + * @return point + */ + public static Point createPoint(String type, JSONObject values) { + // 创建数据点 + Point point = Point.measurement(type); + // 设置数据值 + for (String field : values.keySet()) { + // 数据类型 + Class dataType = MeasurementFieldEnum.getMetricsValueType(type, field); + if (dataType == null) { + continue; + } + // 过滤数据 + String str = values.getString(field); + if (Strings.isBlank(str)) { + continue; + } + // 转换数据类型 + if (dataType == byte.class || dataType == short.class || dataType == int.class || dataType == long.class) { + point.addField(field, values.getLongValue(field)); + } else if (dataType == float.class || dataType == double.class) { + point.addField(field, values.getDoubleValue(field)); + } else if (dataType == boolean.class) { + point.addField(field, values.getBoolean(field)); + } else if (dataType == String.class) { + point.addField(field, values.getString(field)); + } + } + return point; + } + +} diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/resources/mapper/MonitorHostMapper.xml b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/resources/mapper/MonitorHostMapper.xml new file mode 100644 index 00000000..eb7c0d19 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/resources/mapper/MonitorHostMapper.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + id, host_id, policy_id, agent_key, alarm_switch, owner_user_id, owner_username, monitor_meta, monitor_config, create_time, update_time, creator, updater, deleted + + + diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/resources/mapper/MonitorMetricsMapper.xml b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/resources/mapper/MonitorMetricsMapper.xml new file mode 100644 index 00000000..84e4f020 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/main/resources/mapper/MonitorMetricsMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + id, name, measurement, value, unit, suffix, description, id, create_time, update_time, creator, updater, deleted + + + diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/java/org/dromara/visor/module/monitor/api/impl/.gitkeep b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/java/org/dromara/visor/module/monitor/api/impl/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/java/org/dromara/visor/module/monitor/service/impl/.gitkeep b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/java/org/dromara/visor/module/monitor/service/impl/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/resources/application-unit-test.yaml b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/resources/application-unit-test.yaml new file mode 100644 index 00000000..f349f31e --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/resources/application-unit-test.yaml @@ -0,0 +1,30 @@ +spring: + main: + lazy-initialization: true + banner-mode: OFF + datasource: + druid: + name: orion_visor + url: jdbc:h2:mem:memdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; + driver-class-name: org.h2.Driver + username: sa + password: + max-active: 1 + async-init: true + initial-size: 1 + test-while-idle: false + sql: + init: + schema-locations: + - classpath:/sql/create-table-h2-*.sql + redis: + host: 127.0.0.1 + port: 16379 + database: 0 + redisson: + threads: 2 + netty-threads: 2 + minimum-idle-size: 2 + +mybatis-plus: + lazy-initialization: true diff --git a/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/resources/sql/.gitkeep b/orion-visor-modules/orion-visor-module-monitor/orion-visor-module-monitor-service/src/test/resources/sql/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/orion-visor-modules/orion-visor-module-monitor/pom.xml b/orion-visor-modules/orion-visor-module-monitor/pom.xml new file mode 100644 index 00000000..d0effa82 --- /dev/null +++ b/orion-visor-modules/orion-visor-module-monitor/pom.xml @@ -0,0 +1,23 @@ + + + + org.dromara.visor + orion-visor-modules + ${revision} + + + 4.0.0 + orion-visor-module-monitor + pom + + 项目监控模块 + https://github.com/dromara/orion-visor + + + orion-visor-module-monitor-provider + orion-visor-module-monitor-service + + + \ No newline at end of file diff --git a/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/CommandSnippetGroupAutoClearTask.java b/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/CommandSnippetGroupAutoClearTask.java index a0d77072..a75fdba3 100644 --- a/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/CommandSnippetGroupAutoClearTask.java +++ b/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/CommandSnippetGroupAutoClearTask.java @@ -56,7 +56,7 @@ public class CommandSnippetGroupAutoClearTask { public void clear() { log.info("CommandSnippetGroupAutoClearTask.clear start"); // 获取锁并执行 - LockerUtils.tryLock(LOCK_KEY, commandSnippetGroupService::clearUnusedGroup); + LockerUtils.tryLockExecute(LOCK_KEY, commandSnippetGroupService::clearUnusedGroup); log.info("CommandSnippetGroupAutoClearTask.clear finish"); } diff --git a/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/PathBookmarkGroupAutoClearTask.java b/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/PathBookmarkGroupAutoClearTask.java index f1af9525..4e763d21 100644 --- a/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/PathBookmarkGroupAutoClearTask.java +++ b/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/PathBookmarkGroupAutoClearTask.java @@ -56,7 +56,7 @@ public class PathBookmarkGroupAutoClearTask { public void clear() { log.info("PathBookmarkGroupAutoClearTask.clear start"); // 获取锁并执行 - LockerUtils.tryLock(LOCK_KEY, pathBookmarkGroupService::clearUnusedGroup); + LockerUtils.tryLockExecute(LOCK_KEY, pathBookmarkGroupService::clearUnusedGroup); log.info("PathBookmarkGroupAutoClearTask.clear finish"); } diff --git a/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/TerminalConnectLogAutoClearTask.java b/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/TerminalConnectLogAutoClearTask.java index 806f7820..73ba13dd 100644 --- a/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/TerminalConnectLogAutoClearTask.java +++ b/orion-visor-modules/orion-visor-module-terminal/orion-visor-module-terminal-service/src/main/java/org/dromara/visor/module/terminal/task/TerminalConnectLogAutoClearTask.java @@ -70,7 +70,7 @@ public class TerminalConnectLogAutoClearTask { return; } // 获取锁并执行 - LockerUtils.tryLock(LOCK_KEY, this::doClear); + LockerUtils.tryLockExecute(LOCK_KEY, this::doClear); log.info("TerminalConnectLogAutoClearTask.clear finish"); } diff --git a/orion-visor-modules/pom.xml b/orion-visor-modules/pom.xml index a9e26967..191903fe 100644 --- a/orion-visor-modules/pom.xml +++ b/orion-visor-modules/pom.xml @@ -21,6 +21,7 @@ orion-visor-module-asset orion-visor-module-exec orion-visor-module-terminal + orion-visor-module-monitor \ No newline at end of file diff --git a/orion-visor-ui/.env.development b/orion-visor-ui/.env.development index cde81650..14e7553f 100644 --- a/orion-visor-ui/.env.development +++ b/orion-visor-ui/.env.development @@ -3,4 +3,4 @@ VITE_API_BASE_URL=http://127.0.0.1:9200/orion-visor/api # websocket 路径 VITE_WS_BASE_URL=ws://127.0.0.1:9200/orion-visor/keep-alive # 版本号 -VITE_APP_VERSION=2.4.3 +VITE_APP_VERSION=2.5.0 diff --git a/orion-visor-ui/.env.production b/orion-visor-ui/.env.production index e99ebffc..4b89d4ec 100644 --- a/orion-visor-ui/.env.production +++ b/orion-visor-ui/.env.production @@ -3,4 +3,4 @@ VITE_API_BASE_URL=/orion-visor/api # websocket 路径 VITE_WS_BASE_URL=/orion-visor/keep-alive # 版本号 -VITE_APP_VERSION=2.4.3 +VITE_APP_VERSION=2.5.0 diff --git a/orion-visor-ui/package.json b/orion-visor-ui/package.json index fbf966f0..77bbb39f 100644 --- a/orion-visor-ui/package.json +++ b/orion-visor-ui/package.json @@ -1,7 +1,7 @@ { "name": "orion-visor-ui", "description": "Orion Visor UI", - "version": "2.4.3", + "version": "2.5.0", "private": true, "author": "Jiahang Li", "license": "Apache 2.0", diff --git a/orion-visor-ui/src/api/asset/host-agent.ts b/orion-visor-ui/src/api/asset/host-agent.ts new file mode 100644 index 00000000..d07c658d --- /dev/null +++ b/orion-visor-ui/src/api/asset/host-agent.ts @@ -0,0 +1,102 @@ +import axios from 'axios'; +import qs from 'query-string'; + +/** + * 主机探针状态 + */ +export interface HostAgentStatusResponse { + id: number; + agentVersion: string; + latestVersion: string; + agentInstallStatus: number; + agentOnlineStatus: number; +} + +/** + * 探针日志 + */ +export interface HostAgentLogResponse { + id: number; + hostId: number; + agentKey: string; + type: string; + status: string; + message: string; + createTime: number; + updateTime: number; + creator: string; + updater: string; + agentStatus: HostAgentStatusResponse; +} + +/** + * 安装探针请求 + */ +export interface HostInstallAgentRequest { + idList?: Array; +} + +/** + * 主机安装探针更新状态请求 + */ +export interface HostAgentInstallStatusUpdateRequest { + id?: number; + status?: string; + message?: string; +} + +/** + * 安装主机探针 + */ +export function installHostAgent(request: HostInstallAgentRequest) { + return axios.post('/asset/host-agent/install', request); +} + +/** + * 修改探针安装状态 + */ +export function updateAgentInstallStatus(request: HostAgentInstallStatusUpdateRequest) { + return axios.put('/asset/host-agent/update-install-status', request); +} + +/** + * 查询主机探针状态 + */ +export function getHostAgentStatus(idList: Array) { + return axios.get>('/asset/host-agent/status', { + params: { idList }, + promptBizErrorMessage: false, + promptRequestErrorMessage: false, + paramsSerializer: params => { + return qs.stringify(params, { arrayFormat: 'comma' }); + } + }); +} + +/** + * 查询探针安装状态 + */ +export function getAgentInstallLogStatus(idList: Array) { + return axios.get>('/asset/host-agent/install-status', { + params: { idList }, + promptBizErrorMessage: false, + promptRequestErrorMessage: false, + paramsSerializer: params => { + return qs.stringify(params, { arrayFormat: 'comma' }); + } + }); +} + +/** + * 上传探针发布包 + */ +export function uploadAgentRelease(file: File) { + const formData = new FormData(); + formData.append('file', file); + return axios.post('/asset/host-agent/upload-agent-release', formData, { + timeout: 120000, + headers: { + 'Content-Type': 'multipart/form-data' + }, + }); +} diff --git a/orion-visor-ui/src/api/asset/host-config.ts b/orion-visor-ui/src/api/asset/host-config.ts index 281d34a0..1de7a426 100644 --- a/orion-visor-ui/src/api/asset/host-config.ts +++ b/orion-visor-ui/src/api/asset/host-config.ts @@ -56,7 +56,6 @@ export interface HostVncConfig extends HostBaseConfig { identityId?: number; noUsername?: boolean; noPassword?: boolean; - portForwardId?: number; timezone?: string; clipboardEncoding?: string; } diff --git a/orion-visor-ui/src/api/asset/host-extra.ts b/orion-visor-ui/src/api/asset/host-extra.ts index 62419d8d..c77a90d0 100644 --- a/orion-visor-ui/src/api/asset/host-extra.ts +++ b/orion-visor-ui/src/api/asset/host-extra.ts @@ -50,20 +50,23 @@ export interface HostLabelExtraSettingModel { export interface HostSpecExtraModel { sn: string; osName: string; - cpuCore: number; + cpuCount: number; + cpuPhysicalCore: number; + cpuLogicalCore: number; cpuFrequency: number; cpuModel: string; memorySize: number; diskSize: number; inBandwidth: number; outBandwidth: number; - publicIpAddress: Array; - privateIpAddress: Array; - chargePerson: string; + publicIpAddresses: Array; + privateIpAddresses: Array; + ownerPerson: string; createdTime: number; expiredTime: number; items: Array<{ label: string; + key?: string; value: string; }>; } diff --git a/orion-visor-ui/src/api/asset/host.ts b/orion-visor-ui/src/api/asset/host.ts index a01dd48e..4da9acfb 100644 --- a/orion-visor-ui/src/api/asset/host.ts +++ b/orion-visor-ui/src/api/asset/host.ts @@ -69,6 +69,11 @@ export interface HostQueryBaseResponse { code: string; address: string; status: string; + agentKey: string; + agentVersion: string; + agentInstallStatus: number; + agentOnlineStatus: number; + agentOnlineChangeTime: number; description: string; createTime: number; updateTime: number; @@ -143,8 +148,8 @@ export function updateHostSpec(request: Partial) { /** * 查询主机 */ -export function getHost(id: number) { - return axios.get('/asset/host/get', { params: { id } }); +export function getHost(id: number, base = false) { + return axios.get('/asset/host/get', { params: { id, base } }); } /** diff --git a/orion-visor-ui/src/api/interceptor.ts b/orion-visor-ui/src/api/interceptor.ts index 2bf14d34..a2b6b146 100644 --- a/orion-visor-ui/src/api/interceptor.ts +++ b/orion-visor-ui/src/api/interceptor.ts @@ -6,7 +6,7 @@ import { getToken } from '@/utils/auth'; import { httpBaseUrl } from '@/utils/env'; import { reLoginTipsKey } from '@/types/symbol'; -axios.defaults.timeout = 10000; +axios.defaults.timeout = 15000; axios.defaults.setAuthorization = true; axios.defaults.promptBizErrorMessage = true; axios.defaults.promptRequestErrorMessage = true; diff --git a/orion-visor-ui/src/api/monitor/metrics.ts b/orion-visor-ui/src/api/monitor/metrics.ts new file mode 100644 index 00000000..1d5437d3 --- /dev/null +++ b/orion-visor-ui/src/api/monitor/metrics.ts @@ -0,0 +1,95 @@ +import type { TableData } from '@arco-design/web-vue'; +import type { DataGrid, OrderDirection, Pagination } from '@/types/global'; +import axios from 'axios'; + +/** + * 监控指标创建请求 + */ +export interface MetricsCreateRequest { + name?: string; + measurement?: string; + value?: string; + unit?: string; + suffix?: string; + description?: string; +} + +/** + * 监控指标更新请求 + */ +export interface MetricsUpdateRequest extends MetricsCreateRequest { + id?: number; +} + +/** + * 监控指标查询请求 + */ +export interface MetricsQueryRequest extends Pagination, OrderDirection { + searchValue?: string; + id?: number; + name?: string; + measurement?: string; + value?: string; + unit?: string; + suffix?: string; + description?: string; +} + +/** + * 监控指标查询响应 + */ +export interface MetricsQueryResponse extends TableData { + id: number; + name: string; + measurement: string; + value: string; + unit: string; + suffix: string; + description: string; + createTime: number; + updateTime: number; + creator: string; + updater: string; +} + +/** + * 创建监控指标 + */ +export function createMetrics(request: MetricsCreateRequest) { + return axios.post('/monitor/monitor-metrics/create', request); +} + +/** + * 更新监控指标 + */ +export function updateMetrics(request: MetricsUpdateRequest) { + return axios.put('/monitor/monitor-metrics/update', request); +} + +/** + * 查询监控指标 + */ +export function getMetrics(id: number) { + return axios.get('/monitor/monitor-metrics/get', { params: { id } }); +} + +/** + * 查询全部监控指标 + */ +export function getMetricsList() { + return axios.get>('/monitor/monitor-metrics/list'); +} + +/** + * 分页查询监控指标 + */ +export function getMetricsPage(request: MetricsQueryRequest) { + return axios.post>('/monitor/monitor-metrics/query', request); +} + +/** + * 删除监控指标 + */ +export function deleteMetrics(id: number) { + return axios.delete('/monitor/monitor-metrics/delete', { params: { id } }); +} diff --git a/orion-visor-ui/src/api/monitor/monitor-host.ts b/orion-visor-ui/src/api/monitor/monitor-host.ts new file mode 100644 index 00000000..34d62e3f --- /dev/null +++ b/orion-visor-ui/src/api/monitor/monitor-host.ts @@ -0,0 +1,168 @@ +import type { TableData } from '@arco-design/web-vue'; +import type { DataGrid, Pagination, TimeChartSeries } from '@/types/global'; +import type { HostAgentLogResponse } from '@/api/asset/host-agent'; +import axios from 'axios'; + +/** + * 监控主机更新请求 + */ +export interface MonitorHostUpdateRequest { + id?: number; + policyId?: number; + alarmSwitch?: number; + ownerUserId?: number; + cpuName?: string; + diskName?: string; + networkName?: string; +} + +/** + * 监控主机更新请求 + */ +export interface MonitorHostSwitchUpdateRequest { + id?: number; + alarmSwitch?: number; +} + +/** + * 监控主机查询请求 + */ +export interface MonitorHostQueryRequest extends Pagination { + agentKeyList?: Array; + searchValue?: string; + alarmSwitch?: number; + policyId?: number; + ownerUserId?: number; + name?: string; + code?: string; + address?: string; + agentKey?: string; + agentInstallStatus?: number; + agentOnlineStatus?: number; + description?: string; + tags?: Array; +} + +/** + * 监控主机图表查询请求 + */ +export interface MonitorHostChartRequest { + agentKeys?: Array; + measurement?: string; + fields?: Array; + window?: string; + aggregate?: string; + range?: string; + start?: string; + end?: string; +} + +/** + * 监控主机查询响应 + */ +export interface MonitorHostQueryResponse extends TableData { + id: number; + hostId: number; + policyId: number; + policyName: string; + osType: string; + name: string; + code: string; + address: string; + status: string; + agentKey: string; + agentVersion: string; + latestVersion: string; + agentInstallStatus: number; + agentOnlineStatus: number; + agentOnlineChangeTime: number; + alarmSwitch: number; + ownerUserId: number; + ownerUsername: string; + tags: Array<{ id: number, name: string }>; + meta: MonitorHostMeta; + config: MonitorHostConfig; + metricsData: MonitorHostMetricsData; + installLog: HostAgentLogResponse; +} + +/** + * 监控元数据 + */ +export interface MonitorHostMeta { + cpus: Array; + disks: Array; + nets: Array; + memoryBytes: number; +} + +/** + * 监控配置 + */ +export interface MonitorHostConfig { + cpuName: string; + diskName: string; + networkName: string; +} + +/** + * 监控数据 + */ +export interface MonitorHostMetricsData { + agentKey: string; + noData: boolean; + timestamp: number; + cpuName: string; + diskName: string; + networkName: string; + cpuUsagePercent: number; + memoryUsagePercent: number; + memoryUsageBytes: number; + load1: number; + load5: number; + load15: number; + diskUsagePercent: number; + diskUsageBytes: number; + networkSentPreBytes: number; + networkRecvPreBytes: number; +} + +/** + * 查询监控主机指标 + */ +export function getMonitorHostMetrics(agentKeyList: Array) { + return axios.post>('/monitor/monitor-host/metrics', { + agentKeyList + }, { + promptBizErrorMessage: false, + promptRequestErrorMessage: false, + }); +} + +/** + * 查询监控主机图表 + */ +export function getMonitorHostChart(request: MonitorHostChartRequest) { + return axios.post>('/monitor/monitor-host/chart', request); +} + +/** + * 分页查询监控主机 + */ +export function getMonitorHostPage(request: MonitorHostQueryRequest) { + return axios.post>('/monitor/monitor-host/query', request); +} + +/** + * 更新监控主机 + */ +export function updateMonitorHost(request: MonitorHostUpdateRequest) { + return axios.put('/monitor/monitor-host/update', request); +} + +/** + * 更新监控主机告警开关 + */ +export function updateMonitorHostAlarmSwitch(request: MonitorHostSwitchUpdateRequest) { + return axios.put('/monitor/monitor-host/update-switch', request); +} diff --git a/orion-visor-ui/src/api/terminal/terminal-sftp.ts b/orion-visor-ui/src/api/terminal/terminal-sftp.ts index 43f837fd..252de82e 100644 --- a/orion-visor-ui/src/api/terminal/terminal-sftp.ts +++ b/orion-visor-ui/src/api/terminal/terminal-sftp.ts @@ -20,7 +20,7 @@ export function setSftpFileContent(token: string, content: string) { formData.append('token', token); formData.append('file', new File([content], Date.now() + '', { type: 'text/plain' })); return axios.post('/terminal/terminal-sftp/set-content', formData, { - timeout: 60000, + timeout: 120000, headers: { 'Content-Type': 'multipart/form-data' } diff --git a/orion-visor-ui/src/assets/style/arco-extends.less b/orion-visor-ui/src/assets/style/arco-extends.less index 386470a9..2bdecfc7 100644 --- a/orion-visor-ui/src/assets/style/arco-extends.less +++ b/orion-visor-ui/src/assets/style/arco-extends.less @@ -31,19 +31,19 @@ background-color: rgb(var(--blue-6)); &.normal { - color: rgb(var(--arcoblue-6)); + background-color: rgb(var(--arcoblue-6)); } &.pass { - color: rgb(var(--green-6)); + background-color: rgb(var(--green-6)); } &.warn { - color: rgb(var(--orange-6)); + background-color: rgb(var(--orange-6)); } &.error { - color: rgb(var(--red-6)); + background-color: rgb(var(--red-6)); } } } diff --git a/orion-visor-ui/src/assets/style/chart.less b/orion-visor-ui/src/assets/style/chart.less new file mode 100644 index 00000000..844607a5 --- /dev/null +++ b/orion-visor-ui/src/assets/style/chart.less @@ -0,0 +1,49 @@ +// tooltip +.chart-tooltip-wrapper { + // 时间 + .chart-tooltip-time { + font-size: 13px; + } + + // 表头 + .chart-tooltip-header { + margin-top: 5px; + font-size: 12px; + line-height: 1.3; + + &-grid { + display: grid; + gap: 0 8px; + align-items: center; + } + + &-item { + font-weight: bold; + padding: 2px 0; + white-space: nowrap; + border-bottom: 1px solid #ddd; + } + } + + // 圆点 + .chart-tooltip-dot { + display: inline-block; + width: 8px; + height: 8px; + border-radius: 50%; + margin-right: 5px; + } + + // 数据行 + .chart-tooltip-col { + font-weight: 500; + color: #000; + padding: 3px 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: flex; + align-items: center; + } + +} diff --git a/orion-visor-ui/src/assets/style/global.less b/orion-visor-ui/src/assets/style/global.less index 105f2ba8..3d82980c 100644 --- a/orion-visor-ui/src/assets/style/global.less +++ b/orion-visor-ui/src/assets/style/global.less @@ -282,10 +282,18 @@ body { margin-left: 4px; } +.mr2 { + margin-right: 2px; +} + .mr4 { margin-right: 4px; } +.mt2 { + margin-top: 2px; +} + .mt4 { margin-top: 4px; } diff --git a/orion-visor-ui/src/assets/style/layout.less b/orion-visor-ui/src/assets/style/layout.less index e7bbf85a..1930ceeb 100644 --- a/orion-visor-ui/src/assets/style/layout.less +++ b/orion-visor-ui/src/assets/style/layout.less @@ -172,7 +172,7 @@ } & > .arco-card-body { - padding: 0 16px 16px 16px; + padding: 0 16px 12px 16px; flex-grow: 1; } } @@ -230,6 +230,10 @@ } // -- doption +.arco-dropdown-option-disabled .arco-dropdown-option-content .more-doption { + color: var(--color-text-4); +} + .more-doption { min-width: 42px; padding: 0 4px; diff --git a/orion-visor-ui/src/components/app/setting/index.vue b/orion-visor-ui/src/components/app/setting/index.vue index dd3ac34e..b2c937a0 100644 --- a/orion-visor-ui/src/components/app/setting/index.vue +++ b/orion-visor-ui/src/components/app/setting/index.vue @@ -152,6 +152,15 @@ defaultVal: appStore.hostIdentityView, options: cardOptions, }, + { + name: '主机监控', + key: 'monitorHostView', + type: 'radio-group', + margin: '0 0 4px 0', + permission: ['monitor:monitor-host:query'], + defaultVal: appStore.monitorHostView, + options: cardOptions, + }, ]); // 是否展示创建 PWA 应用 diff --git a/orion-visor-ui/src/components/app/tab-bar/index.vue b/orion-visor-ui/src/components/app/tab-bar/index.vue index 2911802f..03e86b5a 100644 --- a/orion-visor-ui/src/components/app/tab-bar/index.vue +++ b/orion-visor-ui/src/components/app/tab-bar/index.vue @@ -6,6 +6,7 @@

@@ -18,7 +19,6 @@ + + + + diff --git a/orion-visor-ui/src/views/monitor/metrics/components/metrics-table.vue b/orion-visor-ui/src/views/monitor/metrics/components/metrics-table.vue new file mode 100644 index 00000000..61eca0d0 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/metrics/components/metrics-table.vue @@ -0,0 +1,221 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/metrics/index.vue b/orion-visor-ui/src/views/monitor/metrics/index.vue new file mode 100644 index 00000000..8876f0ee --- /dev/null +++ b/orion-visor-ui/src/views/monitor/metrics/index.vue @@ -0,0 +1,46 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/metrics/types/const.ts b/orion-visor-ui/src/views/monitor/metrics/types/const.ts new file mode 100644 index 00000000..d14d05b0 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/metrics/types/const.ts @@ -0,0 +1,10 @@ +export const TableName = 'monitor_metrics'; + +// 监控指标类型 字典项 +export const MeasurementKey = 'metricsMeasurement'; + +// 监控指标单位 字典项 +export const MetricsUnitKey = 'metricsUnit'; + +// 加载的字典值 +export const dictKeys = [MeasurementKey, MetricsUnitKey]; diff --git a/orion-visor-ui/src/views/monitor/metrics/types/form.rules.ts b/orion-visor-ui/src/views/monitor/metrics/types/form.rules.ts new file mode 100644 index 00000000..9bfc9f58 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/metrics/types/form.rules.ts @@ -0,0 +1,52 @@ +import type { FieldRule } from '@arco-design/web-vue'; + +export const name = [{ + required: true, + message: '请输入指标名称' +}, { + maxLength: 64, + message: '指标名称长度不能大于64位' +}] as FieldRule[]; + +export const measurement = [{ + required: true, + message: '请输入数据集' +}, { + maxLength: 64, + message: '数据集长度不能大于64位' +}] as FieldRule[]; + +export const value = [{ + required: true, + message: '请输入指标项' +}, { + maxLength: 128, + message: '指标项长度不能大于128位' +}] as FieldRule[]; + +export const unit = [{ + required: true, + message: '请选择单位' +}] as FieldRule[]; + +export const suffix = [{ + required: true, + message: '请输入后缀文本' +}, { + maxLength: 32, + message: '后缀文本长度不能大于32位' +}] as FieldRule[]; + +export const description = [{ + maxLength: 128, + message: '指标描述长度不能大于128位' +}] as FieldRule[]; + +export default { + name, + measurement, + value, + unit, + suffix, + description, +} as Record; diff --git a/orion-visor-ui/src/views/monitor/metrics/types/table.columns.ts b/orion-visor-ui/src/views/monitor/metrics/types/table.columns.ts new file mode 100644 index 00000000..bfbdfce6 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/metrics/types/table.columns.ts @@ -0,0 +1,98 @@ +import type { TableColumnData } from '@arco-design/web-vue'; +import { dateFormat } from '@/utils'; + +const columns = [ + { + title: 'id', + dataIndex: 'id', + slotName: 'id', + width: 68, + align: 'left', + fixed: 'left', + default: true, + }, { + title: '指标名称', + dataIndex: 'name', + slotName: 'name', + align: 'left', + width: 238, + ellipsis: true, + tooltip: true, + default: true, + }, { + title: '数据集', + dataIndex: 'measurement', + slotName: 'measurement', + align: 'left', + width: 148, + ellipsis: true, + tooltip: true, + default: true, + }, { + title: '指标项', + dataIndex: 'value', + slotName: 'value', + align: 'left', + minWidth: 288, + ellipsis: true, + tooltip: true, + default: true, + }, { + title: '指标单位', + dataIndex: 'unit', + slotName: 'unit', + align: 'left', + width: 168, + default: true, + }, { + title: '指标描述', + dataIndex: 'description', + slotName: 'description', + align: 'left', + ellipsis: true, + tooltip: true, + default: true, + }, { + title: '创建时间', + dataIndex: 'createTime', + slotName: 'createTime', + align: 'center', + width: 180, + render: ({ record }) => { + return dateFormat(new Date(record.createTime)); + }, + }, { + title: '修改时间', + dataIndex: 'updateTime', + slotName: 'updateTime', + align: 'center', + width: 180, + render: ({ record }) => { + return dateFormat(new Date(record.updateTime)); + }, + default: true, + }, { + title: '创建人', + dataIndex: 'creator', + slotName: 'creator', + width: 148, + ellipsis: true, + tooltip: true, + }, { + title: '修改人', + dataIndex: 'updater', + slotName: 'updater', + width: 148, + ellipsis: true, + tooltip: true, + }, { + title: '操作', + slotName: 'handle', + width: 130, + align: 'center', + fixed: 'right', + default: true, + }, +] as TableColumnData[]; + +export default columns; diff --git a/orion-visor-ui/src/views/monitor/monitor-detail/compoments/detail-header.vue b/orion-visor-ui/src/views/monitor/monitor-detail/compoments/detail-header.vue new file mode 100644 index 00000000..59e84fa5 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-detail/compoments/detail-header.vue @@ -0,0 +1,207 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-detail/compoments/metrics-chart-tab.vue b/orion-visor-ui/src/views/monitor/monitor-detail/compoments/metrics-chart-tab.vue new file mode 100644 index 00000000..bcc8608f --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-detail/compoments/metrics-chart-tab.vue @@ -0,0 +1,179 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-detail/compoments/metrics-chart.vue b/orion-visor-ui/src/views/monitor/monitor-detail/compoments/metrics-chart.vue new file mode 100644 index 00000000..39500b63 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-detail/compoments/metrics-chart.vue @@ -0,0 +1,241 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-detail/index.vue b/orion-visor-ui/src/views/monitor/monitor-detail/index.vue new file mode 100644 index 00000000..fc2b8402 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-detail/index.vue @@ -0,0 +1,112 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-detail/types/const.ts b/orion-visor-ui/src/views/monitor/monitor-detail/types/const.ts new file mode 100644 index 00000000..b83e96af --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-detail/types/const.ts @@ -0,0 +1,45 @@ +import type { WindowUnit, MetricUnitType, MetricUnitFormatOptions } from '@/utils/metrics'; + +// 图表组件配置 +export interface MetricsChartProps { + agentKeys: Array; + range: string; + windowValue: number; + windowUnit: WindowUnit; + option: MetricsChartOption; +} + +// 图表显示配置 +export interface MetricsChartOption { + name: string; + type?: 'line' | 'bar'; + measurement: string; + fields: Array; + span?: number; + legend?: boolean; + background?: boolean; + colors: Array<[string, string]>; + aggregate: string; + unit: MetricUnitType; + unitOption: MetricUnitFormatOptions; +} + +// tab +export const TabKeys = { + CHART: 'chart' +}; + +// 探针在线状态 字典项 +export const OnlineStatusKey = 'agentOnlineStatus'; + +// 监控告警开关 字典项 +export const AlarmSwitchKey = 'monitorAlarmSwitch'; + +// 指标图表区间 字典项 +export const ChartRangeKey = 'metricsChartRange'; + +// 指标聚合函数 字典项 +export const MetricsAggregateKey = 'metricsAggregate'; + +// 加载的字典值 +export const dictKeys = [AlarmSwitchKey, OnlineStatusKey, ChartRangeKey, MetricsAggregateKey]; diff --git a/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-cell.vue b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-cell.vue new file mode 100644 index 00000000..b2939e74 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-cell.vue @@ -0,0 +1,68 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-card-list.vue b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-card-list.vue new file mode 100644 index 00000000..7fd152a5 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-card-list.vue @@ -0,0 +1,424 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-form-drawer.vue b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-form-drawer.vue new file mode 100644 index 00000000..7a3f8b1b --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-form-drawer.vue @@ -0,0 +1,150 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-table.vue b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-table.vue new file mode 100644 index 00000000..58d6de4e --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/components/monitor-host-table.vue @@ -0,0 +1,490 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-host/components/release-upload-modal.vue b/orion-visor-ui/src/views/monitor/monitor-host/components/release-upload-modal.vue new file mode 100644 index 00000000..83fcf6a2 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/components/release-upload-modal.vue @@ -0,0 +1,112 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-host/index.vue b/orion-visor-ui/src/views/monitor/monitor-host/index.vue new file mode 100644 index 00000000..1dc9a151 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/index.vue @@ -0,0 +1,65 @@ + + + + + + + diff --git a/orion-visor-ui/src/views/monitor/monitor-host/types/card.fields.ts b/orion-visor-ui/src/views/monitor/monitor-host/types/card.fields.ts new file mode 100644 index 00000000..c6b3c21a --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/types/card.fields.ts @@ -0,0 +1,81 @@ +import type { CardField, CardFieldConfig } from '@/types/card'; + +const fieldConfig = { + rowGap: '10px', + labelSpan: 6, + minHeight: '22px', + fields: [ + { + label: '主机ID', + dataIndex: 'hostId', + slotName: 'hostId', + default: true, + }, { + label: '主机地址', + dataIndex: 'address', + slotName: 'address', + default: true, + }, { + label: '主机编码', + dataIndex: 'code', + slotName: 'code', + default: false, + }, { + label: '负责人', + dataIndex: 'ownerUsername', + slotName: 'ownerUsername', + ellipsis: true, + default: true, + }, { + label: '设备状态', + dataIndex: 'agentOnlineStatus', + slotName: 'agentOnlineStatus', + default: true, + }, { + label: 'CPU', + dataIndex: 'cpuUsage', + slotName: 'cpuUsage', + default: true, + }, { + label: '内存', + dataIndex: 'memoryUsage', + slotName: 'memoryUsage', + default: true, + }, { + label: '磁盘', + dataIndex: 'diskUsage', + slotName: 'diskUsage', + default: true, + }, { + label: '网络', + dataIndex: 'network', + slotName: 'network', + default: true, + }, { + label: '负载', + dataIndex: 'load', + slotName: 'load', + default: true, + }, { + label: '标签', + dataIndex: 'tags', + slotName: 'tags', + default: false, + }, { + label: 'agentKey', + dataIndex: 'agentKey', + slotName: 'agentKey', + ellipsis: true, + default: false, + }, { + label: '探针版本', + dataIndex: 'agentVersion', + slotName: 'agentVersion', + ellipsis: true, + tooltip: true, + default: true, + } + ] as CardField[] +} as CardFieldConfig; + +export default fieldConfig; diff --git a/orion-visor-ui/src/views/monitor/monitor-host/types/const.ts b/orion-visor-ui/src/views/monitor/monitor-host/types/const.ts new file mode 100644 index 00000000..9b0d221b --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/types/const.ts @@ -0,0 +1,32 @@ +export const TableName = 'monitor_host'; + +// 监控告警开关 +export const AlarmSwitch = { + OFF: 0, + ON: 1, +}; + +// 探针日志状态 +export const AgentLogStatus = { + WAIT: 'WAIT', + RUNNING: 'RUNNING', + SUCCESS: 'SUCCESS', + FAILED: 'FAILED', +}; + +export const NODATA_TIPS = '暂无数据'; + +// 探针安装状态 字典项 +export const InstallStatusKey = 'agentInstallStatus'; + +// 探针在线状态 字典项 +export const OnlineStatusKey = 'agentOnlineStatus'; + +// 监控告警开关 字典项 +export const AlarmSwitchKey = 'monitorAlarmSwitch'; + +// 探针日志状态 字典项 +export const AgentLogStatusKey = 'agentLogStatus'; + +// 加载的字典值 +export const dictKeys = [InstallStatusKey, AlarmSwitchKey, OnlineStatusKey, AgentLogStatusKey]; diff --git a/orion-visor-ui/src/views/monitor/monitor-host/types/form.rules.ts b/orion-visor-ui/src/views/monitor/monitor-host/types/form.rules.ts new file mode 100644 index 00000000..00b6821b --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/types/form.rules.ts @@ -0,0 +1,16 @@ +import type { FieldRule } from '@arco-design/web-vue'; + +export const policyId = [{ + required: false, + message: '请输入策略id' +}] as FieldRule[]; + +export const alarmSwitch = [{ + required: true, + message: '请输入告警开关' +}] as FieldRule[]; + +export default { + policyId, + alarmSwitch, +} as Record; diff --git a/orion-visor-ui/src/views/monitor/monitor-host/types/table.columns.ts b/orion-visor-ui/src/views/monitor/monitor-host/types/table.columns.ts new file mode 100644 index 00000000..3328df4f --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/types/table.columns.ts @@ -0,0 +1,112 @@ +import type { TableColumnData } from '@arco-design/web-vue'; + +const columns = [ + { + title: '主机ID', + dataIndex: 'hostId', + slotName: 'hostId', + width: 80, + align: 'left', + fixed: 'left', + default: true, + }, { + title: '主机信息', + dataIndex: 'hostInfo', + slotName: 'hostInfo', + width: 248, + align: 'left', + fixed: 'left', + default: true, + }, { + title: '设备状态', + dataIndex: 'agentOnlineStatus', + slotName: 'agentOnlineStatus', + align: 'center', + width: 120, + default: true, + }, { + title: 'CPU', + dataIndex: 'cpuUsage', + slotName: 'cpuUsage', + align: 'left', + width: 198, + default: true, + }, { + title: '内存', + dataIndex: 'memoryUsage', + slotName: 'memoryUsage', + align: 'left', + width: 198, + default: true, + }, { + title: '磁盘', + dataIndex: 'diskUsage', + slotName: 'diskUsage', + align: 'left', + width: 198, + default: true, + }, { + title: '网络', + dataIndex: 'network', + slotName: 'network', + align: 'left', + width: 148, + default: true, + }, { + title: '负载', + dataIndex: 'load', + slotName: 'load', + align: 'left', + width: 148, + default: true, + }, { + title: '标签', + dataIndex: 'tags', + slotName: 'tags', + align: 'left', + minWidth: 148, + default: false, + }, { + title: 'agentKey', + dataIndex: 'agentKey', + slotName: 'agentKey', + align: 'left', + width: 288, + default: false, + }, { + // TODO + // title: '告警策略', + // dataIndex: 'alarmPolicy', + // slotName: 'alarmPolicy', + // align: 'left', + // width: 120, + // default: true, + // }, { + title: '负责人', + dataIndex: 'ownerUsername', + slotName: 'ownerUsername', + align: 'left', + width: 108, + ellipsis: true, + tooltip: true, + default: true, + }, { + title: '探针版本', + dataIndex: 'agentVersion', + slotName: 'agentVersion', + align: 'left', + width: 118, + ellipsis: true, + tooltip: true, + default: true, + }, { + title: '操作', + slotName: 'handle', + width: 128, + align: 'center', + fixed: 'right', + default: true, + }, +] as TableColumnData[]; + +export default columns; diff --git a/orion-visor-ui/src/views/monitor/monitor-host/types/use-monitor-host-list.ts b/orion-visor-ui/src/views/monitor/monitor-host/types/use-monitor-host-list.ts new file mode 100644 index 00000000..3fe83588 --- /dev/null +++ b/orion-visor-ui/src/views/monitor/monitor-host/types/use-monitor-host-list.ts @@ -0,0 +1,273 @@ +import type { MonitorHostQueryResponse, } from '@/api/monitor/monitor-host'; +import { getMonitorHostMetrics, updateMonitorHostAlarmSwitch } from '@/api/monitor/monitor-host'; +import type { HostAgentLogResponse } from '@/api/asset/host-agent'; +import { getAgentInstallLogStatus, getHostAgentStatus, installHostAgent, updateAgentInstallStatus } from '@/api/asset/host-agent'; +import type { Ref } from 'vue'; +import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'; +import { useRouter } from 'vue-router'; +import { useDictStore } from '@/store'; +import { Message, Modal } from '@arco-design/web-vue'; +import { AgentInstallStatus, HostOsType } from '@/views/asset/host-list/types/const'; +import { AgentLogStatus, AlarmSwitchKey } from '@/views/monitor/monitor-host/types/const'; + +// 监控主机列表配置 +export interface UseMonitorHostListOptions { + // 主机信息 + hosts: Ref>; + // 设置加载中 + setLoading: (loading: boolean) => void; + // 重新加载 + reload: () => void; +} + +// 使用监控主机列表 +export default function useMonitorHostList(options: UseMonitorHostListOptions) { + const autoRefresh = ref(true); + const autoRefreshId = ref(); + const fetchInstallStatusId = ref(); + const lastRefreshTime = ref(0); + + const router = useRouter(); + const { toggleDict } = useDictStore(); + const { hosts, setLoading, reload } = options; + + // 打开详情 + const openDetail = (hostId: number, name: string) => { + router.push({ name: 'monitorDetail', query: { hostId, name } }); + }; + + // 安装探针 + const installAgent = async (hostIdList: Array) => { + try { + setLoading(true); + // 获取全部数据 + const installHosts = hosts.value.filter(s => hostIdList.includes(s.hostId)); + let hasWindows = false; + // 安装前检查 + for (let host of installHosts) { + // 检查状态 + if (host?.installLog?.status === AgentLogStatus.WAIT || host?.installLog?.status === AgentLogStatus.RUNNING) { + Message.error('主机' + host.name + '正在安装中, 请勿重复操作'); + return; + } + // 检查系统类型 + if (host.osType === HostOsType.WINDOWS.value) { + hasWindows = true; + } + } + // 二次确认 + Modal.confirm({ + title: '安装提示', + titleAlign: 'start', + bodyStyle: { 'white-space': 'pre-wrap' }, + content: `请确保探针已关闭\n请确认文件夹是否有权限${hasWindows ? '\nWindows 系统仅支持探针上传, 请手动进行安装' : ''}`, + okText: '确定', + onOk: async () => { + try { + // 调用安装 + await installHostAgent({ idList: hostIdList }); + Message.success('开始安装'); + // 重新加载 + reload(); + } catch (e) { + } finally { + setLoading(false); + } + } + }); + } catch (e) { + } finally { + setLoading(false); + } + }; + + // 手动安装成功 + const setInstallSuccess = (log: HostAgentLogResponse) => { + Modal.confirm({ + title: '修正状态', + titleAlign: 'start', + content: `确定要手动将安装记录修正为完成吗?`, + okText: '确定', + onOk: async () => { + try { + setLoading(true); + // 调用修改接口 + await updateAgentInstallStatus({ + id: log.id, + status: AgentLogStatus.SUCCESS, + message: '手动修正', + }); + log.status = AgentLogStatus.SUCCESS; + Message.success('状态已修正'); + } catch (e) { + } finally { + setLoading(false); + } + } + }); + }; + + // 更新告警开关 + const toggleAlarmSwitch = async (record: MonitorHostQueryResponse) => { + const dict = toggleDict(AlarmSwitchKey, record.alarmSwitch); + Modal.confirm({ + title: `${dict.label}确认`, + titleAlign: 'start', + content: `确定要${dict.label}告警功能吗?`, + okText: '确定', + onOk: async () => { + try { + setLoading(true); + const newSwitch = dict.value as number; + // 调用修改接口 + await updateMonitorHostAlarmSwitch({ + id: record.id, + alarmSwitch: newSwitch, + }); + record.alarmSwitch = newSwitch; + Message.success(`已${dict.label}`); + } catch (e) { + } finally { + setLoading(false); + } + } + }); + }; + + // 获取探针安装状态 + const pullInstallLogStatus = async () => { + // 获取安装中的记录 + const runningIdList = hosts.value.filter(s => s.installLog?.status === AgentLogStatus.WAIT || s.installLog?.status === AgentLogStatus.RUNNING) + .map(s => s.installLog?.id) + .filter(Boolean); + if (!runningIdList.length) { + return; + } + // 查询状态 + const { data } = await getAgentInstallLogStatus(runningIdList); + data.forEach(item => { + hosts.value.filter(s => s.installLog?.id === item.id).forEach(s => { + s.installLog.status = item.status; + s.installLog.message = item.message; + // 若安装成功则修改探针信息 + if (item.status === AgentLogStatus.SUCCESS && item.agentStatus) { + s.agentVersion = item.agentStatus.agentVersion; + s.latestVersion = item.agentStatus.latestVersion; + s.agentInstallStatus = item.agentStatus.agentInstallStatus; + s.agentOnlineStatus = item.agentStatus.agentOnlineStatus; + } + }); + }); + }; + + // 获取探针状态 + const getAgentStatus = async () => { + // 获取全部 hostId + const hostIds = hosts.value.map(s => s.hostId); + if (hostIds.length) { + try { + // 查询状态 + const { data } = await getHostAgentStatus(hostIds); + data.forEach(item => { + hosts.value.filter(s => s.hostId === item.id).forEach(s => { + s.agentVersion = item.agentVersion; + s.latestVersion = item.latestVersion; + s.agentInstallStatus = item.agentInstallStatus; + s.agentOnlineStatus = item.agentOnlineStatus; + }); + }); + } catch (e) { + } + } + }; + + // 获取指标信息 + const getHostMetrics = async () => { + // 获取全部已安装 agentKey + const agentKeys = hosts.value + .filter(s => s.agentInstallStatus === AgentInstallStatus.INSTALLED) + .map(s => s.agentKey) + .filter(Boolean); + if (agentKeys.length) { + try { + // 查询指标 + const { data } = await getMonitorHostMetrics(agentKeys); + data.forEach(item => { + hosts.value.filter(s => s.agentKey === item.agentKey).forEach(s => { + s.metricsData = item; + }); + }); + } catch (e) { + } + } + }; + + // 刷新指标 + const refreshMetrics = async () => { + // 加载状态信息 + await getAgentStatus(); + // 加载指标数据 + await getHostMetrics(); + // 设置刷新时间 + lastRefreshTime.value = Date.now(); + }; + + // 切换自动刷新 + const toggleAutoRefresh = async () => { + autoRefresh.value = !autoRefresh.value; + if (autoRefresh.value) { + // 开启自动刷新 + await openAutoRefresh(); + } else { + // 关闭自动刷新 + closeAutoRefresh(); + } + }; + + // 开启自动刷新 + const openAutoRefresh = async () => { + window.clearInterval(autoRefreshId.value); + if (!autoRefresh.value) { + return; + } + if (lastRefreshTime.value === 0) { + // 防止首次就刷新 + lastRefreshTime.value = 1; + } else if (Date.now() - lastRefreshTime.value > 60000) { + // 超过刷新的时间 + await refreshMetrics(); + } + // 设置自动刷新 + autoRefreshId.value = window.setInterval(refreshMetrics, 60000); + }; + + // 关闭自动刷新 + const closeAutoRefresh = () => { + window.clearInterval(autoRefreshId.value); + autoRefreshId.value = undefined; + }; + + onMounted(openAutoRefresh); + onActivated(openAutoRefresh); + onDeactivated(closeAutoRefresh); + onUnmounted(closeAutoRefresh); + + onMounted(() => { + window.clearInterval(fetchInstallStatusId.value); + fetchInstallStatusId.value = window.setInterval(pullInstallLogStatus, 5000); + }); + + onUnmounted(() => { + window.clearInterval(fetchInstallStatusId.value); + }); + + return { + autoRefresh, + openDetail, + installAgent, + setInstallSuccess, + toggleAlarmSwitch, + toggleAutoRefresh, + }; + +}; diff --git a/orion-visor-ui/src/views/system/setting/components/login-setting.vue b/orion-visor-ui/src/views/system/setting/components/login-setting.vue index 19ef5ab8..ec8e164c 100644 --- a/orion-visor-ui/src/views/system/setting/components/login-setting.vue +++ b/orion-visor-ui/src/views/system/setting/components/login-setting.vue @@ -35,7 +35,7 @@ checked-text="开启" unchecked-text="关闭" /> @@ -105,7 +105,7 @@ diff --git a/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-action-bar.vue b/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-action-bar.vue index 7d96f1fc..ba3a311e 100644 --- a/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-action-bar.vue +++ b/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-action-bar.vue @@ -206,7 +206,11 @@ // 选择文件回调 const onSelectFile = (files: Array) => { - fileList.value = [files[files.length - 1]]; + if (files.length) { + fileList.value = [files[files.length - 1]]; + } else { + fileList.value = []; + } }; // 上传文件 diff --git a/pom.xml b/pom.xml index fe8eacc0..0e981882 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ - 2.4.3 + 2.5.0 8 8 3.0.0-M5 diff --git a/sql/init-2-schema-tables.sql b/sql/init-2-schema-tables.sql index bad4420f..158bc5af 100644 --- a/sql/init-2-schema-tables.sql +++ b/sql/init-2-schema-tables.sql @@ -12,7 +12,7 @@ CREATE TABLE `_copy` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -35,7 +35,7 @@ CREATE TABLE `command_snippet` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user` (`user_id`) USING BTREE ) ENGINE = InnoDB @@ -60,7 +60,7 @@ CREATE TABLE `data_extra` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id` (`user_id`) USING BTREE, INDEX `idx_type_rel_id` (`type`, `rel_id`) USING BTREE @@ -86,7 +86,7 @@ CREATE TABLE `data_group` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_type_user` (`type`, `user_id`) USING BTREE ) ENGINE = InnoDB @@ -110,7 +110,7 @@ CREATE TABLE `data_group_rel` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_group_rel` (`group_id`, `rel_id`) USING BTREE, INDEX `idx_type_user` (`type`, `user_id`) USING BTREE @@ -135,7 +135,7 @@ CREATE TABLE `data_permission` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id` (`user_id`) USING BTREE, INDEX `idx_role_id` (`role_id`) USING BTREE, @@ -161,7 +161,7 @@ CREATE TABLE `dict_key` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_key` (`key_name`) USING BTREE ) ENGINE = InnoDB @@ -187,7 +187,7 @@ CREATE TABLE `dict_value` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_key_id` (`key_id`) USING BTREE ) ENGINE = InnoDB @@ -214,13 +214,13 @@ CREATE TABLE `exec_host_log` `log_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '日志路径', `script_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '脚本路径', `error_message` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '错误信息', - `start_time` datetime(3) NULL DEFAULT NULL COMMENT '执行开始时间', - `finish_time` datetime(3) NULL DEFAULT NULL COMMENT '执行结束时间', + `start_time` datetime(6) NULL DEFAULT NULL COMMENT '执行开始时间', + `finish_time` datetime(6) NULL DEFAULT NULL COMMENT '执行结束时间', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_log_id` (`log_id`) USING BTREE ) ENGINE = InnoDB @@ -251,7 +251,7 @@ CREATE TABLE `exec_job` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_exec_user_id` (`exec_user_id`) USING BTREE ) ENGINE = InnoDB @@ -273,7 +273,7 @@ CREATE TABLE `exec_job_host` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_job_id` (`job_id`) USING BTREE ) ENGINE = InnoDB @@ -301,13 +301,13 @@ CREATE TABLE `exec_log` `timeout` int(0) NULL DEFAULT NULL COMMENT '超时时间', `script_exec` tinyint(0) NULL DEFAULT 0 COMMENT '是否使用脚本执行', `status` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '执行状态', - `start_time` datetime(3) NULL DEFAULT NULL COMMENT '执行开始时间', - `finish_time` datetime(3) NULL DEFAULT NULL COMMENT '执行完成时间', + `start_time` datetime(6) NULL DEFAULT NULL COMMENT '执行开始时间', + `finish_time` datetime(6) NULL DEFAULT NULL COMMENT '执行完成时间', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id` (`user_id`) USING BTREE, INDEX `idx_source` (`source`, `source_id`) USING BTREE @@ -333,7 +333,7 @@ CREATE TABLE `exec_template` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -354,7 +354,7 @@ CREATE TABLE `exec_template_host` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `template_id` (`template_id`) USING BTREE ) ENGINE = InnoDB @@ -377,7 +377,7 @@ CREATE TABLE `favorite` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_type_user` (`type`, `user_id`) USING BTREE ) ENGINE = InnoDB @@ -399,7 +399,7 @@ CREATE TABLE `history_value` `after_value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '修改后', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -413,28 +413,60 @@ CREATE TABLE `history_value` DROP TABLE IF EXISTS `host`; CREATE TABLE `host` ( - `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id', - `types` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机类型', - `os_type` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '系统类型', - `arch_type` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '系统架构', - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机名称', - `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机编码', - `address` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机地址', - `status` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机状态', - `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机描述', - `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id', + `types` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机类型', + `os_type` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '系统类型', + `arch_type` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '系统架构', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机名称', + `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机编码', + `address` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机地址', + `status` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机状态', + `agent_key` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'agentKey', + `agent_version` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '探针版本', + `agent_install_status` tinyint(0) NULL DEFAULT NULL COMMENT '探针安装状态', + `agent_online_status` tinyint(0) NULL DEFAULT NULL COMMENT '探针在线状态', + `agent_online_change_time` datetime(0) NULL DEFAULT NULL COMMENT '探针切换在线状态时间', + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '主机描述', + `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_name` (`name`) USING BTREE + INDEX `idx_name` (`name`) USING BTREE, + INDEX `idx_agent_key` (`agent_key`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '主机' ROW_FORMAT = Dynamic; +-- ---------------------------- +-- Table structure for host_agent_log +-- ---------------------------- +DROP TABLE IF EXISTS `host_agent_log`; +CREATE TABLE `host_agent_log` +( + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id', + `host_id` bigint(0) NULL DEFAULT NULL COMMENT '主机id', + `agent_key` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'agentKey', + `type` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '类型', + `status` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '状态', + `message` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '消息', + `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_agent_key` (`agent_key`) USING BTREE, + INDEX `idx_host_id` (`host_id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_unicode_ci COMMENT = '主机探针日志' + ROW_FORMAT = Dynamic; + -- ---------------------------- -- Table structure for host_config -- ---------------------------- @@ -450,7 +482,7 @@ CREATE TABLE `host_config` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `host_type_idx` (`host_id`, `type`) USING BTREE ) ENGINE = InnoDB @@ -476,7 +508,7 @@ CREATE TABLE `host_identity` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -500,7 +532,7 @@ CREATE TABLE `host_key` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -508,6 +540,62 @@ CREATE TABLE `host_key` COLLATE = utf8mb4_unicode_ci COMMENT = '主机密钥' ROW_FORMAT = Dynamic; +-- ---------------------------- +-- Table structure for monitor_host +-- ---------------------------- +DROP TABLE IF EXISTS `monitor_host`; +CREATE TABLE `monitor_host` +( + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id', + `host_id` bigint(0) NULL DEFAULT NULL COMMENT '主机id', + `policy_id` bigint(0) NULL DEFAULT NULL COMMENT '策略id', + `agent_key` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'agent key', + `alarm_switch` tinyint(0) NULL DEFAULT 0 COMMENT '告警开关', + `owner_user_id` bigint(0) NULL DEFAULT NULL COMMENT '负责人id', + `owner_username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '负责人用户名', + `monitor_meta` json NULL COMMENT '监控元数据', + `monitor_config` json NULL COMMENT '监控配置', + `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_host_id` (`host_id`) USING BTREE, + INDEX `idx_policy_id` (`policy_id`) USING BTREE, + INDEX `idx_agent_key` (`agent_key`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_unicode_ci COMMENT = '监控主机' + ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for monitor_metrics +-- ---------------------------- +DROP TABLE IF EXISTS `monitor_metrics`; +CREATE TABLE `monitor_metrics` +( + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '指标名称', + `measurement` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '数据集', + `value` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '指标项', + `unit` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT 'NONE' COMMENT '单位', + `suffix` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '后缀', + `description` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '指标描述', + `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_value` (`value`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_unicode_ci COMMENT = '监控指标' + ROW_FORMAT = Dynamic; + -- ---------------------------- -- Table structure for operator_log -- ---------------------------- @@ -530,10 +618,10 @@ CREATE TABLE `operator_log` `error_message` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '错误信息', `return_value` json NULL COMMENT '返回值', `duration` int(0) NULL DEFAULT NULL COMMENT '操作时间', - `start_time` datetime(3) NULL DEFAULT NULL COMMENT '开始时间', - `end_time` datetime(3) NULL DEFAULT NULL COMMENT '结束时间', + `start_time` datetime(6) NULL DEFAULT NULL COMMENT '开始时间', + `end_time` datetime(6) NULL DEFAULT NULL COMMENT '结束时间', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id` (`user_id`) USING BTREE, INDEX `idx_type` (`type`) USING BTREE @@ -559,7 +647,7 @@ CREATE TABLE `path_bookmark` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user` (`user_id`) USING BTREE ) ENGINE = InnoDB @@ -583,7 +671,7 @@ CREATE TABLE `preference` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_type` (`user_id`, `type`) USING BTREE ) ENGINE = InnoDB @@ -615,7 +703,7 @@ CREATE TABLE `system_menu` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -640,7 +728,7 @@ CREATE TABLE `system_message` `receiver_username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '接收人用户名', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_receiver_classify` (`receiver_id`, `classify`) USING BTREE ) ENGINE = InnoDB @@ -664,7 +752,7 @@ CREATE TABLE `system_role` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -685,7 +773,7 @@ CREATE TABLE `system_role_menu` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_role` (`role_id`) USING BTREE ) ENGINE = InnoDB @@ -708,7 +796,7 @@ CREATE TABLE `system_setting` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_key` (`config_key`) USING BTREE ) ENGINE = InnoDB @@ -740,7 +828,7 @@ CREATE TABLE `system_user` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_username` (`username`) USING BTREE ) ENGINE = InnoDB @@ -762,7 +850,7 @@ CREATE TABLE `system_user_role` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user` (`user_id`) USING BTREE ) ENGINE = InnoDB @@ -784,7 +872,7 @@ CREATE TABLE `tag` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_type` (`type`) USING BTREE ) ENGINE = InnoDB @@ -808,7 +896,7 @@ CREATE TABLE `tag_rel` `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_tag` (`tag_id`) USING BTREE, INDEX `idx_type_rel` (`tag_type`, `rel_id`) USING BTREE @@ -833,12 +921,12 @@ CREATE TABLE `terminal_connect_log` `type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '类型', `status` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '状态', `session_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'sessionId', - `start_time` datetime(3) NULL DEFAULT NULL COMMENT '开始时间', - `end_time` datetime(3) NULL DEFAULT NULL COMMENT '结束时间', + `start_time` datetime(6) NULL DEFAULT NULL COMMENT '开始时间', + `end_time` datetime(6) NULL DEFAULT NULL COMMENT '结束时间', `extra_info` json NULL COMMENT '额外信息', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id` (`user_id`) USING BTREE, INDEX `idx_host_type` (`host_id`, `type`) USING BTREE, @@ -864,13 +952,13 @@ CREATE TABLE `upload_task` `file_count` int(0) NULL DEFAULT NULL COMMENT '文件数量', `host_count` int(0) NULL DEFAULT NULL COMMENT '主机数量', `extra_info` json NULL COMMENT '额外信息', - `start_time` datetime(3) NULL DEFAULT NULL COMMENT '开始时间', - `end_time` datetime(3) NULL DEFAULT NULL COMMENT '结束时间', + `start_time` datetime(6) NULL DEFAULT NULL COMMENT '开始时间', + `end_time` datetime(6) NULL DEFAULT NULL COMMENT '结束时间', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 @@ -892,14 +980,14 @@ CREATE TABLE `upload_task_file` `real_file_path` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '实际文件路径', `file_size` bigint(0) NULL DEFAULT NULL COMMENT '文件大小', `status` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '状态', - `start_time` datetime(3) NULL DEFAULT NULL COMMENT '开始时间', - `end_time` datetime(3) NULL DEFAULT NULL COMMENT '结束时间', + `start_time` datetime(6) NULL DEFAULT NULL COMMENT '开始时间', + `end_time` datetime(6) NULL DEFAULT NULL COMMENT '结束时间', `error_message` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '错误信息', `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', - `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', + `deleted` tinyint(0) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_task_id` (`task_id`) USING BTREE ) ENGINE = InnoDB diff --git a/sql/init-4-data.sql b/sql/init-4-data.sql index 68c34c13..7bf604c2 100644 --- a/sql/init-4-data.sql +++ b/sql/init-4-data.sql @@ -33,6 +33,44 @@ INSERT INTO `system_setting` VALUES (28, 'autoClear', 'autoClear_terminalLogKeep INSERT INTO `system_setting` VALUES (29, 'autoClear', 'autoClear_execLogEnabled', 'true', '2025-02-10 22:22:00', '2025-02-10 22:22:00', 'admin', 'admin', 0); INSERT INTO `system_setting` VALUES (30, 'autoClear', 'autoClear_terminalLogEnabled', 'true', '2025-02-10 22:22:00', '2025-02-10 22:22:00', 'admin', 'admin', 0); +-- 监控指标 +INSERT INTO `monitor_metrics` VALUES (1, 'CPU用户利用率', 'cpu', 'cpu_user_seconds_total', 'PER', NULL, '用户态使用时间', '2025-08-12 23:51:16', '2025-09-06 17:09:02', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (2, 'CPU系统利用率', 'cpu', 'cpu_system_seconds_total', 'PER', NULL, '内核态使用时间', '2025-08-13 00:23:56', '2025-09-06 17:09:02', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (3, 'CPU总利用率', 'cpu', 'cpu_total_seconds_total', 'PER', NULL, '用户态使用时间+内核态使用时间', '2025-08-13 00:24:30', '2025-09-06 17:09:02', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (4, '内存使用量', 'memory', 'mem_used_bytes_total', 'BYTES', NULL, '内存使用字节数', '2025-08-13 00:28:33', '2025-09-07 11:56:25', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (5, '内存使用率', 'memory', 'mem_used_percent', 'PER', NULL, '内存使用率', '2025-08-13 00:30:02', '2025-09-06 17:09:03', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (6, '交换内存使用量', 'memory', 'mem_swap_used_bytes_total', 'BYTES', NULL, '交换区使用字节数', '2025-08-13 00:31:14', '2025-09-07 11:56:21', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (7, '交换内存使用率', 'memory', 'mem_swap_used_percent', 'PER', NULL, '交换区使用率', '2025-08-13 00:31:48', '2025-09-06 17:09:03', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (8, '系统负载-1', 'load', 'load1', 'NONE', NULL, 'load1', '2025-08-13 00:33:01', '2025-08-13 00:33:01', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (9, '系统负载-5', 'load', 'load5', 'NONE', NULL, 'load5', '2025-08-13 00:33:24', '2025-08-13 00:33:24', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (10, '系统负载-15', 'load', 'load15', 'NONE', NULL, 'load15', '2025-08-13 00:33:45', '2025-08-13 00:33:45', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (11, '系统负载比-1', 'load', 'load1_core_ratio', 'NONE', NULL, '每个核心的平均load1 ', '2025-08-13 00:34:41', '2025-08-13 10:50:05', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (12, '系统负载比-5', 'load', 'load5_core_ratio', 'NONE', NULL, '每个核心的平均load5', '2025-08-13 00:35:12', '2025-08-13 10:50:05', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (13, '系统负载比-15', 'load', 'load15_core_ratio', 'NONE', NULL, '每个核心的平均load15', '2025-08-13 00:35:38', '2025-08-13 10:50:05', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (14, '磁盘使用量', 'disk', 'disk_fs_used_bytes', 'BYTES', NULL, '磁盘使用量', '2025-08-13 10:04:18', '2025-08-13 10:04:18', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (15, '磁盘使用率', 'disk', 'disk_fs_used_percent', 'PER', NULL, '磁盘使用率', '2025-08-13 10:04:18', '2025-09-06 17:09:03', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (16, 'inode使用率', 'disk', 'disk_fs_inodes_used_percent', 'PER', NULL, '磁盘inode使用率', '2025-08-13 10:04:18', '2025-09-06 17:09:03', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (17, 'IO总读取字节大小', 'io', 'disk_io_read_bytes_total', 'BYTES', NULL, '磁盘IO总读取字节大小', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (18, 'IO总写入字节大小', 'io', 'disk_io_write_bytes_total', 'BYTES', NULL, '磁盘IO总写入字节大小', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (19, 'IO总读取次数', 'io', 'disk_io_reads_total', 'COUNT', NULL, '磁盘IO总读取次数', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (20, 'IO总写入次数', 'io', 'disk_io_writes_total', 'COUNT', NULL, '磁盘IO总写入次数', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (21, 'IO每秒读取字节大小', 'io', 'disk_io_read_bytes_per_second', 'BYTES_S', NULL, '磁盘IO每秒读取字节大小', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (22, 'IO每秒写入字节大小', 'io', 'disk_io_write_bytes_per_second', 'BYTES_S', NULL, '磁盘IO每秒写入字节大小', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (23, 'IO每秒读取次数', 'io', 'disk_io_reads_per_second', 'COUNT_S', NULL, '磁盘IO每秒读取次数', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (24, 'IO每秒写入次数', 'io', 'disk_io_writes_per_second', 'COUNT_S', NULL, '磁盘IO每秒写入次数', '2025-08-13 10:10:29', '2025-08-13 10:10:29', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (25, '网卡总发送字节大小', 'network', 'net_recv_bytes_total', 'BITS', NULL, '网卡总发送字节大小', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (26, '网卡总接收字节大小', 'network', 'net_recv_bytes_total', 'BITS', NULL, '网卡总接收字节大小', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (27, '网卡总发送包数量', 'network', 'net_sent_packets_total', 'COUNT', NULL, '网卡总发送包数量', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (28, '网卡总接收包数量', 'network', 'net_recv_packets_total', 'COUNT', NULL, '网卡总接收包数量', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (29, '网卡每秒发送字节大小', 'network', 'net_sent_bytes_per_second', 'BITS_S', NULL, '网卡每秒发送字节大小', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (30, '网卡每秒接收字节大小', 'network', 'net_recv_bytes_per_second', 'BITS_S', NULL, '网卡每秒接收字节大小', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (31, '网卡每秒发送包数量', 'network', 'net_sent_packets_per_second', 'COUNT_S', NULL, '网卡每秒发送包数量', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (32, '网卡每秒接收包数量', 'network', 'net_recv_packets_per_second', 'COUNT_S', NULL, '网卡每秒接收包数量', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (33, 'TCP连接数', 'connections', 'net_tcp_connections', 'NONE', NULL, 'TCP连接数', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (34, 'UDP连接数', 'connections', 'net_udp_connections', 'NONE', NULL, 'UDP连接数', '2025-08-13 10:36:16', '2025-08-13 10:36:16', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (35, 'INET连接数', 'connections', 'net_inet_connections', 'NONE', NULL, 'INET连接数', '2025-08-13 10:36:17', '2025-08-13 10:36:17', 'admin', 'admin', 0); +INSERT INTO `monitor_metrics` VALUES (36, '总连接数', 'connections', 'net_all_connections', 'NONE', NULL, 'TCP + UDP + INET 连接数量', '2025-08-13 10:36:17', '2025-08-13 10:36:17', 'admin', 'admin', 0); + -- 字典项 INSERT INTO `dict_key` VALUES (1, 'operatorLogModule', 'STRING', '[]', '操作日志模块', '2023-10-21 02:04:22', '2023-10-30 14:11:38', 'admin', 'admin', 0); INSERT INTO `dict_key` VALUES (2, 'operatorLogType', 'STRING', '[]', '操作日志类型', '2023-10-21 02:06:04', '2023-10-21 02:06:04', 'admin', 'admin', 0); @@ -86,6 +124,15 @@ INSERT INTO `dict_key` VALUES (73, 'clipboardNormalize', 'STRING', '[]', '剪切 INSERT INTO `dict_key` VALUES (74, 'clipboardEncoding', 'STRING', '[]', '剪切板编码', '2025-06-19 01:22:44', '2025-06-19 01:22:44', 'admin', 'admin', 0); INSERT INTO `dict_key` VALUES (75, 'vcnCursor', 'STRING', '[]', 'vnc光标', '2025-06-19 01:22:54', '2025-06-19 01:22:54', 'admin', 'admin', 0); INSERT INTO `dict_key` VALUES (76, 'driveMountMode', 'STRING', '[{\"name\": \"help\", \"type\": \"STRING\"}]', '驱动挂载模式', '2025-06-28 22:53:20', '2025-06-28 22:53:20', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (77, 'metricsMeasurement', 'STRING', '[]', '监控指标类型', '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (78, 'metricsUnit', 'STRING', '[]', '监控指标单位', '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (79, 'monitorAlarmSwitch', 'INTEGER', '[]', '监控告警开关', '2025-08-23 17:07:21', '2025-09-01 23:32:34', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (80, 'agentOnlineStatus', 'INTEGER', '[{\"name\": \"status\", \"type\": \"STRING\"}, {\"name\": \"color\", \"type\": \"COLOR\"}, {\"name\": \"icon\", \"type\": \"STRING\"}]', '探针在线状态', '2025-08-23 17:07:21', '2025-08-27 07:48:53', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (81, 'agentInstallStatus', 'INTEGER', '[]', '探针安装状态', '2025-08-24 22:48:54', '2025-08-27 07:48:17', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (82, 'agentLogType', 'STRING', '[]', '探针日志类型', '2025-08-31 12:16:24', '2025-08-31 12:16:24', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (83, 'agentLogStatus', 'STRING', '[{\"name\": \"color\", \"type\": \"STRING\"}, {\"name\": \"loading\", \"type\": \"BOOLEAN\"}, {\"name\": \"installLabel\", \"type\": \"STRING\"}]', '探针日志状态', '2025-08-31 12:16:24', '2025-09-01 23:18:18', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (84, 'metricsChartRange', 'STRING', '[{\"name\": \"window\", \"type\": \"STRING\"}]', '指标图表区间', '2025-09-06 23:32:21', '2025-09-06 23:32:21', 'admin', 'admin', 0); +INSERT INTO `dict_key` VALUES (85, 'metricsAggregate', 'STRING', '[]', '指标聚合函数', '2025-09-07 16:54:22', '2025-09-07 16:54:22', 'admin', 'admin', 0); -- 字典值 INSERT INTO `dict_value` VALUES (3, 4, 'systemMenuType', '1', '父菜单', '{}', 10, '2023-10-26 15:58:59', '2023-10-26 15:58:59', 'admin', 'admin', 0); @@ -347,6 +394,12 @@ INSERT INTO `dict_value` VALUES (366, 53, 'terminalTheme', '{\"background\":\"#1 INSERT INTO `dict_value` VALUES (385, 57, 'hostStatus', 'ENABLED', '启用', '{\"color\": \"arcoblue\", \"status\": \"normal\", \"buttonStatus\": \"normal\"}', 10, '2024-07-17 12:51:10', '2024-07-22 16:53:53', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (386, 57, 'hostStatus', 'DISABLED', '停用', '{\"color\": \"orangered\", \"status\": \"error\", \"buttonStatus\": \"danger\"}', 20, '2024-07-17 12:51:10', '2024-07-22 16:53:46', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (387, 58, 'hostType', 'SSH', 'SSH', '{\"color\": \"arcoblue\"}', 10, '2024-07-17 12:51:10', '2024-07-17 15:57:24', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (388, 2, 'operatorLogType', 'terminal:sftp-chown', '修改文件归属', '{}', 73, '2024-02-23 17:54:37', '2024-10-16 10:41:59', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (389, 2, 'operatorLogType', 'terminal:sftp-chgrp', '修改文件分组', '{}', 76, '2024-02-23 17:54:37', '2024-10-16 10:41:59', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (390, 2, 'operatorLogType', 'terminal:sftp-get-content', '查看文件内容', '{}', 79, '2024-02-23 17:54:37', '2024-10-16 10:41:59', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (391, 33, 'terminalFileOperatorType', 'terminal:sftp-chown', '修改文件归属', '{}', 63, '2024-03-05 16:52:18', '2025-06-29 12:30:54', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (392, 33, 'terminalFileOperatorType', 'terminal:sftp-chgrp', '修改文件分组', '{}', 66, '2024-03-05 16:52:18', '2025-06-29 12:30:55', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (393, 33, 'terminalFileOperatorType', 'terminal:sftp-get-content', '查看文件内容', '{}', 69, '2024-03-05 16:52:18', '2025-06-29 12:30:55', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (401, 43, 'messageType', 'LOGIN_FAILED', '登录失败', '{\"tagColor\": \"red\", \"tagLabel\": \"登录失败\", \"tagVisible\": true, \"redirectComponent\": \"0\"}', 50, '2024-08-19 18:34:27', '2024-08-19 18:34:27', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (402, 53, 'terminalTheme', '{\"background\":\"#101216\",\"foreground\":\"#8B949E\",\"cursor\":\"#C9D1D9\",\"selectionBackground\":\"#3B5070\",\"black\":\"#000000\",\"red\":\"#F78166\",\"green\":\"#56D364\",\"yellow\":\"#E3B341\",\"blue\":\"#6CA4F8\",\"cyan\":\"#2B7489\",\"white\":\"#FFFFFF\",\"brightBlack\":\"#4D4D4D\",\"brightRed\":\"#F78166\",\"brightGreen\":\"#56D364\",\"brightYellow\":\"#E3B341\",\"brightBlue\":\"#6CA4F8\",\"brightCyan\":\"#2B7489\",\"brightWhite\":\"#FFFFFF\"}', 'GitHub Dark', '{\"dark\": true}', 150, '2024-08-19 18:53:14', '2024-08-19 18:53:20', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (403, 53, 'terminalTheme', '{\"background\":\"#F4F4F4\",\"foreground\":\"#3E3E3E\",\"cursor\":\"#3F3F3F\",\"selectionBackground\":\"#A9C1E2\",\"black\":\"#3E3E3E\",\"red\":\"#970B16\",\"green\":\"#07962A\",\"yellow\":\"#F8EEC7\",\"blue\":\"#003E8A\",\"cyan\":\"#89D1EC\",\"white\":\"#FFFFFF\",\"brightBlack\":\"#666666\",\"brightRed\":\"#DE0000\",\"brightGreen\":\"#87D5A2\",\"brightYellow\":\"#F1D007\",\"brightBlue\":\"#2E6CBA\",\"brightCyan\":\"#1CFAFE\",\"brightWhite\":\"#FFFFFF\"}', 'Github', '{\"dark\": false}', 160, '2024-08-19 18:53:39', '2024-08-19 18:53:39', 'admin', 'admin', 0); @@ -429,6 +482,58 @@ INSERT INTO `dict_value` VALUES (518, 33, 'terminalFileOperatorType', 'terminal: INSERT INTO `dict_value` VALUES (519, 33, 'terminalFileOperatorType', 'terminal:rdp-download', '下载文件(RDP)', '{}', 110, '2024-03-05 16:52:18', '2025-06-29 12:28:52', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (520, 58, 'hostType', 'VNC', 'VNC', '{\"color\": \"pinkpurple\"}', 30, '2025-07-01 16:02:01', '2025-07-03 00:56:56', 'admin', 'admin', 0); INSERT INTO `dict_value` VALUES (521, 27, 'terminalConnectType', 'VNC', 'VNC', '{\"color\": \"pinkpurple\"}', 40, '2025-07-01 16:02:21', '2025-07-03 00:56:54', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (522, 1, 'operatorLogModule', 'monitor:monitor-metrics', '监控指标', '{}', 2160, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (523, 2, 'operatorLogType', 'monitor-metrics:create', '创建监控指标', '{}', 10, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (524, 2, 'operatorLogType', 'monitor-metrics:update', '更新监控指标', '{}', 20, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (525, 2, 'operatorLogType', 'monitor-metrics:delete', '删除监控指标', '{}', 30, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (526, 77, 'metricsMeasurement', 'cpu', 'cpu', '{}', 10, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (527, 77, 'metricsMeasurement', 'memory', '内存', '{}', 20, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (528, 77, 'metricsMeasurement', 'load', '负载', '{}', 30, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (529, 77, 'metricsMeasurement', 'disk', '磁盘', '{}', 40, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (530, 77, 'metricsMeasurement', 'io', 'io', '{}', 50, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (531, 77, 'metricsMeasurement', 'network', '网络', '{}', 60, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (532, 77, 'metricsMeasurement', 'connections', '连接数', '{}', 70, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (533, 78, 'metricsUnit', 'BYTES', '字节', '{}', 10, '2025-08-12 23:31:00', '2025-08-12 23:31:00', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (534, 78, 'metricsUnit', 'BYTES_S', '字节/秒', '{}', 40, '2025-08-12 23:31:00', '2025-08-13 00:17:12', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (535, 78, 'metricsUnit', 'BITS_S', '比特/秒', '{}', 50, '2025-08-12 23:31:00', '2025-08-13 00:17:14', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (536, 78, 'metricsUnit', 'TEXT', '文本', '{}', 100, '2025-08-12 23:31:00', '2025-08-15 16:38:56', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (537, 78, 'metricsUnit', 'NONE', '无', '{}', 110, '2025-08-12 23:31:00', '2025-08-15 16:38:56', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (538, 78, 'metricsUnit', 'SECONDS', '秒', '{}', 30, '2025-08-12 23:55:17', '2025-08-13 00:17:07', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (539, 78, 'metricsUnit', 'COUNT', '次', '{}', 20, '2025-08-13 00:15:15', '2025-08-13 00:15:50', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (540, 78, 'metricsUnit', 'COUNT_S', '次/秒', '{}', 60, '2025-08-13 00:15:38', '2025-08-13 00:17:20', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (541, 78, 'metricsUnit', 'BITS', '比特', '{}', 15, '2025-08-13 10:34:27', '2025-08-13 10:34:27', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (542, 78, 'metricsUnit', 'PER', '百分比', '{}', 90, '2025-08-13 10:34:27', '2025-08-13 10:34:27', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (543, 79, 'monitorAlarmSwitch', '0', '关闭', '{}', 10, '2025-08-23 17:07:21', '2025-09-01 23:32:55', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (544, 79, 'monitorAlarmSwitch', '1', '开启', '{}', 20, '2025-08-23 17:07:21', '2025-09-01 23:32:50', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (545, 80, 'agentOnlineStatus', '0', '离线', '{\"icon\": \"icon-close\", \"color\": \"red\", \"status\": \"error\"}', 10, '2025-08-23 17:07:21', '2025-08-27 07:48:50', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (546, 80, 'agentOnlineStatus', '1', '在线', '{\"icon\": \"icon-check\", \"color\": \"green\", \"status\": \"pass\"}', 20, '2025-08-23 17:07:21', '2025-08-27 07:48:50', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (547, 1, 'operatorLogModule', 'monitor:monitor-host', '监控主机', '{}', 2170, '2025-08-23 17:08:17', '2025-08-23 17:08:17', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (548, 2, 'operatorLogType', 'monitor-host:update', '更新监控配置', '{}', 10, '2025-08-23 17:08:17', '2025-08-23 17:08:17', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (549, 2, 'operatorLogType', 'monitor-host:update-switch', '更新监控开关', '{}', 20, '2025-08-23 17:08:17', '2025-08-23 17:08:17', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (550, 81, 'agentInstallStatus', '0', '未安装', '{}', 10, '2025-08-24 22:49:27', '2025-08-27 07:48:12', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (551, 81, 'agentInstallStatus', '1', '已安装', '{}', 20, '2025-08-24 22:49:34', '2025-08-27 07:48:12', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (553, 82, 'agentLogType', 'OFFLINE', '下线', '{}', 10, '2025-08-31 12:16:24', '2025-08-31 12:16:24', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (554, 82, 'agentLogType', 'ONLINE', '上线', '{}', 20, '2025-08-31 12:16:24', '2025-08-31 12:16:24', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (555, 82, 'agentLogType', 'INSTALL', '安装', '{}', 30, '2025-08-31 12:16:24', '2025-08-31 12:16:24', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (556, 82, 'agentLogType', 'START', '启动', '{}', 40, '2025-08-31 12:16:24', '2025-08-31 12:16:24', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (557, 82, 'agentLogType', 'STOP', '停止', '{}', 50, '2025-08-31 12:16:24', '2025-08-31 12:16:24', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (558, 83, 'agentLogStatus', 'WAIT', '等待中', '{\"color\": \"green\", \"loading\": true, \"installLabel\": \"等待安装\"}', 10, '2025-08-31 12:16:24', '2025-09-01 23:18:53', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (559, 83, 'agentLogStatus', 'RUNNING', '运行中', '{\"color\": \"green\", \"loading\": true, \"installLabel\": \"安装中\"}', 20, '2025-08-31 12:16:24', '2025-09-01 23:18:48', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (560, 83, 'agentLogStatus', 'SUCCESS', '成功', '{\"color\": \"arcoblue\", \"loading\": false, \"installLabel\": \"安装成功\"}', 30, '2025-08-31 12:16:24', '2025-09-01 23:18:41', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (561, 83, 'agentLogStatus', 'FAILED', '失败', '{\"color\": \"red\", \"loading\": false, \"installLabel\": \"安装失败\"}', 40, '2025-08-31 12:16:24', '2025-09-01 23:18:36', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (562, 2, 'operatorLogType', 'host:install-agent', '安装主机探针', '{}', 110, '2025-08-31 20:18:44', '2025-08-31 20:18:44', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (563, 2, 'operatorLogType', 'host:update-install-status', '修改探针安装状态', '{}', 120, '2025-08-31 20:18:44', '2025-08-31 20:18:44', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (564, 2, 'operatorLogType', 'host:upload-agent-release', '上传探针发布包', '{}', 130, '2025-08-31 20:18:44', '2025-09-02 07:21:42', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (565, 84, 'metricsChartRange', '-30m', '30分钟', '{\"window\": \"1m\"}', 10, '2025-09-06 23:33:13', '2025-09-07 01:45:01', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (566, 84, 'metricsChartRange', '-2h', '2小时', '{\"window\": \"1m,5m\"}', 20, '2025-09-06 23:33:49', '2025-09-07 01:44:55', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (567, 84, 'metricsChartRange', '-24h', '24小时', '{\"window\": \"5m,1h\"}', 30, '2025-09-06 23:34:28', '2025-09-07 01:44:48', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (568, 84, 'metricsChartRange', '-7d', '1周', '{\"window\": \"1h,12h,24h\"}', 40, '2025-09-06 23:35:37', '2025-09-07 01:44:43', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (569, 84, 'metricsChartRange', '-30d', '30天', '{\"window\": \"1d\"}', 50, '2025-09-06 23:36:17', '2025-09-07 01:44:38', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (570, 84, 'metricsChartRange', '-60d', '60天', '{\"window\": \"1d\"}', 60, '2025-09-06 23:36:31', '2025-09-07 01:44:35', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (571, 85, 'metricsAggregate', 'mean', '平均值', '{}', 10, '2025-09-07 16:54:35', '2025-09-07 16:54:35', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (572, 85, 'metricsAggregate', 'max', '最大值', '{}', 20, '2025-09-07 16:54:41', '2025-09-07 16:54:59', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (573, 85, 'metricsAggregate', 'min', '最小值', '{}', 30, '2025-09-07 16:55:19', '2025-09-07 16:55:19', 'admin', 'admin', 0); +INSERT INTO `dict_value` VALUES (574, 85, 'metricsAggregate', 'sum', '总和', '{}', 40, '2025-09-07 16:55:27', '2025-09-07 16:55:27', 'admin', 'admin', 0); -- 菜单配置 INSERT INTO `system_menu` VALUES (1, 0, '工作台', NULL, 1, 10, 1, 1, 1, 0, 'IconComputer', NULL, 'workplace', '2023-07-28 10:51:50', '2024-08-11 00:05:44', 'admin', 'admin', 0); @@ -550,3 +655,15 @@ INSERT INTO `system_menu` VALUES (202, 198, '清理上传日志', 'exec:upload-t INSERT INTO `system_menu` VALUES (203, 12, '系统设置', NULL, 2, 40, 1, 1, 1, 0, 'IconSettings', NULL, 'systemSetting', '2024-06-17 20:46:15', '2024-06-17 20:46:15', 'admin', 'admin', 0); INSERT INTO `system_menu` VALUES (265, 203, '更新系统设置', 'infra:system-setting:update', 3, 20, 1, 1, 1, 0, NULL, NULL, NULL, '2024-10-09 19:25:28', '2025-01-02 22:14:45', 'admin', 'admin', 0); INSERT INTO `system_menu` VALUES (271, 177, '修改任务执行用户', 'exec:exec-job:update-exec-user', 3, 45, 1, 1, 1, 0, NULL, NULL, NULL, '2024-12-13 00:18:13', '2024-12-13 00:18:13', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (282, 0, '系统监控', NULL, 1, 350, 1, 1, 1, 0, 'IconComputer', NULL, 'monitorModule', '2025-08-12 23:31:02', '2025-08-12 23:38:49', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (283, 282, '监控指标', NULL, 2, 110, 1, 1, 1, 0, 'IconList', NULL, 'metrics', '2025-08-12 23:31:02', '2025-09-03 23:03:30', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (284, 283, '查询监控指标', 'monitor:monitor-metrics:query', 3, 10, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-12 23:31:02', '2025-08-12 23:31:02', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (285, 283, '创建监控指标', 'monitor:monitor-metrics:create', 3, 20, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-12 23:31:02', '2025-08-12 23:31:02', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (286, 283, '修改监控指标', 'monitor:monitor-metrics:update', 3, 30, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-12 23:31:02', '2025-08-12 23:31:02', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (287, 283, '删除监控指标', 'monitor:monitor-metrics:delete', 3, 40, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-12 23:31:02', '2025-08-12 23:31:02', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (288, 282, '主机监控', NULL, 2, 10, 1, 1, 1, 0, 'IconComputer', NULL, 'monitorHost', '2025-08-23 17:02:02', '2025-08-24 22:47:03', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (289, 288, '查询监控主机', 'monitor:monitor-host:query', 3, 10, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-23 17:02:02', '2025-08-23 17:02:02', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (290, 288, '修改监控主机', 'monitor:monitor-host:update', 3, 20, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-23 17:02:02', '2025-08-23 17:03:56', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (292, 288, '修改告警开关', 'monitor:monitor-host:update-switch', 3, 30, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-23 17:02:02', '2025-08-23 17:04:31', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (293, 64, '安装探针', 'asset:host:install-agent', 3, 110, 1, 1, 1, 0, NULL, NULL, NULL, '2025-08-31 20:18:14', '2025-08-31 20:18:14', 'admin', 'admin', 0); +INSERT INTO `system_menu` VALUES (294, 282, '主机监控详情', NULL, 2, 20, 0, 1, 1, 0, 'IconComputer', '', 'monitorDetail', '2025-09-03 23:03:20', '2025-09-03 23:03:55', 'admin', 'admin', 0);