@@ -19,6 +19,10 @@ services:
|
|||||||
DEMO_MODE: false
|
DEMO_MODE: false
|
||||||
volumes:
|
volumes:
|
||||||
- /data/orion-visor-space/docker-volumes/service/root-orion:/root/orion
|
- /data/orion-visor-space/docker-volumes/service/root-orion:/root/orion
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 65536
|
||||||
|
hard: 65536
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD", "curl", "http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health" ]
|
test: [ "CMD", "curl", "http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health" ]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
version: '3.3'
|
version: '3.3'
|
||||||
|
|
||||||
# latest = 2.5.2
|
# latest = 2.5.1
|
||||||
|
|
||||||
# 支持以下源
|
# 支持以下源
|
||||||
# lijiahangmax/*
|
# lijiahangmax/*
|
||||||
@@ -27,10 +27,6 @@ services:
|
|||||||
privileged: true
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- "9200:9200"
|
- "9200:9200"
|
||||||
ulimits:
|
|
||||||
nofile:
|
|
||||||
soft: 65536
|
|
||||||
hard: 65536
|
|
||||||
environment:
|
environment:
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
||||||
MYSQL_HOST: ${MYSQL_HOST:-mysql}
|
MYSQL_HOST: ${MYSQL_HOST:-mysql}
|
||||||
@@ -57,6 +53,10 @@ services:
|
|||||||
DEMO_MODE: ${DEMO_MODE:-false}
|
DEMO_MODE: ${DEMO_MODE:-false}
|
||||||
volumes:
|
volumes:
|
||||||
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion
|
- ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 65536
|
||||||
|
hard: 65536
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD", "curl", "http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health" ]
|
test: [ "CMD", "curl", "http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health" ]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ set -e
|
|||||||
source ./project-build.sh "$@"
|
source ./project-build.sh "$@"
|
||||||
|
|
||||||
# 版本号
|
# 版本号
|
||||||
version=2.5.2
|
version=2.5.3
|
||||||
# 是否推送镜像
|
# 是否推送镜像
|
||||||
push_image=false
|
push_image=false
|
||||||
# 是否构建 latest
|
# 是否构建 latest
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -e
|
|||||||
# DockerContext: orion-visor
|
# DockerContext: orion-visor
|
||||||
|
|
||||||
# 版本号
|
# 版本号
|
||||||
version=2.5.2
|
version=2.5.3
|
||||||
# 是否构建 service
|
# 是否构建 service
|
||||||
export build_service=false
|
export build_service=false
|
||||||
# 是否构建 ui
|
# 是否构建 ui
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public interface AppConst extends OrionConst {
|
|||||||
/**
|
/**
|
||||||
* 同 ${orion.version} 迭代时候需要手动更改
|
* 同 ${orion.version} 迭代时候需要手动更改
|
||||||
*/
|
*/
|
||||||
String VERSION = "2.5.2";
|
String VERSION = "2.5.3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同 ${spring.application.name}
|
* 同 ${spring.application.name}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ package org.dromara.visor.common.constant;
|
|||||||
*/
|
*/
|
||||||
public interface AutoConfigureOrderConst {
|
public interface AutoConfigureOrderConst {
|
||||||
|
|
||||||
|
int FRAMEWORK_EXECUTOR = Integer.MIN_VALUE + 1000;
|
||||||
|
|
||||||
int FRAMEWORK_WEB = Integer.MIN_VALUE + 1100;
|
int FRAMEWORK_WEB = Integer.MIN_VALUE + 1100;
|
||||||
|
|
||||||
int FRAMEWORK_SECURITY = Integer.MIN_VALUE + 1200;
|
int FRAMEWORK_SECURITY = Integer.MIN_VALUE + 1200;
|
||||||
@@ -65,8 +67,6 @@ public interface AutoConfigureOrderConst {
|
|||||||
|
|
||||||
int FRAMEWORK_JOB_QUARTZ = Integer.MIN_VALUE + 2610;
|
int FRAMEWORK_JOB_QUARTZ = Integer.MIN_VALUE + 2610;
|
||||||
|
|
||||||
int FRAMEWORK_JOB_ASYNC = Integer.MIN_VALUE + 2620;
|
|
||||||
|
|
||||||
int FRAMEWORK_BIZ_PUSH = Integer.MIN_VALUE + 2700;
|
int FRAMEWORK_BIZ_PUSH = Integer.MIN_VALUE + 2700;
|
||||||
|
|
||||||
int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 7000;
|
int FRAMEWORK_BIZ_OPERATOR_LOG = Integer.MIN_VALUE + 7000;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<url>https://github.com/dromara/orion-visor</url>
|
<url>https://github.com/dromara/orion-visor</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>2.5.2</revision>
|
<revision>2.5.3</revision>
|
||||||
<spring.boot.version>2.7.17</spring.boot.version>
|
<spring.boot.version>2.7.17</spring.boot.version>
|
||||||
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
|
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
|
||||||
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
|
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
|
||||||
@@ -106,6 +106,11 @@
|
|||||||
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-websocket</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-websocket</artifactId>
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ public class PushMessageEventListener implements ApplicationListener<PushMessage
|
|||||||
this.pushServiceMap = pushServiceMap;
|
this.pushServiceMap = pushServiceMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME
|
@Async("pushExecutor")
|
||||||
@Async("asyncExecutor")
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(PushMessageEvent event) {
|
public void onApplicationEvent(PushMessageEvent event) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-framework</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<description>项目线程池配置包</description>
|
||||||
|
<url>https://github.com/dromara/orion-visor</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- common -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -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.framework.executor.configuration;
|
||||||
|
|
||||||
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
|
import org.dromara.visor.framework.executor.configuration.config.ExecutorsConfig;
|
||||||
|
import org.dromara.visor.framework.executor.core.context.ExecutorContext;
|
||||||
|
import org.dromara.visor.framework.executor.core.utils.ExecutorUtils;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
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.scheduling.annotation.EnableAsync;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目线程池配置
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/16 14:34
|
||||||
|
*/
|
||||||
|
@EnableAsync
|
||||||
|
@AutoConfiguration
|
||||||
|
@EnableConfigurationProperties({ExecutorsConfig.class})
|
||||||
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_EXECUTOR)
|
||||||
|
public class OrionExecutorAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建线程池上下文
|
||||||
|
*
|
||||||
|
* @param executorsConfig executorsConfig
|
||||||
|
* @param beanFactory beanFactory
|
||||||
|
* @return 线程池上下文
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public ExecutorContext executorContext(ExecutorsConfig executorsConfig,
|
||||||
|
ConfigurableBeanFactory beanFactory) {
|
||||||
|
// 创建上下文
|
||||||
|
ExecutorContext context = new ExecutorContext(executorsConfig, beanFactory);
|
||||||
|
Map<String, ThreadPoolTaskExecutor> executorMap = context.init();
|
||||||
|
// 获取线程池列表
|
||||||
|
ExecutorUtils.setExecutors(executorMap);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* 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.executor.configuration.config;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.define.thread.RejectPolicy;
|
||||||
|
import cn.orionsec.kit.lang.utils.Systems;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程池配置
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/16 10:51
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ExecutorConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用
|
||||||
|
*/
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用 MDC
|
||||||
|
*/
|
||||||
|
private boolean mdc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心线程数
|
||||||
|
*/
|
||||||
|
private int corePoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大线程数
|
||||||
|
*/
|
||||||
|
private int maxPoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 队列容量
|
||||||
|
*/
|
||||||
|
private int queueCapacity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空闲线程存活时间
|
||||||
|
*/
|
||||||
|
private int keepAliveSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许核心线程超时
|
||||||
|
*/
|
||||||
|
private boolean allowCoreTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用同步队列
|
||||||
|
*/
|
||||||
|
private boolean synchronousQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程名称前缀
|
||||||
|
*/
|
||||||
|
private String threadNamePrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拒绝策略
|
||||||
|
*/
|
||||||
|
private RejectPolicy rejectPolicy;
|
||||||
|
|
||||||
|
public ExecutorConfig() {
|
||||||
|
this.enabled = true;
|
||||||
|
this.corePoolSize = Systems.PROCESS_NUM;
|
||||||
|
this.maxPoolSize = Systems.PROCESS_NUM;
|
||||||
|
this.queueCapacity = 100;
|
||||||
|
this.keepAliveSeconds = 300;
|
||||||
|
this.rejectPolicy = RejectPolicy.CALLER_RUNS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,47 +20,27 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.dromara.visor.framework.job.configuration.config;
|
package org.dromara.visor.framework.executor.configuration.config;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 线程池配置类
|
* 线程池配置
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2023/7/10 15:49
|
* @since 2025/9/16 16:21
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ConfigurationProperties(prefix = "orion.async.executor")
|
@ConfigurationProperties(prefix = "app")
|
||||||
public class AsyncExecutorConfig {
|
public class ExecutorsConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 核心线程数量
|
* 线程池配置
|
||||||
*/
|
*/
|
||||||
private int corePoolSize;
|
private Map<String, ExecutorConfig> executors;
|
||||||
|
|
||||||
/**
|
|
||||||
* 最大线程数量
|
|
||||||
*/
|
|
||||||
private int maxPoolSize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 队列容量
|
|
||||||
*/
|
|
||||||
private int queueCapacity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 活跃时间
|
|
||||||
*/
|
|
||||||
private int keepAliveSeconds;
|
|
||||||
|
|
||||||
public AsyncExecutorConfig() {
|
|
||||||
this.corePoolSize = 8;
|
|
||||||
this.maxPoolSize = 16;
|
|
||||||
this.queueCapacity = 200;
|
|
||||||
this.keepAliveSeconds = 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.executor.core.context;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.define.thread.RejectPolicy;
|
||||||
|
import cn.orionsec.kit.lang.utils.Strings;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.visor.common.thread.ThreadPoolMdcTaskExecutor;
|
||||||
|
import org.dromara.visor.framework.executor.configuration.config.ExecutorConfig;
|
||||||
|
import org.dromara.visor.framework.executor.configuration.config.ExecutorsConfig;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行器上下文
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/16 16:28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ExecutorContext {
|
||||||
|
|
||||||
|
private final ExecutorsConfig executorsConfig;
|
||||||
|
|
||||||
|
private final ConfigurableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
public ExecutorContext(ExecutorsConfig executorsConfig, ConfigurableBeanFactory beanFactory) {
|
||||||
|
this.executorsConfig = executorsConfig;
|
||||||
|
this.beanFactory = beanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*
|
||||||
|
* @return executorMap
|
||||||
|
*/
|
||||||
|
public Map<String, ThreadPoolTaskExecutor> init() {
|
||||||
|
log.info("--------- Executors init start --------- ");
|
||||||
|
Map<String, ThreadPoolTaskExecutor> executorMap = new HashMap<>();
|
||||||
|
executorsConfig.getExecutors().forEach((beanName, config) -> {
|
||||||
|
String executorName = Strings.leftPad(beanName, 30);
|
||||||
|
// 是否启用
|
||||||
|
if (!config.isEnabled()) {
|
||||||
|
log.info("Executor [{}] is disabled.", executorName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 创建线程池
|
||||||
|
ThreadPoolTaskExecutor executor = this.createTaskExecutor(config);
|
||||||
|
// 注册到容器中
|
||||||
|
beanFactory.registerSingleton(beanName, executor);
|
||||||
|
executorMap.put(beanName, executor);
|
||||||
|
log.info("Executor [{}] init success. {}", executorName, JSON.toJSONString(config));
|
||||||
|
});
|
||||||
|
log.info("--------- Executors init end --------- ");
|
||||||
|
return executorMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建线程池
|
||||||
|
*
|
||||||
|
* @param config config
|
||||||
|
*/
|
||||||
|
private ThreadPoolTaskExecutor createTaskExecutor(ExecutorConfig config) {
|
||||||
|
// 创建线程池
|
||||||
|
ThreadPoolTaskExecutor executor;
|
||||||
|
if (config.isMdc()) {
|
||||||
|
executor = new ThreadPoolMdcTaskExecutor();
|
||||||
|
} else {
|
||||||
|
executor = new ThreadPoolTaskExecutor();
|
||||||
|
}
|
||||||
|
// 同步队列
|
||||||
|
if (config.isSynchronousQueue()) {
|
||||||
|
config.setCorePoolSize(0);
|
||||||
|
config.setMaxPoolSize(Integer.MAX_VALUE);
|
||||||
|
config.setQueueCapacity(0);
|
||||||
|
config.setRejectPolicy(RejectPolicy.ABORT);
|
||||||
|
}
|
||||||
|
// 设置参数
|
||||||
|
executor.setCorePoolSize(config.getCorePoolSize());
|
||||||
|
executor.setMaxPoolSize(config.getMaxPoolSize());
|
||||||
|
executor.setQueueCapacity(config.getQueueCapacity());
|
||||||
|
executor.setThreadNamePrefix(config.getThreadNamePrefix());
|
||||||
|
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
|
||||||
|
executor.setAllowCoreThreadTimeOut(config.isAllowCoreTimeout());
|
||||||
|
executor.setRejectedExecutionHandler(config.getRejectPolicy().getHandler());
|
||||||
|
// 设置等待所有任务执行结束再关闭线程池
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
executor.setAwaitTerminationSeconds(60);
|
||||||
|
// 初始化
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.executor.core.utils;
|
||||||
|
|
||||||
|
import cn.orionsec.kit.lang.able.Executable;
|
||||||
|
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||||
|
import cn.orionsec.kit.lang.utils.collect.Maps;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程池工具类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/9/16 16:34
|
||||||
|
*/
|
||||||
|
public class ExecutorUtils {
|
||||||
|
|
||||||
|
private static Map<String, ThreadPoolTaskExecutor> executorMap;
|
||||||
|
|
||||||
|
private ExecutorUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线程池
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @return executor
|
||||||
|
*/
|
||||||
|
public static ThreadPoolTaskExecutor getExecutor(String name) {
|
||||||
|
return executorMap.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param runnable runnable
|
||||||
|
*/
|
||||||
|
public static void execute(String name, Runnable runnable) {
|
||||||
|
getExecutor(name).execute(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param executable executable
|
||||||
|
*/
|
||||||
|
public static void execute(String name, Executable executable) {
|
||||||
|
getExecutor(name).execute(executable::exec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setExecutors(Map<String, ThreadPoolTaskExecutor> executorMap) {
|
||||||
|
if (ExecutorUtils.executorMap != null) {
|
||||||
|
// unmodified
|
||||||
|
throw Exceptions.state();
|
||||||
|
}
|
||||||
|
ExecutorUtils.executorMap = Maps.unmodified(executorMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*",
|
||||||
|
"type": "org.dromara.visor.framework.executor.configuration.config.ExecutorConfig",
|
||||||
|
"sourceType": "org.dromara.visor.framework.executor.configuration.config.ExecutorConfig",
|
||||||
|
"description": "线程池配置项."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "orion.executors",
|
||||||
|
"type": "java.util.Map<java.lang.String,org.dromara.visor.framework.executor.configuration.config.ExecutorConfig>",
|
||||||
|
"description": "线程池配置.",
|
||||||
|
"defaultValue": "{}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.enabled",
|
||||||
|
"type": "java.lang.Boolean",
|
||||||
|
"description": "是否启用.",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.corePoolSize",
|
||||||
|
"type": "java.lang.Integer",
|
||||||
|
"description": "核心线程数.",
|
||||||
|
"defaultValue": "CPU_NUM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.maxPoolSize",
|
||||||
|
"type": "java.lang.Integer",
|
||||||
|
"description": "最大线程数.",
|
||||||
|
"defaultValue": "CPU_NUM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.queueCapacity",
|
||||||
|
"type": "java.lang.Integer",
|
||||||
|
"description": "任务队列容量.",
|
||||||
|
"defaultValue": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.keepAliveSeconds",
|
||||||
|
"type": "java.lang.Integer",
|
||||||
|
"description": "空闲线程存活时间.",
|
||||||
|
"defaultValue": 60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.allowCoreTimeout",
|
||||||
|
"type": "java.lang.Boolean",
|
||||||
|
"description": "是否允许核心线程超时回收.",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.synchronousQueue",
|
||||||
|
"type": "java.lang.Boolean",
|
||||||
|
"description": "是否启用同步队列模式.",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.mdc",
|
||||||
|
"type": "java.lang.Boolean",
|
||||||
|
"description": "是否启用 MDC 上下文传递.",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.threadNamePrefix",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "线程名称前缀."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orion.executors.*.rejectPolicy",
|
||||||
|
"type": "cn.orionsec.kit.lang.define.thread.RejectPolicy",
|
||||||
|
"description": "拒绝策略.",
|
||||||
|
"defaultValue": "CALLER_RUNS"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.dromara.visor.framework.executor.configuration.OrionExecutorAutoConfiguration
|
||||||
@@ -24,6 +24,7 @@ package org.dromara.visor.framework.influxdb.core.query;
|
|||||||
|
|
||||||
import cn.orionsec.kit.lang.utils.collect.Collections;
|
import cn.orionsec.kit.lang.utils.collect.Collections;
|
||||||
import cn.orionsec.kit.lang.utils.collect.Lists;
|
import cn.orionsec.kit.lang.utils.collect.Lists;
|
||||||
|
import cn.orionsec.kit.lang.utils.collect.Maps;
|
||||||
import org.dromara.visor.common.constant.Const;
|
import org.dromara.visor.common.constant.Const;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -194,7 +195,7 @@ public class FluxQueryBuilder {
|
|||||||
if (values.size() == 1) {
|
if (values.size() == 1) {
|
||||||
return this.tag(key, Collections.first(values));
|
return this.tag(key, Collections.first(values));
|
||||||
}
|
}
|
||||||
//
|
// 使用 or 拼接
|
||||||
Collection<String> conditions = values.stream()
|
Collection<String> conditions = values.stream()
|
||||||
.map(value -> String.format("r[\"%s\"] == \"%s\"", key, value))
|
.map(value -> String.format("r[\"%s\"] == \"%s\"", key, value))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@@ -204,33 +205,18 @@ public class FluxQueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 过滤多个 tag
|
* 过滤 tag
|
||||||
* tag 使用 and
|
|
||||||
* value 使用 or
|
|
||||||
*
|
*
|
||||||
* @param tags tags
|
* @param tags tags
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public FluxQueryBuilder tags(Map<String, ? extends Collection<String>> tags) {
|
public FluxQueryBuilder tags(Map<String, ? extends Collection<String>> tags) {
|
||||||
|
if (Maps.isEmpty(tags)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
for (Map.Entry<String, ? extends Collection<String>> entry : tags.entrySet()) {
|
for (Map.Entry<String, ? extends Collection<String>> entry : tags.entrySet()) {
|
||||||
String key = entry.getKey();
|
this.tag(entry.getKey(), entry.getValue());
|
||||||
Collection<String> 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<String> 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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.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.core.task.TaskExecutor;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
|
||||||
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* async 异步任务
|
|
||||||
*
|
|
||||||
* @author Jiahang Li
|
|
||||||
* @version 1.0.0
|
|
||||||
* @since 2023/6/20 10:34
|
|
||||||
*/
|
|
||||||
@EnableAsync
|
|
||||||
@AutoConfiguration
|
|
||||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_JOB_ASYNC)
|
|
||||||
@EnableConfigurationProperties(AsyncExecutorConfig.class)
|
|
||||||
public class OrionAsyncAutoConfiguration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@code @Async("asyncExecutor")}
|
|
||||||
*
|
|
||||||
* @return 支持 MDC 的异步线程池
|
|
||||||
*/
|
|
||||||
@Bean(name = "asyncExecutor")
|
|
||||||
public TaskExecutor asyncExecutor(AsyncExecutorConfig config) {
|
|
||||||
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
|
|
||||||
executor.setCorePoolSize(config.getCorePoolSize());
|
|
||||||
executor.setMaxPoolSize(config.getMaxPoolSize());
|
|
||||||
executor.setQueueCapacity(config.getQueueCapacity());
|
|
||||||
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
|
|
||||||
executor.setAllowCoreThreadTimeOut(true);
|
|
||||||
executor.setThreadNamePrefix("async-task-");
|
|
||||||
// 设置等待所有任务执行结束再关闭线程池
|
|
||||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
|
||||||
// 以确保应用最后能够被关闭
|
|
||||||
executor.setAwaitTerminationSeconds(60);
|
|
||||||
// 调用者调用拒绝策略
|
|
||||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
|
||||||
executor.initialize();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -25,6 +25,8 @@ package org.dromara.visor.framework.job.configuration;
|
|||||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
|
import org.springframework.boot.autoconfigure.task.TaskSchedulingProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
@@ -40,17 +42,18 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
|||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_JOB)
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_JOB)
|
||||||
|
@EnableConfigurationProperties(TaskSchedulingProperties.class)
|
||||||
public class OrionSchedulerAutoConfiguration {
|
public class OrionSchedulerAutoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 任务调度器
|
* @return 任务调度器
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public TaskScheduler taskScheduler() {
|
public TaskScheduler taskScheduler(TaskSchedulingProperties properties) {
|
||||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||||
scheduler.setPoolSize(4);
|
|
||||||
scheduler.setRemoveOnCancelPolicy(true);
|
scheduler.setRemoveOnCancelPolicy(true);
|
||||||
scheduler.setThreadNamePrefix("scheduling-task-");
|
scheduler.setPoolSize(properties.getPool().getSize());
|
||||||
|
scheduler.setThreadNamePrefix(properties.getThreadNamePrefix());
|
||||||
return scheduler;
|
return scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"name": "orion.async.executor",
|
|
||||||
"type": "org.dromara.visor.framework.job.configuration.config.AsyncExecutorConfig",
|
|
||||||
"sourceType": "org.dromara.visor.framework.job.configuration.config.AsyncExecutorConfig"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "orion.async.executor.core-pool-size",
|
|
||||||
"type": "java.lang.Integer",
|
|
||||||
"description": "核心线程数量.",
|
|
||||||
"defaultValue": "8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "orion.async.executor.max-pool-size",
|
|
||||||
"type": "java.lang.Integer",
|
|
||||||
"description": "最大线程数量.",
|
|
||||||
"defaultValue": "16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "orion.async.executor.queue-capacity",
|
|
||||||
"type": "java.lang.Integer",
|
|
||||||
"description": "队列容量.",
|
|
||||||
"defaultValue": "200"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "orion.async.executor.keep-alive-seconds",
|
|
||||||
"type": "java.lang.Integer",
|
|
||||||
"description": "活跃时间.",
|
|
||||||
"defaultValue": "300"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
org.dromara.visor.framework.job.configuration.OrionSchedulerAutoConfiguration
|
org.dromara.visor.framework.job.configuration.OrionSchedulerAutoConfiguration
|
||||||
org.dromara.visor.framework.job.configuration.OrionQuartzAutoConfiguration
|
org.dromara.visor.framework.job.configuration.OrionQuartzAutoConfiguration
|
||||||
org.dromara.visor.framework.job.configuration.OrionAsyncAutoConfiguration
|
|
||||||
@@ -312,6 +312,19 @@ public class RedisMaps extends RedisUtils {
|
|||||||
return getJson(key.getKey(), hashKey, (Class<V>) key.getType());
|
return getJson(key.getKey(), hashKey, (Class<V>) key.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取值 json
|
||||||
|
*
|
||||||
|
* @param define define
|
||||||
|
* @param key key
|
||||||
|
* @param hashKey hashKey
|
||||||
|
* @param <V> V
|
||||||
|
* @return value
|
||||||
|
*/
|
||||||
|
public static <V> V getJson(String key, CacheKeyDefine define, Object hashKey) {
|
||||||
|
return getJson(key, hashKey, (Class<V>) define.getType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取值 json
|
* 获取值 json
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
|||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
@@ -67,6 +68,7 @@ import java.util.List;
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2023/6/16 16:26
|
* @since 2023/6/16 16:26
|
||||||
*/
|
*/
|
||||||
|
@DependsOn({"executorContext"})
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_WEB)
|
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_WEB)
|
||||||
@EnableConfigurationProperties(ExposeApiConfig.class)
|
@EnableConfigurationProperties(ExposeApiConfig.class)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
<module>orion-visor-spring-boot-starter-cipher</module>
|
<module>orion-visor-spring-boot-starter-cipher</module>
|
||||||
<module>orion-visor-spring-boot-starter-config</module>
|
<module>orion-visor-spring-boot-starter-config</module>
|
||||||
<module>orion-visor-spring-boot-starter-job</module>
|
<module>orion-visor-spring-boot-starter-job</module>
|
||||||
|
<module>orion-visor-spring-boot-starter-executor</module>
|
||||||
<module>orion-visor-spring-boot-starter-websocket</module>
|
<module>orion-visor-spring-boot-starter-websocket</module>
|
||||||
<module>orion-visor-spring-boot-starter-redis</module>
|
<module>orion-visor-spring-boot-starter-redis</module>
|
||||||
<module>orion-visor-spring-boot-starter-desensitize</module>
|
<module>orion-visor-spring-boot-starter-desensitize</module>
|
||||||
|
|||||||
@@ -102,6 +102,10 @@
|
|||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-websocket</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-websocket</artifactId>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
druid:
|
druid:
|
||||||
url: jdbc:mysql://${MYSQL_HOST:127.0.0.1}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:orion_visor}?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
|
url: jdbc:mysql://${MYSQL_HOST:127.0.0.1}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:orion_visor}?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&useServerPrepStmts=false
|
||||||
username: ${MYSQL_USER:root}
|
username: ${MYSQL_USER:root}
|
||||||
password: ${MYSQL_PASSWORD:Data@123456}
|
password: ${MYSQL_PASSWORD:Data@123456}
|
||||||
initial-size: 0
|
initial-size: 0
|
||||||
@@ -49,3 +49,84 @@ mybatis-plus:
|
|||||||
configuration:
|
configuration:
|
||||||
# 日志打印
|
# 日志打印
|
||||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
|
|
||||||
|
app:
|
||||||
|
executors:
|
||||||
|
# 默认异步线程池
|
||||||
|
asyncExecutor:
|
||||||
|
mdc: true
|
||||||
|
core-pool-size: 2
|
||||||
|
max-pool-size: 4
|
||||||
|
queue-capacity: 30
|
||||||
|
allow-core-timeout: false
|
||||||
|
thread-name-prefix: async-executor-
|
||||||
|
# 指标存储异步线程池
|
||||||
|
metricsExecutor:
|
||||||
|
mdc: true
|
||||||
|
core-pool-size: 2
|
||||||
|
max-pool-size: 2
|
||||||
|
queue-capacity: 1000
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: metrics-task-
|
||||||
|
# 推送异步线程池
|
||||||
|
pushExecutor:
|
||||||
|
mdc: true
|
||||||
|
core-pool-size: 1
|
||||||
|
max-pool-size: 1
|
||||||
|
queue-capacity: 1000
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: message-push-
|
||||||
|
# 探针安装线程池
|
||||||
|
agentInstallExecutor:
|
||||||
|
core-pool-size: 2
|
||||||
|
max-pool-size: 2
|
||||||
|
queue-capacity: 200
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: agent-install-
|
||||||
|
# 终端标准输出线程池
|
||||||
|
terminalStdoutExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: terminal-stdout-
|
||||||
|
# 终端操作线程池
|
||||||
|
terminalOperatorExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: terminal-operator-
|
||||||
|
# 终端异步保存线程池
|
||||||
|
terminalAsyncSaverExecutor:
|
||||||
|
core-pool-size: 1
|
||||||
|
max-pool-size: 1
|
||||||
|
queue-capacity: 1000
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: terminal-watcher-
|
||||||
|
# 批量执行超时检查线程池
|
||||||
|
execTimeoutCheckExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: timeout-check-
|
||||||
|
# 批量执行任务线程池
|
||||||
|
execTaskExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: exec-task-
|
||||||
|
# 批量执行主机命令线程池
|
||||||
|
execHostCommandExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: exec-host-
|
||||||
|
# 批量执行日志查看线程池
|
||||||
|
execLogViewExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: exec-log-
|
||||||
|
# 批量上传任务线程池
|
||||||
|
uploadTaskExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: upload-task-
|
||||||
|
# 批量上传主机线程池
|
||||||
|
uploadHostExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: upload-host-
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
druid:
|
druid:
|
||||||
url: jdbc:mysql://${MYSQL_HOST:127.0.0.1}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:orion_visor}?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
|
url: jdbc:mysql://${MYSQL_HOST:127.0.0.1}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:orion_visor}?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&useServerPrepStmts=false
|
||||||
username: ${MYSQL_USER:root}
|
username: ${MYSQL_USER:root}
|
||||||
password: ${MYSQL_PASSWORD:Data@123456}
|
password: ${MYSQL_PASSWORD:Data@123456}
|
||||||
# 初始连接数
|
# 初始连接数
|
||||||
@@ -84,9 +84,81 @@ orion:
|
|||||||
aes:
|
aes:
|
||||||
# 加密密钥
|
# 加密密钥
|
||||||
secret-key: ${SECRET_KEY:uQeacXV8b3isvKLK}
|
secret-key: ${SECRET_KEY:uQeacXV8b3isvKLK}
|
||||||
async:
|
|
||||||
executor:
|
app:
|
||||||
|
executors:
|
||||||
|
# 默认异步线程池
|
||||||
|
asyncExecutor:
|
||||||
|
mdc: true
|
||||||
core-pool-size: 8
|
core-pool-size: 8
|
||||||
max-pool-size: 16
|
max-pool-size: 16
|
||||||
queue-capacity: 200
|
queue-capacity: 100
|
||||||
keep-alive-seconds: 300
|
allow-core-timeout: false
|
||||||
|
thread-name-prefix: async-executor-
|
||||||
|
# 指标存储异步线程池
|
||||||
|
metricsExecutor:
|
||||||
|
mdc: true
|
||||||
|
core-pool-size: 4
|
||||||
|
max-pool-size: 4
|
||||||
|
queue-capacity: 1000
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: metrics-task-
|
||||||
|
# 推送异步线程池
|
||||||
|
pushExecutor:
|
||||||
|
mdc: true
|
||||||
|
core-pool-size: 4
|
||||||
|
max-pool-size: 4
|
||||||
|
queue-capacity: 1000
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: message-push-
|
||||||
|
# 探针安装线程池
|
||||||
|
agentInstallExecutor:
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: agent-install-
|
||||||
|
# 终端标准输出线程池
|
||||||
|
terminalStdoutExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: terminal-stdout-
|
||||||
|
# 终端操作线程池
|
||||||
|
terminalOperatorExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: terminal-operator-
|
||||||
|
# 终端异步保存线程池
|
||||||
|
terminalAsyncSaverExecutor:
|
||||||
|
core-pool-size: 1
|
||||||
|
max-pool-size: 1
|
||||||
|
queue-capacity: 1000
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: terminal-watcher-
|
||||||
|
# 批量执行超时检查线程池
|
||||||
|
execTimeoutCheckExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: timeout-check-
|
||||||
|
# 批量执行任务线程池
|
||||||
|
execTaskExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: exec-task-
|
||||||
|
# 批量执行主机命令线程池
|
||||||
|
execHostCommandExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: exec-host-
|
||||||
|
# 批量执行日志查看线程池
|
||||||
|
execLogViewExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: exec-log-
|
||||||
|
# 批量上传任务线程池
|
||||||
|
uploadTaskExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: upload-task-
|
||||||
|
# 批量上传主机线程池
|
||||||
|
uploadHostExecutor:
|
||||||
|
synchronous-queue: true
|
||||||
|
allow-core-timeout: true
|
||||||
|
thread-name-prefix: upload-host-
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ spring:
|
|||||||
async:
|
async:
|
||||||
# 异步请求时间 30min
|
# 异步请求时间 30min
|
||||||
request-timeout: 1800000
|
request-timeout: 1800000
|
||||||
|
task:
|
||||||
|
scheduling:
|
||||||
|
thread-name-prefix: scheduling-task-
|
||||||
|
pool:
|
||||||
|
size: 4
|
||||||
datasource:
|
datasource:
|
||||||
druid:
|
druid:
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
@@ -255,13 +260,6 @@ orion:
|
|||||||
secret-key: I66AndrKWrwXjtBL
|
secret-key: I66AndrKWrwXjtBL
|
||||||
use-generator-key: true
|
use-generator-key: true
|
||||||
generator-key-length: 128
|
generator-key-length: 128
|
||||||
async:
|
|
||||||
# 线程池配置
|
|
||||||
executor:
|
|
||||||
core-pool-size: 2
|
|
||||||
max-pool-size: 4
|
|
||||||
queue-capacity: 30
|
|
||||||
keep-alive-seconds: 180
|
|
||||||
operator-log:
|
operator-log:
|
||||||
error-message-length: 255
|
error-message-length: 255
|
||||||
user-agent-length: 128
|
user-agent-length: 128
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ import java.util.function.Function;
|
|||||||
*/
|
*/
|
||||||
public class ReplaceVersion {
|
public class ReplaceVersion {
|
||||||
|
|
||||||
private static final String TARGET_VERSION = "2.5.1";
|
private static final String TARGET_VERSION = "2.5.2";
|
||||||
|
|
||||||
private static final String REPLACE_VERSION = "2.5.2";
|
private static final String REPLACE_VERSION = "2.5.3";
|
||||||
|
|
||||||
private static final String PATH = new File("").getAbsolutePath();
|
private static final String PATH = new File("").getAbsolutePath();
|
||||||
|
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ public interface HostAgentApi {
|
|||||||
/**
|
/**
|
||||||
* 获取缓存名称
|
* 获取缓存名称
|
||||||
*
|
*
|
||||||
* @param agentKeyList agentKeyList
|
* @param agentKeys agentKeys
|
||||||
* @return nameMap
|
* @return nameMap
|
||||||
*/
|
*/
|
||||||
Map<String, String> getNameCacheByAgentKey(List<String> agentKeyList);
|
Map<String, String> getNameCacheByAgentKey(List<String> agentKeys);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存名称
|
* 获取缓存名称
|
||||||
|
|||||||
@@ -88,6 +88,10 @@
|
|||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
||||||
|
|||||||
@@ -103,11 +103,11 @@ public class HostAgentApiImpl implements HostAgentApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getNameCacheByAgentKey(List<String> agentKeyList) {
|
public Map<String, String> getNameCacheByAgentKey(List<String> agentKeys) {
|
||||||
Map<String, String> result = new HashMap<>();
|
Map<String, String> result = new HashMap<>();
|
||||||
List<String> queryList = new ArrayList<>();
|
List<String> queryList = new ArrayList<>();
|
||||||
// 查询缓存
|
// 查询缓存
|
||||||
for (String agentKey : agentKeyList) {
|
for (String agentKey : agentKeys) {
|
||||||
HostBaseDTO host = AGENT_HOST_CACHE.get(agentKey);
|
HostBaseDTO host = AGENT_HOST_CACHE.get(agentKey);
|
||||||
if (host != null) {
|
if (host != null) {
|
||||||
result.put(agentKey, host.getName());
|
result.put(agentKey, host.getName());
|
||||||
|
|||||||
@@ -92,14 +92,14 @@ public interface HostDAO extends IMapper<HostDO> {
|
|||||||
/**
|
/**
|
||||||
* 更新探针信息
|
* 更新探针信息
|
||||||
*
|
*
|
||||||
* @param keys agentKeyList
|
* @param agentKeys agentKeys
|
||||||
* @param update update
|
* @param update update
|
||||||
* @return effect
|
* @return effect
|
||||||
*/
|
*/
|
||||||
default int updateByAgentKeys(List<String> keys, HostDO update) {
|
default int updateByAgentKeys(List<String> agentKeys, HostDO update) {
|
||||||
update.setUpdateTime(new Date());
|
update.setUpdateTime(new Date());
|
||||||
// 更新
|
// 更新
|
||||||
return this.update(update, Conditions.in(HostDO::getAgentKey, keys));
|
return this.update(update, Conditions.in(HostDO::getAgentKey, agentKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.module.asset.define;
|
package org.dromara.visor.module.asset.define;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.define.thread.ExecutorBuilder;
|
import org.dromara.visor.framework.executor.core.utils.ExecutorUtils;
|
||||||
import cn.orionsec.kit.lang.utils.Systems;
|
|
||||||
import org.dromara.visor.common.constant.Const;
|
|
||||||
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行线程池
|
* 执行线程池
|
||||||
@@ -41,13 +38,6 @@ public interface AssetThreadPools {
|
|||||||
/**
|
/**
|
||||||
* 批量执行主机命令线程池
|
* 批量执行主机命令线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor AGENT_INSTALL = ExecutorBuilder.create()
|
Executor AGENT_INSTALL = ExecutorUtils.getExecutor("agentInstallExecutor");
|
||||||
.namedThreadFactory("agent-install-")
|
|
||||||
.corePoolSize(Systems.PROCESS_NUM)
|
|
||||||
.maxPoolSize(Systems.PROCESS_NUM)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new LinkedBlockingQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,25 +212,25 @@ public class HostAgentEndpointServiceImpl implements HostAgentEndpointService {
|
|||||||
/**
|
/**
|
||||||
* 标记在线状态
|
* 标记在线状态
|
||||||
*
|
*
|
||||||
* @param agentKeyList agentKeyList
|
* @param agentKeys agentKeys
|
||||||
* @param status status
|
* @param status status
|
||||||
*/
|
*/
|
||||||
private void markOnlineStatus(List<String> agentKeyList, AgentOnlineStatusEnum status) {
|
private void markOnlineStatus(List<String> agentKeys, AgentOnlineStatusEnum status) {
|
||||||
if (Lists.isEmpty(agentKeyList)) {
|
if (Lists.isEmpty(agentKeys)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.info("HostAgentEndpointService mark {}. count: {}, keys: {}", status, agentKeyList.size(), agentKeyList);
|
log.info("HostAgentEndpointService mark {}. count: {}, keys: {}", status, agentKeys.size(), agentKeys);
|
||||||
// 更新数据
|
// 更新数据
|
||||||
HostDO update = HostDO.builder()
|
HostDO update = HostDO.builder()
|
||||||
.agentOnlineStatus(status.getValue())
|
.agentOnlineStatus(status.getValue())
|
||||||
.agentOnlineChangeTime(new Date())
|
.agentOnlineChangeTime(new Date())
|
||||||
.build();
|
.build();
|
||||||
int effect = hostDAO.updateByAgentKeys(agentKeyList, update);
|
int effect = hostDAO.updateByAgentKeys(agentKeys, update);
|
||||||
// 更新缓存
|
// 更新缓存
|
||||||
agentKeyList.forEach(s -> ONLINE_STATUS_CACHE.put(s, status.getValue()));
|
agentKeys.forEach(s -> ONLINE_STATUS_CACHE.put(s, status.getValue()));
|
||||||
log.info("HostAgentEndpointService mark {}. effect: {}", status, effect);
|
log.info("HostAgentEndpointService mark {}. effect: {}", status, effect);
|
||||||
// 插入日志
|
// 插入日志
|
||||||
List<HostAgentLogDO> logList = hostDAO.selectIdByAgentKeys(agentKeyList)
|
List<HostAgentLogDO> logList = hostDAO.selectIdByAgentKeys(agentKeys)
|
||||||
.stream()
|
.stream()
|
||||||
.map(s -> {
|
.map(s -> {
|
||||||
HostAgentLogDO agentLog = HostAgentLogDO.builder()
|
HostAgentLogDO agentLog = HostAgentLogDO.builder()
|
||||||
@@ -250,7 +250,7 @@ public class HostAgentEndpointServiceImpl implements HostAgentEndpointService {
|
|||||||
}
|
}
|
||||||
// 发送已下线事件
|
// 发送已下线事件
|
||||||
if (AgentOnlineStatusEnum.OFFLINE.equals(status)) {
|
if (AgentOnlineStatusEnum.OFFLINE.equals(status)) {
|
||||||
SpringHolder.publishEvent(new AgentOfflineEvent(agentKeyList));
|
SpringHolder.publishEvent(new AgentOfflineEvent(agentKeys));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,10 @@
|
|||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
||||||
|
|||||||
@@ -22,11 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.module.exec.define;
|
package org.dromara.visor.module.exec.define;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.define.thread.ExecutorBuilder;
|
import org.dromara.visor.framework.executor.core.utils.ExecutorUtils;
|
||||||
import org.dromara.visor.common.constant.Const;
|
|
||||||
|
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行线程池
|
* 执行线程池
|
||||||
@@ -40,73 +38,31 @@ public interface ExecThreadPools {
|
|||||||
/**
|
/**
|
||||||
* 超时检查线程池
|
* 超时检查线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor TIMEOUT_CHECK = ExecutorBuilder.create()
|
Executor TIMEOUT_CHECK = ExecutorUtils.getExecutor("execTimeoutCheckExecutor");
|
||||||
.namedThreadFactory("timeout-check-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量执行任务线程池
|
* 批量执行任务线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor EXEC_TASK = ExecutorBuilder.create()
|
Executor EXEC_TASK = ExecutorUtils.getExecutor("execTaskExecutor");
|
||||||
.namedThreadFactory("exec-task-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量执行主机命令线程池
|
* 批量执行主机命令线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor EXEC_HOST = ExecutorBuilder.create()
|
Executor EXEC_HOST = ExecutorUtils.getExecutor("execHostCommandExecutor");
|
||||||
.namedThreadFactory("exec-host-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量执行日志查看线程池
|
* 批量执行日志查看线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor EXEC_LOG = ExecutorBuilder.create()
|
Executor EXEC_LOG = ExecutorUtils.getExecutor("execLogViewExecutor");
|
||||||
.namedThreadFactory("exec-log-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量上传任务线程池
|
* 批量上传任务线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor UPLOAD_TASK = ExecutorBuilder.create()
|
Executor UPLOAD_TASK = ExecutorUtils.getExecutor("uploadTaskExecutor");
|
||||||
.namedThreadFactory("upload-task-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量上传主机线程池
|
* 批量上传主机线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor UPLOAD_HOST = ExecutorBuilder.create()
|
Executor UPLOAD_HOST = ExecutorUtils.getExecutor("uploadHostExecutor");
|
||||||
.namedThreadFactory("upload-host-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,10 @@
|
|||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
||||||
|
|||||||
@@ -48,13 +48,13 @@ import javax.annotation.Resource;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录 api
|
* 告警事件 api
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2025-9-17 21:31
|
* @since 2025-9-17 21:31
|
||||||
*/
|
*/
|
||||||
@Tag(name = "monitor - 告警记录服务")
|
@Tag(name = "monitor - 告警事件服务")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Validated
|
@Validated
|
||||||
@RestWrapper
|
@RestWrapper
|
||||||
@@ -67,7 +67,7 @@ public class AlarmEventController {
|
|||||||
|
|
||||||
@IgnoreLog(IgnoreLogMode.RET)
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
@Operation(summary = "分页查询告警记录")
|
@Operation(summary = "分页查询告警事件")
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:query')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:query')")
|
||||||
public DataGrid<AlarmEventVO> getAlarmEventPage(@Validated(Page.class) @RequestBody AlarmEventQueryRequest request) {
|
public DataGrid<AlarmEventVO> getAlarmEventPage(@Validated(Page.class) @RequestBody AlarmEventQueryRequest request) {
|
||||||
return alarmEventService.getAlarmEventPage(request);
|
return alarmEventService.getAlarmEventPage(request);
|
||||||
@@ -76,7 +76,7 @@ public class AlarmEventController {
|
|||||||
@IgnoreLog(IgnoreLogMode.RET)
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
@OperatorLog(AlarmEventOperatorType.HANDLE)
|
@OperatorLog(AlarmEventOperatorType.HANDLE)
|
||||||
@PostMapping("/handle")
|
@PostMapping("/handle")
|
||||||
@Operation(summary = "处理告警记录")
|
@Operation(summary = "处理告警事件")
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:handle')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:handle')")
|
||||||
public Integer handleAlarmEvent(@Validated @RequestBody AlarmEventHandleRequest request) {
|
public Integer handleAlarmEvent(@Validated @RequestBody AlarmEventHandleRequest request) {
|
||||||
return alarmEventService.handleAlarmEvent(request);
|
return alarmEventService.handleAlarmEvent(request);
|
||||||
@@ -92,7 +92,7 @@ public class AlarmEventController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/count")
|
@PostMapping("/count")
|
||||||
@Operation(summary = "查询告警记录数量")
|
@Operation(summary = "查询告警事件数量")
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:query')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:query')")
|
||||||
public Long getAlarmEventCount(@Validated @RequestBody AlarmEventQueryRequest request) {
|
public Long getAlarmEventCount(@Validated @RequestBody AlarmEventQueryRequest request) {
|
||||||
return alarmEventService.getAlarmEventCount(request);
|
return alarmEventService.getAlarmEventCount(request);
|
||||||
@@ -101,7 +101,7 @@ public class AlarmEventController {
|
|||||||
@DemoDisableApi
|
@DemoDisableApi
|
||||||
@OperatorLog(AlarmEventOperatorType.DELETE)
|
@OperatorLog(AlarmEventOperatorType.DELETE)
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@Operation(summary = "删除告警记录")
|
@Operation(summary = "删除告警事件")
|
||||||
@Parameter(name = "id", description = "id", required = true)
|
@Parameter(name = "id", description = "id", required = true)
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:delete')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:delete')")
|
||||||
public Integer deleteAlarmEvent(@RequestParam("id") Long id) {
|
public Integer deleteAlarmEvent(@RequestParam("id") Long id) {
|
||||||
@@ -111,7 +111,7 @@ public class AlarmEventController {
|
|||||||
@DemoDisableApi
|
@DemoDisableApi
|
||||||
@OperatorLog(AlarmEventOperatorType.DELETE)
|
@OperatorLog(AlarmEventOperatorType.DELETE)
|
||||||
@DeleteMapping("/batch-delete")
|
@DeleteMapping("/batch-delete")
|
||||||
@Operation(summary = "批量删除告警记录")
|
@Operation(summary = "批量删除告警事件")
|
||||||
@Parameter(name = "idList", description = "idList", required = true)
|
@Parameter(name = "idList", description = "idList", required = true)
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:delete')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:delete')")
|
||||||
public Integer batchDeleteAlarmEvent(@RequestParam("idList") List<Long> idList) {
|
public Integer batchDeleteAlarmEvent(@RequestParam("idList") List<Long> idList) {
|
||||||
@@ -121,7 +121,7 @@ public class AlarmEventController {
|
|||||||
@DemoDisableApi
|
@DemoDisableApi
|
||||||
@OperatorLog(AlarmEventOperatorType.CLEAR)
|
@OperatorLog(AlarmEventOperatorType.CLEAR)
|
||||||
@PostMapping("/clear")
|
@PostMapping("/clear")
|
||||||
@Operation(summary = "清理告警记录")
|
@Operation(summary = "清理告警事件")
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:management:clear')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-event:management:clear')")
|
||||||
public Integer clearAlarmEvent(@Validated @RequestBody AlarmEventClearRequest request) {
|
public Integer clearAlarmEvent(@Validated @RequestBody AlarmEventClearRequest request) {
|
||||||
return alarmEventService.clearAlarmEvent(request);
|
return alarmEventService.clearAlarmEvent(request);
|
||||||
|
|||||||
@@ -93,11 +93,11 @@ public class AlarmPolicyRuleController {
|
|||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "查询全部监控告警规则")
|
@Operation(summary = "查询全部监控告警规则")
|
||||||
@Parameter(name = "policyId", description = "policyId", required = true)
|
@Parameter(name = "policyId", description = "policyId", required = true)
|
||||||
@Parameter(name = "metricsMeasurement", description = "metricsMeasurement")
|
@Parameter(name = "measurement", description = "measurement")
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:alarm-policy:query')")
|
@PreAuthorize("@ss.hasPermission('monitor:alarm-policy:query')")
|
||||||
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(@RequestParam("policyId") Long policyId,
|
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(@RequestParam("policyId") Long policyId,
|
||||||
@RequestParam(value = "metricsMeasurement", required = false) String metricsMeasurement) {
|
@RequestParam(value = "measurement", required = false) String measurement) {
|
||||||
return alarmPolicyRuleService.getAlarmPolicyRuleList(policyId, metricsMeasurement);
|
return alarmPolicyRuleService.getAlarmPolicyRuleList(policyId, measurement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DemoDisableApi
|
@DemoDisableApi
|
||||||
|
|||||||
@@ -38,10 +38,7 @@ import org.dromara.visor.framework.web.core.annotation.RestWrapper;
|
|||||||
import org.dromara.visor.module.monitor.define.operator.MonitorHostOperatorType;
|
import org.dromara.visor.module.monitor.define.operator.MonitorHostOperatorType;
|
||||||
import org.dromara.visor.module.monitor.engine.MonitorContext;
|
import org.dromara.visor.module.monitor.engine.MonitorContext;
|
||||||
import org.dromara.visor.module.monitor.entity.dto.AgentMetricsDataDTO;
|
import org.dromara.visor.module.monitor.entity.dto.AgentMetricsDataDTO;
|
||||||
import org.dromara.visor.module.monitor.entity.request.host.MonitorHostChartRequest;
|
import org.dromara.visor.module.monitor.entity.request.host.*;
|
||||||
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.MonitorHostMetricsDataVO;
|
||||||
import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO;
|
import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO;
|
||||||
import org.dromara.visor.module.monitor.service.MonitorHostService;
|
import org.dromara.visor.module.monitor.service.MonitorHostService;
|
||||||
@@ -95,7 +92,7 @@ public class MonitorHostController {
|
|||||||
@Operation(summary = "查询监控指标")
|
@Operation(summary = "查询监控指标")
|
||||||
@PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')")
|
@PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')")
|
||||||
public List<MonitorHostMetricsDataVO> getMonitorHostMetrics(@Validated(Key.class) @RequestBody MonitorHostQueryRequest request) {
|
public List<MonitorHostMetricsDataVO> getMonitorHostMetrics(@Validated(Key.class) @RequestBody MonitorHostQueryRequest request) {
|
||||||
return monitorHostService.getMonitorHostMetrics(request.getAgentKeyList());
|
return monitorHostService.getMonitorHostMetrics(request.getAgentKeys());
|
||||||
}
|
}
|
||||||
|
|
||||||
@IgnoreLog(IgnoreLogMode.RET)
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
@@ -106,6 +103,14 @@ public class MonitorHostController {
|
|||||||
return monitorHostService.getMonitorHostChart(request);
|
return monitorHostService.getMonitorHostChart(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
|
@PostMapping("/host-tags")
|
||||||
|
@Operation(summary = "查询监控告警标签")
|
||||||
|
@PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')")
|
||||||
|
public List<String> getMonitorHostTags(@RequestBody MonitorHostQueryTagRequest request) {
|
||||||
|
return monitorHostService.getMonitorHostTags(request);
|
||||||
|
}
|
||||||
|
|
||||||
@DemoDisableApi
|
@DemoDisableApi
|
||||||
@OperatorLog(MonitorHostOperatorType.UPDATE)
|
@OperatorLog(MonitorHostOperatorType.UPDATE)
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ package org.dromara.visor.module.monitor.convert;
|
|||||||
import org.dromara.visor.module.monitor.entity.domain.AlarmEventDO;
|
import org.dromara.visor.module.monitor.entity.domain.AlarmEventDO;
|
||||||
import org.dromara.visor.module.monitor.entity.dto.AlarmEventTriggerDTO;
|
import org.dromara.visor.module.monitor.entity.dto.AlarmEventTriggerDTO;
|
||||||
import org.dromara.visor.module.monitor.entity.dto.AlarmPolicyAlarmCountDTO;
|
import org.dromara.visor.module.monitor.entity.dto.AlarmPolicyAlarmCountDTO;
|
||||||
import org.dromara.visor.module.monitor.entity.po.AlarmPolicyAlarmCountPO;
|
import org.dromara.visor.module.monitor.entity.po.AlarmEventCountPO;
|
||||||
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventQueryRequest;
|
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventQueryRequest;
|
||||||
import org.dromara.visor.module.monitor.entity.vo.AlarmEventVO;
|
import org.dromara.visor.module.monitor.entity.vo.AlarmEventVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
@@ -34,7 +34,7 @@ import org.mapstruct.factory.Mappers;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 内部对象转换器
|
* 监控告警事件 内部对象转换器
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -51,7 +51,7 @@ public interface AlarmEventConvert {
|
|||||||
|
|
||||||
AlarmEventTriggerDTO toTrigger(AlarmEventDO domain);
|
AlarmEventTriggerDTO toTrigger(AlarmEventDO domain);
|
||||||
|
|
||||||
AlarmPolicyAlarmCountDTO toCount(AlarmPolicyAlarmCountPO domain);
|
AlarmPolicyAlarmCountDTO toCount(AlarmEventCountPO domain);
|
||||||
|
|
||||||
List<AlarmEventVO> to(List<AlarmEventDO> list);
|
List<AlarmEventVO> to(List<AlarmEventDO> list);
|
||||||
|
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import org.apache.ibatis.annotations.Mapper;
|
|||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.dromara.visor.framework.mybatis.core.mapper.IMapper;
|
import org.dromara.visor.framework.mybatis.core.mapper.IMapper;
|
||||||
import org.dromara.visor.module.monitor.entity.domain.AlarmEventDO;
|
import org.dromara.visor.module.monitor.entity.domain.AlarmEventDO;
|
||||||
import org.dromara.visor.module.monitor.entity.po.AlarmPolicyRuleCountPO;
|
import org.dromara.visor.module.monitor.entity.po.AlarmEventCountPO;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 Mapper 接口
|
* 监控告警事件 Mapper 接口
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -49,7 +49,7 @@ public interface AlarmEventDAO extends IMapper<AlarmEventDO> {
|
|||||||
* @param createTimeEnd createTimeEnd
|
* @param createTimeEnd createTimeEnd
|
||||||
* @return count
|
* @return count
|
||||||
*/
|
*/
|
||||||
List<AlarmPolicyRuleCountPO> selectPolicyEventCount(@Param("policyIdList") List<Long> policyIdList,
|
List<AlarmEventCountPO> selectPolicyEventCount(@Param("policyIdList") List<Long> policyIdList,
|
||||||
@Param("createTimeStart") Date createTimeStart,
|
@Param("createTimeStart") Date createTimeStart,
|
||||||
@Param("createTimeEnd") Date createTimeEnd);
|
@Param("createTimeEnd") Date createTimeEnd);
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,20 @@ public interface MonitorHostDAO extends IMapper<MonitorHostDO> {
|
|||||||
return this.delete(Conditions.in(MonitorHostDO::getHostId, hostIdList));
|
return this.delete(Conditions.in(MonitorHostDO::getHostId, hostIdList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 policyId 查询
|
||||||
|
*
|
||||||
|
* @param policyId policyId
|
||||||
|
* @return row
|
||||||
|
*/
|
||||||
|
default List<MonitorHostDO> selectByPolicyId(Long policyId) {
|
||||||
|
return this.of()
|
||||||
|
.createWrapper()
|
||||||
|
.eq(MonitorHostDO::getPolicyId, policyId)
|
||||||
|
.then()
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 policyId 为 null
|
* 设置 policyId 为 null
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
public interface AlarmPolicyCacheKeyDefine {
|
public interface AlarmPolicyCacheKeyDefine {
|
||||||
|
|
||||||
CacheKeyDefine MONITOR_ALARM_POLICY = new CacheKeyBuilder()
|
CacheKeyDefine ALARM_POLICY = new CacheKeyBuilder()
|
||||||
.key("alarm:policy:list")
|
.key("alarm:policy:list")
|
||||||
.desc("告警策略")
|
.desc("告警策略")
|
||||||
.type(AlarmPolicyCacheDTO.class)
|
.type(AlarmPolicyCacheDTO.class)
|
||||||
@@ -49,6 +49,7 @@ public interface AlarmPolicyCacheKeyDefine {
|
|||||||
CacheKeyDefine ALARM_RULE_SILENCE = new CacheKeyBuilder()
|
CacheKeyDefine ALARM_RULE_SILENCE = new CacheKeyBuilder()
|
||||||
.key("alarm:silence:{}:{}")
|
.key("alarm:silence:{}:{}")
|
||||||
.desc("告警规则沉默标志 ${agentKey} ${ruleId}")
|
.desc("告警规则沉默标志 ${agentKey} ${ruleId}")
|
||||||
|
.type(Long.class)
|
||||||
.struct(RedisCacheStruct.STRING)
|
.struct(RedisCacheStruct.STRING)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRi
|
|||||||
import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.L;
|
import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 操作日志类型
|
* 监控告警事件 操作日志类型
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -51,9 +51,9 @@ public class AlarmEventOperatorType extends InitializingOperatorTypes {
|
|||||||
public OperatorType[] types() {
|
public OperatorType[] types() {
|
||||||
return new OperatorType[]{
|
return new OperatorType[]{
|
||||||
new OperatorType(L, HANDLE, "设置告警状态为 ${status} <sb>${count}</sb> 条"),
|
new OperatorType(L, HANDLE, "设置告警状态为 ${status} <sb>${count}</sb> 条"),
|
||||||
new OperatorType(L, SET_FALSE, "设置告警记录为误报 <sb>${count}</sb> 条"),
|
new OperatorType(L, SET_FALSE, "设置告警事件为误报 <sb>${count}</sb> 条"),
|
||||||
new OperatorType(H, DELETE, "删除告警记录 <sb>${count}</sb> 条"),
|
new OperatorType(H, DELETE, "删除告警事件 <sb>${count}</sb> 条"),
|
||||||
new OperatorType(H, CLEAR, "清理告警记录 <sb>${count}</sb> 条"),
|
new OperatorType(H, CLEAR, "清理告警事件 <sb>${count}</sb> 条"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ public class AlarmEngineContext {
|
|||||||
* @return rules
|
* @return rules
|
||||||
*/
|
*/
|
||||||
private Map<Long, List<AlarmEngineRule>> getPolicyRules(List<AlarmPolicyRuleDO> list) {
|
private Map<Long, List<AlarmEngineRule>> getPolicyRules(List<AlarmPolicyRuleDO> list) {
|
||||||
|
if (Lists.isEmpty(list)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
// 转为 map
|
// 转为 map
|
||||||
Map<Long, List<AlarmEngineRule>> ruleMap = Lists.stream(list)
|
Map<Long, List<AlarmEngineRule>> ruleMap = Lists.stream(list)
|
||||||
.map(s -> {
|
.map(s -> {
|
||||||
@@ -154,6 +157,9 @@ public class AlarmEngineContext {
|
|||||||
* @return id
|
* @return id
|
||||||
*/
|
*/
|
||||||
private List<Long> getPolicyEngineNotifier(List<AlarmPolicyNotifyDO> list) {
|
private List<Long> getPolicyEngineNotifier(List<AlarmPolicyNotifyDO> list) {
|
||||||
|
if (Lists.isEmpty(list)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
return list.stream()
|
return list.stream()
|
||||||
.map(AlarmPolicyNotifyDO::getNotifyId)
|
.map(AlarmPolicyNotifyDO::getNotifyId)
|
||||||
.distinct()
|
.distinct()
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 实体对象
|
* 监控告警事件 实体对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -48,7 +48,7 @@ import java.util.Date;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@TableName(value = "monitor_alarm_event", autoResultMap = true)
|
@TableName(value = "monitor_alarm_event", autoResultMap = true)
|
||||||
@Schema(name = "AlarmEventDO", description = "监控告警记录 实体对象")
|
@Schema(name = "AlarmEventDO", description = "监控告警事件 实体对象")
|
||||||
public class AlarmEventDO extends BaseDO {
|
public class AlarmEventDO extends BaseDO {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ import java.io.Serializable;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(name = "AlarmPolicyAlarmCountPO", description = "监控告警事件数量对象")
|
@Schema(name = "AlarmEventCountPO", description = "监控告警事件数量对象")
|
||||||
public class AlarmPolicyAlarmCountPO implements Serializable {
|
public class AlarmEventCountPO implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ import javax.validation.constraints.Min;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 清理请求对象
|
* 监控告警事件 清理请求对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -40,7 +40,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Schema(name = "AlarmEventClearRequest", description = "监控告警记录 清理请求对象")
|
@Schema(name = "AlarmEventClearRequest", description = "监控告警事件 清理请求对象")
|
||||||
public class AlarmEventClearRequest extends AlarmEventQueryRequest implements DataClearRequest {
|
public class AlarmEventClearRequest extends AlarmEventQueryRequest implements DataClearRequest {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 更新请求对象
|
* 监控告警事件 更新请求对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -48,7 +48,7 @@ import java.util.List;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(name = "AlarmEventUpdateRequest", description = "监控告警记录 更新请求对象")
|
@Schema(name = "AlarmEventUpdateRequest", description = "监控告警事件 更新请求对象")
|
||||||
public class AlarmEventHandleRequest implements Serializable {
|
public class AlarmEventHandleRequest implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import javax.validation.constraints.Size;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 查询请求对象
|
* 监控告警事件 查询请求对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -42,7 +42,7 @@ import java.util.Date;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Schema(name = "AlarmEventQueryRequest", description = "监控告警记录 查询请求对象")
|
@Schema(name = "AlarmEventQueryRequest", description = "监控告警事件 查询请求对象")
|
||||||
public class AlarmEventQueryRequest extends BaseQueryRequest {
|
public class AlarmEventQueryRequest extends BaseQueryRequest {
|
||||||
|
|
||||||
@Schema(description = "id")
|
@Schema(description = "id")
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import java.io.Serializable;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 设置误报请求对象
|
* 监控告警事件 设置误报请求对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -43,7 +43,7 @@ import java.util.List;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(name = "AlarmEventSetFalseRequest", description = "监控告警记录 设置误报请求对象")
|
@Schema(name = "AlarmEventSetFalseRequest", description = "监控告警事件 设置误报请求对象")
|
||||||
public class AlarmEventSetFalseRequest implements Serializable {
|
public class AlarmEventSetFalseRequest implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|||||||
@@ -59,17 +59,17 @@ public class MonitorHostChartRequest extends BaseQueryRequest {
|
|||||||
@Schema(description = "时间窗口")
|
@Schema(description = "时间窗口")
|
||||||
private String window;
|
private String window;
|
||||||
|
|
||||||
|
@Schema(description = "时间区间")
|
||||||
|
private String range;
|
||||||
|
|
||||||
|
@Schema(description = "时间区间")
|
||||||
|
private Long start;
|
||||||
|
|
||||||
|
@Schema(description = "时间区间")
|
||||||
|
private Long end;
|
||||||
|
|
||||||
@NotBlank
|
@NotBlank
|
||||||
@Schema(description = "聚合参数")
|
@Schema(description = "聚合参数")
|
||||||
private String aggregate;
|
private String aggregate;
|
||||||
|
|
||||||
@Schema(description = "聚合参数")
|
|
||||||
private Long start;
|
|
||||||
|
|
||||||
@Schema(description = "聚合参数")
|
|
||||||
private Long end;
|
|
||||||
|
|
||||||
@Schema(description = "区间")
|
|
||||||
private String range;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class MonitorHostQueryRequest extends BaseQueryRequest {
|
|||||||
|
|
||||||
@NotEmpty(groups = Key.class)
|
@NotEmpty(groups = Key.class)
|
||||||
@Schema(description = "agentKey")
|
@Schema(description = "agentKey")
|
||||||
private List<String> agentKeyList;
|
private List<String> agentKeys;
|
||||||
|
|
||||||
@Schema(description = "搜索")
|
@Schema(description = "搜索")
|
||||||
private String searchValue;
|
private String searchValue;
|
||||||
|
|||||||
@@ -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.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 java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监控主机标签 查询请求对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-8-14 16:27
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "MonitorHostQueryTagRequest", description = "监控主机标签 查询请求对象")
|
||||||
|
public class MonitorHostQueryTagRequest extends BaseQueryRequest {
|
||||||
|
|
||||||
|
@Schema(description = "数据集")
|
||||||
|
private String measurement;
|
||||||
|
|
||||||
|
@Schema(description = "策略id")
|
||||||
|
private Long policyId;
|
||||||
|
|
||||||
|
@Schema(description = "agentKey")
|
||||||
|
private List<String> agentKeys;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 视图响应对象
|
* 监控告警事件 视图响应对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -43,7 +43,7 @@ import java.util.Date;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(name = "AlarmEventVO", description = "监控告警记录 视图响应对象")
|
@Schema(name = "AlarmEventVO", description = "监控告警事件 视图响应对象")
|
||||||
public class AlarmEventVO implements Serializable {
|
public class AlarmEventVO implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
package org.dromara.visor.module.monitor.enums;
|
package org.dromara.visor.module.monitor.enums;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录处理状态
|
* 告警事件处理状态
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* cpu
|
* cpu
|
||||||
*/
|
*/
|
||||||
CPU("cpu", (s) -> {
|
CPU("cpu", true, (s) -> {
|
||||||
s.accept(MetricsConst.CPU_USER_SECONDS_TOTAL, double.class);
|
s.accept(MetricsConst.CPU_USER_SECONDS_TOTAL, double.class);
|
||||||
s.accept(MetricsConst.CPU_SYSTEM_SECONDS_TOTAL, double.class);
|
s.accept(MetricsConst.CPU_SYSTEM_SECONDS_TOTAL, double.class);
|
||||||
s.accept(MetricsConst.CPU_TOTAL_SECONDS_TOTAL, double.class);
|
s.accept(MetricsConst.CPU_TOTAL_SECONDS_TOTAL, double.class);
|
||||||
@@ -52,7 +52,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* 内存
|
* 内存
|
||||||
*/
|
*/
|
||||||
MEMORY("memory", s -> {
|
MEMORY("memory", false, s -> {
|
||||||
s.accept(MetricsConst.MEM_USED_BYTES_TOTAL, long.class);
|
s.accept(MetricsConst.MEM_USED_BYTES_TOTAL, long.class);
|
||||||
s.accept(MetricsConst.MEM_USED_PERCENT, double.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_BYTES_TOTAL, long.class);
|
||||||
@@ -62,7 +62,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* 负载
|
* 负载
|
||||||
*/
|
*/
|
||||||
LOAD("load", s -> {
|
LOAD("load", false, s -> {
|
||||||
s.accept(MetricsConst.LOAD1, double.class);
|
s.accept(MetricsConst.LOAD1, double.class);
|
||||||
s.accept(MetricsConst.LOAD5, double.class);
|
s.accept(MetricsConst.LOAD5, double.class);
|
||||||
s.accept(MetricsConst.LOAD15, double.class);
|
s.accept(MetricsConst.LOAD15, double.class);
|
||||||
@@ -74,7 +74,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* 磁盘
|
* 磁盘
|
||||||
*/
|
*/
|
||||||
DISK("disk", s -> {
|
DISK("disk", true, s -> {
|
||||||
s.accept(MetricsConst.DISK_FS_USED_BYTES_TOTAL, long.class);
|
s.accept(MetricsConst.DISK_FS_USED_BYTES_TOTAL, long.class);
|
||||||
s.accept(MetricsConst.DISK_FS_USED_PERCENT, double.class);
|
s.accept(MetricsConst.DISK_FS_USED_PERCENT, double.class);
|
||||||
s.accept(MetricsConst.DISK_FS_INODES_USED_PERCENT, double.class);
|
s.accept(MetricsConst.DISK_FS_INODES_USED_PERCENT, double.class);
|
||||||
@@ -83,7 +83,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* io
|
* io
|
||||||
*/
|
*/
|
||||||
IO("io", s -> {
|
IO("io", false, s -> {
|
||||||
s.accept(MetricsConst.DISK_IO_READ_BYTES_TOTAL, long.class);
|
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_WRITE_BYTES_TOTAL, long.class);
|
||||||
s.accept(MetricsConst.DISK_IO_READS_TOTAL, long.class);
|
s.accept(MetricsConst.DISK_IO_READS_TOTAL, long.class);
|
||||||
@@ -97,7 +97,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* 网络
|
* 网络
|
||||||
*/
|
*/
|
||||||
NETWORK("network", s -> {
|
NETWORK("network", true, s -> {
|
||||||
s.accept(MetricsConst.NET_SENT_BYTES_TOTAL, long.class);
|
s.accept(MetricsConst.NET_SENT_BYTES_TOTAL, long.class);
|
||||||
s.accept(MetricsConst.NET_RECV_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_SENT_PACKETS_TOTAL, long.class);
|
||||||
@@ -111,7 +111,7 @@ public enum MeasurementEnum {
|
|||||||
/**
|
/**
|
||||||
* 连接数
|
* 连接数
|
||||||
*/
|
*/
|
||||||
CONNECTIONS("connections", s -> {
|
CONNECTIONS("connections", false, s -> {
|
||||||
s.accept(MetricsConst.NET_TCP_CONNECTIONS, int.class);
|
s.accept(MetricsConst.NET_TCP_CONNECTIONS, int.class);
|
||||||
s.accept(MetricsConst.NET_UDP_CONNECTIONS, int.class);
|
s.accept(MetricsConst.NET_UDP_CONNECTIONS, int.class);
|
||||||
s.accept(MetricsConst.NET_INET_CONNECTIONS, int.class);
|
s.accept(MetricsConst.NET_INET_CONNECTIONS, int.class);
|
||||||
@@ -121,10 +121,14 @@ public enum MeasurementEnum {
|
|||||||
;
|
;
|
||||||
|
|
||||||
private final String measurement;
|
private final String measurement;
|
||||||
|
|
||||||
|
private final boolean hasTags;
|
||||||
|
|
||||||
private final Map<String, Class<?>> fields;
|
private final Map<String, Class<?>> fields;
|
||||||
|
|
||||||
MeasurementEnum(String measurement, Consumer<BiConsumer<String, Class<?>>> register) {
|
MeasurementEnum(String measurement, boolean hasTags, Consumer<BiConsumer<String, Class<?>>> register) {
|
||||||
this.measurement = measurement;
|
this.measurement = measurement;
|
||||||
|
this.hasTags = hasTags;
|
||||||
this.fields = new HashedMap<>();
|
this.fields = new HashedMap<>();
|
||||||
register.accept(this.fields::put);
|
register.accept(this.fields::put);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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<String, Class<?>> fields;
|
|
||||||
|
|
||||||
MeasurementFieldEnum(String measurement, Consumer<BiConsumer<String, Class<?>>> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -35,7 +35,7 @@ import org.dromara.visor.module.monitor.entity.vo.AlarmEventVO;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 服务类
|
* 监控告警事件 服务类
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -44,14 +44,14 @@ import java.util.List;
|
|||||||
public interface AlarmEventService {
|
public interface AlarmEventService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建监控告警记录
|
* 创建监控告警事件
|
||||||
*
|
*
|
||||||
* @param record record
|
* @param record record
|
||||||
*/
|
*/
|
||||||
void createAlarmEvent(AlarmEventDO record);
|
void createAlarmEvent(AlarmEventDO record);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理告警记录
|
* 处理告警事件
|
||||||
*
|
*
|
||||||
* @param request request
|
* @param request request
|
||||||
* @return effect
|
* @return effect
|
||||||
@@ -67,7 +67,7 @@ public interface AlarmEventService {
|
|||||||
Integer setAlarmEventFalse(AlarmEventSetFalseRequest request);
|
Integer setAlarmEventFalse(AlarmEventSetFalseRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询监控告警记录
|
* 分页查询监控告警事件
|
||||||
*
|
*
|
||||||
* @param request request
|
* @param request request
|
||||||
* @return rows
|
* @return rows
|
||||||
@@ -75,7 +75,7 @@ public interface AlarmEventService {
|
|||||||
DataGrid<AlarmEventVO> getAlarmEventPage(AlarmEventQueryRequest request);
|
DataGrid<AlarmEventVO> getAlarmEventPage(AlarmEventQueryRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询监控告警记录数量
|
* 查询监控告警事件数量
|
||||||
*
|
*
|
||||||
* @param request request
|
* @param request request
|
||||||
* @return count
|
* @return count
|
||||||
@@ -83,7 +83,7 @@ public interface AlarmEventService {
|
|||||||
Long getAlarmEventCount(AlarmEventQueryRequest request);
|
Long getAlarmEventCount(AlarmEventQueryRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除监控告警记录
|
* 删除监控告警事件
|
||||||
*
|
*
|
||||||
* @param id id
|
* @param id id
|
||||||
* @return effect
|
* @return effect
|
||||||
@@ -91,7 +91,7 @@ public interface AlarmEventService {
|
|||||||
Integer deleteAlarmEventById(Long id);
|
Integer deleteAlarmEventById(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除监控告警记录
|
* 批量删除监控告警事件
|
||||||
*
|
*
|
||||||
* @param idList idList
|
* @param idList idList
|
||||||
* @return effect
|
* @return effect
|
||||||
@@ -99,7 +99,7 @@ public interface AlarmEventService {
|
|||||||
Integer deleteAlarmEventByIdList(List<Long> idList);
|
Integer deleteAlarmEventByIdList(List<Long> idList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理监控告警记录
|
* 清理监控告警事件
|
||||||
*
|
*
|
||||||
* @param request request
|
* @param request request
|
||||||
* @return effect
|
* @return effect
|
||||||
@@ -107,7 +107,7 @@ public interface AlarmEventService {
|
|||||||
Integer clearAlarmEvent(AlarmEventClearRequest request);
|
Integer clearAlarmEvent(AlarmEventClearRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取策略告警记录数量
|
* 获取策略告警事件数量
|
||||||
*
|
*
|
||||||
* @param policyIdList policyIdList
|
* @param policyIdList policyIdList
|
||||||
* @param startDay startDay
|
* @param startDay startDay
|
||||||
|
|||||||
@@ -74,10 +74,10 @@ public interface AlarmPolicyRuleService {
|
|||||||
* 查询全部监控告警规则
|
* 查询全部监控告警规则
|
||||||
*
|
*
|
||||||
* @param policyId policyId
|
* @param policyId policyId
|
||||||
* @param metricsMeasurement metricsMeasurement
|
* @param measurement measurement
|
||||||
* @return rows
|
* @return rows
|
||||||
*/
|
*/
|
||||||
List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String metricsMeasurement);
|
List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String measurement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 metricsId 删除监控告警规则
|
* 通过 metricsId 删除监控告警规则
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ package org.dromara.visor.module.monitor.service;
|
|||||||
|
|
||||||
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
|
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
|
||||||
import org.dromara.visor.common.entity.chart.TimeChartSeries;
|
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.*;
|
||||||
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.MonitorHostMetricsDataVO;
|
||||||
import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO;
|
import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO;
|
||||||
|
|
||||||
@@ -53,10 +50,10 @@ public interface MonitorHostService {
|
|||||||
/**
|
/**
|
||||||
* 获取监控主机指标数据
|
* 获取监控主机指标数据
|
||||||
*
|
*
|
||||||
* @param agentKeyList agentKeyList
|
* @param agentKeys agentKeys
|
||||||
* @return metrics
|
* @return metrics
|
||||||
*/
|
*/
|
||||||
List<MonitorHostMetricsDataVO> getMonitorHostMetrics(List<String> agentKeyList);
|
List<MonitorHostMetricsDataVO> getMonitorHostMetrics(List<String> agentKeys);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取监控主机图表数据
|
* 获取监控主机图表数据
|
||||||
@@ -66,6 +63,14 @@ public interface MonitorHostService {
|
|||||||
*/
|
*/
|
||||||
List<TimeChartSeries> getMonitorHostChart(MonitorHostChartRequest request);
|
List<TimeChartSeries> getMonitorHostChart(MonitorHostChartRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询监控告警标签
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return tags
|
||||||
|
*/
|
||||||
|
List<String> getMonitorHostTags(MonitorHostQueryTagRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新监控主机
|
* 更新监控主机
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import org.dromara.visor.module.monitor.dao.AlarmEventDAO;
|
|||||||
import org.dromara.visor.module.monitor.define.cache.AlarmEventCacheKeyDefine;
|
import org.dromara.visor.module.monitor.define.cache.AlarmEventCacheKeyDefine;
|
||||||
import org.dromara.visor.module.monitor.entity.domain.AlarmEventDO;
|
import org.dromara.visor.module.monitor.entity.domain.AlarmEventDO;
|
||||||
import org.dromara.visor.module.monitor.entity.dto.AlarmPolicyAlarmCountDTO;
|
import org.dromara.visor.module.monitor.entity.dto.AlarmPolicyAlarmCountDTO;
|
||||||
import org.dromara.visor.module.monitor.entity.po.AlarmPolicyRuleCountPO;
|
import org.dromara.visor.module.monitor.entity.po.AlarmEventCountPO;
|
||||||
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventClearRequest;
|
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventClearRequest;
|
||||||
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventHandleRequest;
|
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventHandleRequest;
|
||||||
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventQueryRequest;
|
import org.dromara.visor.module.monitor.entity.request.alarm.AlarmEventQueryRequest;
|
||||||
@@ -62,7 +62,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控告警记录 服务实现类
|
* 监控告警事件 服务实现类
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -198,7 +198,7 @@ public class AlarmEventServiceImpl implements AlarmEventService {
|
|||||||
if (!queryIdList.isEmpty()) {
|
if (!queryIdList.isEmpty()) {
|
||||||
Map<Long, Integer> countMap = alarmEventDAO.selectPolicyEventCount(queryIdList, startDate, endDate)
|
Map<Long, Integer> countMap = alarmEventDAO.selectPolicyEventCount(queryIdList, startDate, endDate)
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(AlarmPolicyRuleCountPO::getPolicyId, AlarmPolicyRuleCountPO::getCount));
|
.collect(Collectors.toMap(AlarmEventCountPO::getPolicyId, AlarmEventCountPO::getCount));
|
||||||
// 设置缓存
|
// 设置缓存
|
||||||
for (Long policyId : queryIdList) {
|
for (Long policyId : queryIdList) {
|
||||||
Integer count = Objects1.def(countMap.get(policyId), 0);
|
Integer count = Objects1.def(countMap.get(policyId), 0);
|
||||||
|
|||||||
@@ -160,13 +160,13 @@ public class AlarmPolicyRuleServiceImpl implements AlarmPolicyRuleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String metricsMeasurement) {
|
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String measurement) {
|
||||||
// 查询
|
// 查询
|
||||||
return alarmPolicyRuleDAO.of()
|
return alarmPolicyRuleDAO.of()
|
||||||
.createWrapper()
|
.createWrapper()
|
||||||
.eq(AlarmPolicyRuleDO::getPolicyId, policyId)
|
.eq(AlarmPolicyRuleDO::getPolicyId, policyId)
|
||||||
.eq(Strings.isNotBlank(metricsMeasurement), AlarmPolicyRuleDO::getMetricsMeasurement, metricsMeasurement)
|
.eq(Strings.isNotBlank(measurement), AlarmPolicyRuleDO::getMetricsMeasurement, measurement)
|
||||||
// 想同的指标在一起
|
// 相同的指标在一起
|
||||||
.orderByAsc(AlarmPolicyRuleDO::getMetricsId)
|
.orderByAsc(AlarmPolicyRuleDO::getMetricsId)
|
||||||
// 通过 p0 > p1 排序
|
// 通过 p0 > p1 排序
|
||||||
.orderByAsc(AlarmPolicyRuleDO::getLevel)
|
.orderByAsc(AlarmPolicyRuleDO::getLevel)
|
||||||
|
|||||||
@@ -173,14 +173,14 @@ public class AlarmPolicyServiceImpl implements AlarmPolicyService {
|
|||||||
@Override
|
@Override
|
||||||
public List<AlarmPolicyVO> getAlarmPolicyListByCache() {
|
public List<AlarmPolicyVO> getAlarmPolicyListByCache() {
|
||||||
// 查询缓存
|
// 查询缓存
|
||||||
List<AlarmPolicyCacheDTO> list = RedisMaps.valuesJson(AlarmPolicyCacheKeyDefine.MONITOR_ALARM_POLICY);
|
List<AlarmPolicyCacheDTO> list = RedisMaps.valuesJson(AlarmPolicyCacheKeyDefine.ALARM_POLICY);
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
// 查询数据库
|
// 查询数据库
|
||||||
list = alarmPolicyDAO.of().list(AlarmPolicyConvert.MAPPER::toCache);
|
list = alarmPolicyDAO.of().list(AlarmPolicyConvert.MAPPER::toCache);
|
||||||
// 设置屏障 防止穿透
|
// 设置屏障 防止穿透
|
||||||
CacheBarriers.checkBarrier(list, AlarmPolicyCacheDTO::new);
|
CacheBarriers.checkBarrier(list, AlarmPolicyCacheDTO::new);
|
||||||
// 设置缓存
|
// 设置缓存
|
||||||
RedisMaps.putAllJson(AlarmPolicyCacheKeyDefine.MONITOR_ALARM_POLICY, s -> s.getId().toString(), list);
|
RedisMaps.putAllJson(AlarmPolicyCacheKeyDefine.ALARM_POLICY, s -> s.getId().toString(), list);
|
||||||
}
|
}
|
||||||
// 删除屏障
|
// 删除屏障
|
||||||
CacheBarriers.removeBarrier(list);
|
CacheBarriers.removeBarrier(list);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ public class MonitorAgentEndpointServiceImpl implements MonitorAgentEndpointServ
|
|||||||
}
|
}
|
||||||
monitorHostDAO.updateById(update);
|
monitorHostDAO.updateById(update);
|
||||||
}
|
}
|
||||||
// 设置配置缓存
|
// 重新加载监控主机上下文
|
||||||
if (newConfig != null) {
|
if (newConfig != null) {
|
||||||
monitorContext.reloadMonitorHost(agentKey);
|
monitorContext.reloadMonitorHost(agentKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,10 +55,7 @@ import org.dromara.visor.module.monitor.engine.MonitorContext;
|
|||||||
import org.dromara.visor.module.monitor.entity.domain.AlarmPolicyDO;
|
import org.dromara.visor.module.monitor.entity.domain.AlarmPolicyDO;
|
||||||
import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO;
|
import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO;
|
||||||
import org.dromara.visor.module.monitor.entity.dto.*;
|
import org.dromara.visor.module.monitor.entity.dto.*;
|
||||||
import org.dromara.visor.module.monitor.entity.request.host.MonitorHostChartRequest;
|
import org.dromara.visor.module.monitor.entity.request.host.*;
|
||||||
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.MonitorHostMetricsDataVO;
|
||||||
import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO;
|
import org.dromara.visor.module.monitor.entity.vo.MonitorHostVO;
|
||||||
import org.dromara.visor.module.monitor.enums.AlarmSwitchEnum;
|
import org.dromara.visor.module.monitor.enums.AlarmSwitchEnum;
|
||||||
@@ -188,8 +185,8 @@ public class MonitorHostServiceImpl implements MonitorHostService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MonitorHostMetricsDataVO> getMonitorHostMetrics(List<String> agentKeyList) {
|
public List<MonitorHostMetricsDataVO> getMonitorHostMetrics(List<String> agentKeys) {
|
||||||
return agentKeyList.stream()
|
return agentKeys.stream()
|
||||||
.map(s -> this.getHostMetricsData(s, null))
|
.map(s -> this.getHostMetricsData(s, null))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@@ -235,6 +232,44 @@ public class MonitorHostServiceImpl implements MonitorHostService {
|
|||||||
return seriesList;
|
return seriesList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getMonitorHostTags(MonitorHostQueryTagRequest request) {
|
||||||
|
MeasurementEnum measurementEnum = MeasurementEnum.of(request.getMeasurement());
|
||||||
|
if (measurementEnum == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
// 映射数据
|
||||||
|
Function<MonitorHostMetaDTO, List<String>> tagsGetter;
|
||||||
|
if (MeasurementEnum.CPU.equals(measurementEnum)) {
|
||||||
|
tagsGetter = MonitorHostMetaDTO::getCpus;
|
||||||
|
} else if (MeasurementEnum.DISK.equals(measurementEnum)) {
|
||||||
|
tagsGetter = MonitorHostMetaDTO::getDisks;
|
||||||
|
} else if (MeasurementEnum.NETWORK.equals(measurementEnum)) {
|
||||||
|
tagsGetter = MonitorHostMetaDTO::getNets;
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
// 查询监控主机元数据
|
||||||
|
List<MonitorHostMetaDTO> metas = monitorHostDAO.of()
|
||||||
|
.createValidateWrapper()
|
||||||
|
.eq(MonitorHostDO::getPolicyId, request.getPolicyId())
|
||||||
|
.in(MonitorHostDO::getAgentKey, request.getAgentKeys())
|
||||||
|
.then()
|
||||||
|
.stream()
|
||||||
|
.map(MonitorHostDO::getMonitorMeta)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(s -> JSON.parseObject(s, MonitorHostMetaDTO.class))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// 获取 tag
|
||||||
|
return metas.stream()
|
||||||
|
.map(tagsGetter)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Integer updateMonitorHostById(MonitorHostUpdateRequest request) {
|
public Integer updateMonitorHostById(MonitorHostUpdateRequest request) {
|
||||||
@@ -272,7 +307,7 @@ public class MonitorHostServiceImpl implements MonitorHostService {
|
|||||||
if (policyId == null) {
|
if (policyId == null) {
|
||||||
monitorHostDAO.setPolicyIdWithNullById(id);
|
monitorHostDAO.setPolicyIdWithNullById(id);
|
||||||
}
|
}
|
||||||
// 更新缓存
|
// 重新加载监控主机上下文
|
||||||
monitorContext.reloadMonitorHost(host.getAgentKey());
|
monitorContext.reloadMonitorHost(host.getAgentKey());
|
||||||
log.info("MonitorHostService-updateMonitorHostById effect: {}", effect);
|
log.info("MonitorHostService-updateMonitorHostById effect: {}", effect);
|
||||||
return effect;
|
return effect;
|
||||||
@@ -372,6 +407,7 @@ public class MonitorHostServiceImpl implements MonitorHostService {
|
|||||||
} else {
|
} else {
|
||||||
Assert.notNull(request.getStart(), ErrorMessage.PARAM_MISSING);
|
Assert.notNull(request.getStart(), ErrorMessage.PARAM_MISSING);
|
||||||
Assert.notNull(request.getEnd(), ErrorMessage.PARAM_MISSING);
|
Assert.notNull(request.getEnd(), ErrorMessage.PARAM_MISSING);
|
||||||
|
query.range(request.getStart(), request.getEnd());
|
||||||
}
|
}
|
||||||
// 设置名称
|
// 设置名称
|
||||||
Set<String> names = null;
|
Set<String> names = null;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<!-- 操作数量映射结果 -->
|
<!-- 操作数量映射结果 -->
|
||||||
<resultMap id="CountResultMap" type="org.dromara.visor.module.monitor.entity.po.AlarmPolicyRuleCountPO">
|
<resultMap id="CountResultMap" type="org.dromara.visor.module.monitor.entity.po.AlarmEventCountPO">
|
||||||
<result column="policy_id" property="policyId"/>
|
<result column="policy_id" property="policyId"/>
|
||||||
<result column="total_count" property="count"/>
|
<result column="total_count" property="count"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
@@ -48,6 +48,7 @@
|
|||||||
SELECT policy_id, COUNT(1) total_count
|
SELECT policy_id, COUNT(1) total_count
|
||||||
FROM monitor_alarm_event
|
FROM monitor_alarm_event
|
||||||
WHERE deleted = 0
|
WHERE deleted = 0
|
||||||
|
AND false_alarm = 0
|
||||||
AND policy_id IN
|
AND policy_id IN
|
||||||
<foreach collection="policyIdList" item="item" open="(" separator="," close=")">
|
<foreach collection="policyIdList" item="item" open="(" separator="," close=")">
|
||||||
#{item}
|
#{item}
|
||||||
|
|||||||
@@ -83,6 +83,10 @@
|
|||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.visor</groupId>
|
||||||
|
<artifactId>orion-visor-spring-boot-starter-executor</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.visor</groupId>
|
<groupId>org.dromara.visor</groupId>
|
||||||
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
<artifactId>orion-visor-spring-boot-starter-test</artifactId>
|
||||||
|
|||||||
@@ -22,12 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.dromara.visor.module.terminal.define;
|
package org.dromara.visor.module.terminal.define;
|
||||||
|
|
||||||
import cn.orionsec.kit.lang.define.thread.ExecutorBuilder;
|
import org.dromara.visor.framework.executor.core.utils.ExecutorUtils;
|
||||||
import org.dromara.visor.common.constant.Const;
|
|
||||||
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 终端线程池
|
* 终端线程池
|
||||||
@@ -39,37 +36,18 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
public interface TerminalThreadPools {
|
public interface TerminalThreadPools {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* terminal 标准输出线程池
|
* 终端标准输出线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor TERMINAL_STDOUT = ExecutorBuilder.create()
|
Executor TERMINAL_STDOUT = ExecutorUtils.getExecutor("terminalStdoutExecutor");
|
||||||
.namedThreadFactory("terminal-stdout-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* terminal 操作线程池
|
* 终端操作线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor TERMINAL_OPERATOR = ExecutorBuilder.create()
|
Executor TERMINAL_OPERATOR = ExecutorUtils.getExecutor("terminalOperatorExecutor");
|
||||||
.namedThreadFactory("terminal-operator-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(Integer.MAX_VALUE)
|
|
||||||
.keepAliveTime(Const.MS_S_60)
|
|
||||||
.workQueue(new SynchronousQueue<>())
|
|
||||||
.allowCoreThreadTimeout(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 终端异步保存线程池
|
* 终端异步保存线程池
|
||||||
*/
|
*/
|
||||||
ThreadPoolExecutor TERMINAL_ASYNC_SAVER = ExecutorBuilder.create()
|
Executor TERMINAL_ASYNC_SAVER = ExecutorUtils.getExecutor("terminalAsyncSaverExecutor");
|
||||||
.namedThreadFactory("terminal-async-saver-")
|
|
||||||
.corePoolSize(1)
|
|
||||||
.maxPoolSize(1)
|
|
||||||
.workQueue(new LinkedBlockingQueue<>())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ VITE_API_BASE_URL=http://127.0.0.1:9200/orion-visor/api
|
|||||||
# websocket 路径
|
# websocket 路径
|
||||||
VITE_WS_BASE_URL=ws://127.0.0.1:9200/orion-visor/keep-alive
|
VITE_WS_BASE_URL=ws://127.0.0.1:9200/orion-visor/keep-alive
|
||||||
# 版本号
|
# 版本号
|
||||||
VITE_APP_VERSION=2.5.2
|
VITE_APP_VERSION=2.5.3
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ VITE_API_BASE_URL=/orion-visor/api
|
|||||||
# websocket 路径
|
# websocket 路径
|
||||||
VITE_WS_BASE_URL=/orion-visor/keep-alive
|
VITE_WS_BASE_URL=/orion-visor/keep-alive
|
||||||
# 版本号
|
# 版本号
|
||||||
VITE_APP_VERSION=2.5.2
|
VITE_APP_VERSION=2.5.3
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico">
|
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Orion Visor</title>
|
<title>Orion Visor</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "orion-visor-ui",
|
"name": "orion-visor-ui",
|
||||||
"description": "Orion Visor UI",
|
"description": "Orion Visor UI",
|
||||||
"version": "2.5.2",
|
"version": "2.5.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": "Jiahang Li",
|
"author": "Jiahang Li",
|
||||||
"license": "Apache 2.0",
|
"license": "Apache 2.0",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import axios from 'axios';
|
|||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录处理请求
|
* 告警事件处理请求
|
||||||
*/
|
*/
|
||||||
export interface AlarmEventHandleRequest {
|
export interface AlarmEventHandleRequest {
|
||||||
idList?: Array<number>;
|
idList?: Array<number>;
|
||||||
@@ -14,14 +14,14 @@ export interface AlarmEventHandleRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录误报请求
|
* 告警事件误报请求
|
||||||
*/
|
*/
|
||||||
export interface AlarmEventFalseAlarmRequest {
|
export interface AlarmEventFalseAlarmRequest {
|
||||||
idList?: Array<number>;
|
idList?: Array<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录查询请求
|
* 告警事件查询请求
|
||||||
*/
|
*/
|
||||||
export interface AlarmEventQueryRequest extends Pagination, OrderDirection {
|
export interface AlarmEventQueryRequest extends Pagination, OrderDirection {
|
||||||
id?: number;
|
id?: number;
|
||||||
@@ -39,13 +39,13 @@ export interface AlarmEventQueryRequest extends Pagination, OrderDirection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录清理请求
|
* 告警事件清理请求
|
||||||
*/
|
*/
|
||||||
export interface AlarmEventClearRequest extends AlarmEventQueryRequest, ClearRequest {
|
export interface AlarmEventClearRequest extends AlarmEventQueryRequest, ClearRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警记录查询响应
|
* 告警事件查询响应
|
||||||
*/
|
*/
|
||||||
export interface AlarmEventQueryResponse extends TableData {
|
export interface AlarmEventQueryResponse extends TableData {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -75,7 +75,7 @@ export interface AlarmEventQueryResponse extends TableData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理告警记录
|
* 处理告警事件
|
||||||
*/
|
*/
|
||||||
export function handleAlarmEvent(request: AlarmEventHandleRequest) {
|
export function handleAlarmEvent(request: AlarmEventHandleRequest) {
|
||||||
return axios.post<number>('/monitor/alarm-event/handle', request);
|
return axios.post<number>('/monitor/alarm-event/handle', request);
|
||||||
@@ -89,28 +89,28 @@ export function setAlarmEventFalse(request: AlarmEventFalseAlarmRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询告警记录
|
* 分页查询告警事件
|
||||||
*/
|
*/
|
||||||
export function getAlarmEventPage(request: AlarmEventQueryRequest) {
|
export function getAlarmEventPage(request: AlarmEventQueryRequest) {
|
||||||
return axios.post<DataGrid<AlarmEventQueryResponse>>('/monitor/alarm-event/query', request);
|
return axios.post<DataGrid<AlarmEventQueryResponse>>('/monitor/alarm-event/query', request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询告警记录数量
|
* 查询告警事件数量
|
||||||
*/
|
*/
|
||||||
export function getAlarmEventCount(request: AlarmEventQueryRequest) {
|
export function getAlarmEventCount(request: AlarmEventQueryRequest) {
|
||||||
return axios.post<number>('/monitor/alarm-event/count', request);
|
return axios.post<number>('/monitor/alarm-event/count', request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除告警记录
|
* 删除告警事件
|
||||||
*/
|
*/
|
||||||
export function deleteAlarmEvent(id: number) {
|
export function deleteAlarmEvent(id: number) {
|
||||||
return axios.delete<number>('/monitor/alarm-event/delete', { params: { id } });
|
return axios.delete<number>('/monitor/alarm-event/delete', { params: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除告警记录
|
* 批量删除告警事件
|
||||||
*/
|
*/
|
||||||
export function batchDeleteAlarmEvent(idList: Array<number>) {
|
export function batchDeleteAlarmEvent(idList: Array<number>) {
|
||||||
return axios.delete<number>('/monitor/alarm-event/batch-delete', {
|
return axios.delete<number>('/monitor/alarm-event/batch-delete', {
|
||||||
@@ -122,7 +122,7 @@ export function batchDeleteAlarmEvent(idList: Array<number>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理告警记录
|
* 清理告警事件
|
||||||
*/
|
*/
|
||||||
export function clearMonitorAlarmEvent(request: AlarmEventClearRequest) {
|
export function clearMonitorAlarmEvent(request: AlarmEventClearRequest) {
|
||||||
return axios.post<number>('/monitor/alarm-event/clear', request);
|
return axios.post<number>('/monitor/alarm-event/clear', request);
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ export function updateAlarmRuleSwitch(request: AlarmRuleUpdateRequest) {
|
|||||||
/**
|
/**
|
||||||
* 查询全部监控告警规则
|
* 查询全部监控告警规则
|
||||||
*/
|
*/
|
||||||
export function getAlarmRuleList(policyId: number, metricsMeasurement: string = '') {
|
export function getAlarmRuleList(policyId: number, measurement: string = '') {
|
||||||
return axios.get<Array<AlarmRuleQueryResponse>>('/monitor/alarm-policy-rule/list', { params: { policyId, metricsMeasurement } });
|
return axios.get<Array<AlarmRuleQueryResponse>>('/monitor/alarm-policy-rule/list', { params: { policyId, measurement } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export interface MonitorHostSwitchUpdateRequest {
|
|||||||
* 监控主机查询请求
|
* 监控主机查询请求
|
||||||
*/
|
*/
|
||||||
export interface MonitorHostQueryRequest extends Pagination {
|
export interface MonitorHostQueryRequest extends Pagination {
|
||||||
agentKeyList?: Array<string>;
|
agentKeys?: Array<string>;
|
||||||
searchValue?: string;
|
searchValue?: string;
|
||||||
alarmSwitch?: number;
|
alarmSwitch?: number;
|
||||||
policyId?: number;
|
policyId?: number;
|
||||||
@@ -43,6 +43,15 @@ export interface MonitorHostQueryRequest extends Pagination {
|
|||||||
tags?: Array<number>;
|
tags?: Array<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监控主机标签查询请求
|
||||||
|
*/
|
||||||
|
export interface MonitorHostQueryTagRequest {
|
||||||
|
measurement?: string;
|
||||||
|
policyId?: number;
|
||||||
|
agentKeys?: Array<string>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控主机图表查询请求
|
* 监控主机图表查询请求
|
||||||
*/
|
*/
|
||||||
@@ -147,12 +156,12 @@ export interface MonitorHostMetricsData {
|
|||||||
/**
|
/**
|
||||||
* 查询监控主机指标
|
* 查询监控主机指标
|
||||||
*/
|
*/
|
||||||
export function getMonitorHostMetrics(agentKeyList: Array<string>) {
|
export function getMonitorHostMetrics(agentKeys: Array<string>) {
|
||||||
return axios.post<Array<MonitorHostMetricsData>>('/monitor/monitor-host/metrics', {
|
return axios.post<Array<MonitorHostMetricsData>>('/monitor/monitor-host/metrics', {
|
||||||
agentKeyList
|
agentKeys
|
||||||
}, {
|
}, {
|
||||||
promptBizErrorMessage: false,
|
promptBizErrorMessage: false,
|
||||||
promptRequestErrorMessage: false,
|
promptRequestErrorMessage: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +176,9 @@ export function getMonitorHostOverride(agentKey: string) {
|
|||||||
* 查询监控主机图表
|
* 查询监控主机图表
|
||||||
*/
|
*/
|
||||||
export function getMonitorHostChart(request: MonitorHostChartRequest) {
|
export function getMonitorHostChart(request: MonitorHostChartRequest) {
|
||||||
return axios.post<Array<TimeChartSeries>>('/monitor/monitor-host/chart', request);
|
return axios.post<Array<TimeChartSeries>>('/monitor/monitor-host/chart', request, {
|
||||||
|
timeout: 180000,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,6 +188,13 @@ export function getMonitorHostPage(request: MonitorHostQueryRequest) {
|
|||||||
return axios.post<DataGrid<MonitorHostQueryResponse>>('/monitor/monitor-host/query', request);
|
return axios.post<DataGrid<MonitorHostQueryResponse>>('/monitor/monitor-host/query', request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询监控主机标签
|
||||||
|
*/
|
||||||
|
export function getMonitorHostTags(request: MonitorHostQueryTagRequest) {
|
||||||
|
return axios.post<Array<string>>('/monitor/monitor-host/host-tags', request);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新监控主机
|
* 更新监控主机
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
|
|
||||||
// 标准卡片
|
// 标准卡片
|
||||||
.general-card {
|
.general-card {
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
& > .arco-card-header {
|
& > .arco-card-header {
|
||||||
|
|||||||
@@ -14,58 +14,6 @@ body {
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- echarts
|
|
||||||
.echarts-tooltip-diy {
|
|
||||||
background: linear-gradient(304.17deg,
|
|
||||||
rgba(253, 254, 255, 0.6) -6.04%,
|
|
||||||
rgba(244, 247, 252, 0.6) 85.2%) !important;
|
|
||||||
border: none !important;
|
|
||||||
backdrop-filter: blur(10px) !important;
|
|
||||||
/* Note: backdrop-filter has minimal browser support */
|
|
||||||
|
|
||||||
border-radius: 6px !important;
|
|
||||||
|
|
||||||
.content-panel {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 9px;
|
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
width: 164px;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
box-shadow: 6px 0 20px rgba(34, 87, 188, 0.1);
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-title {
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-title,
|
|
||||||
.tooltip-value {
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 15px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
text-align: right;
|
|
||||||
color: #1D2129;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-item-icon {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 8px;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// flex
|
// flex
|
||||||
.flex-center {
|
.flex-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -162,8 +162,8 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-neutral-3);
|
//border: 1px solid var(--color-neutral-3);
|
||||||
transition-property: all;
|
transition-property: all;
|
||||||
|
|
||||||
& > .arco-card-header {
|
& > .arco-card-header {
|
||||||
@@ -230,7 +230,7 @@
|
|||||||
// -- card
|
// -- card
|
||||||
.simple-card {
|
.simple-card {
|
||||||
background: var(--color-bg-2);
|
background: var(--color-bg-2);
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- doption
|
// -- doption
|
||||||
|
|||||||
@@ -27,7 +27,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 状态 -->
|
<!-- 状态 -->
|
||||||
<div class="exec-host-item-status">
|
<div class="exec-host-item-status">
|
||||||
<a-tag :color="getDictValue(execHostStatusKey, item.status, 'execColor')">
|
<!-- 执行结果 -->
|
||||||
|
<a-tag v-if="item.exitCode || item.exitCode === 0"
|
||||||
|
class="exit-code-tag"
|
||||||
|
title="exitCode"
|
||||||
|
:color="item.exitCode === 0 ? 'rgb(var(--arcoblue-4))' : 'rgb(var(--orangered-4))'">
|
||||||
|
<template #icon>
|
||||||
|
<icon-check v-if="item.exitCode === 0" />
|
||||||
|
<icon-exclamation v-else />
|
||||||
|
</template>
|
||||||
|
<span class="exit-code-value">{{ item.exitCode }}</span>
|
||||||
|
</a-tag>
|
||||||
|
<!-- 执行状态 -->
|
||||||
|
<a-tag v-else :color="getDictValue(execHostStatusKey, item.status, 'execColor')">
|
||||||
{{ getDictValue(execHostStatusKey, item.status) }}
|
{{ getDictValue(execHostStatusKey, item.status) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,8 +153,16 @@
|
|||||||
&-status {
|
&-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
:deep(.exit-code-tag .arco-tag-icon) {
|
||||||
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.exit-code-value {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<!-- exitCode -->
|
<!-- exitCode -->
|
||||||
<a-tag v-if="host.exitCode || host.exitCode === 0"
|
<a-tag v-if="host.exitCode || host.exitCode === 0"
|
||||||
:color="host.exitCode === 0 ? 'arcoblue' : 'orangered'"
|
:color="host.exitCode === 0 ? 'arcoblue' : 'orangered'"
|
||||||
title="exit code">
|
title="exitCode">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-check v-if="host.exitCode === 0" />
|
<icon-check v-if="host.exitCode === 0" />
|
||||||
<icon-exclamation v-else />
|
<icon-exclamation v-else />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full">
|
<div v-if="render" class="full">
|
||||||
<!-- 消息分类 -->
|
<!-- 消息分类 -->
|
||||||
<a-spin class="message-classify-container"
|
<a-spin class="message-classify-container"
|
||||||
:hide-icon="true"
|
:hide-icon="true"
|
||||||
@@ -90,6 +90,7 @@
|
|||||||
const classifyCount = ref<Record<string, number>>({});
|
const classifyCount = ref<Record<string, number>>({});
|
||||||
const messageList = ref<Array<MessageRecordResponse>>([]);
|
const messageList = ref<Array<MessageRecordResponse>>([]);
|
||||||
const hasMore = ref(true);
|
const hasMore = ref(true);
|
||||||
|
const render = ref(false);
|
||||||
|
|
||||||
// 重新加载消息
|
// 重新加载消息
|
||||||
const reloadAllMessage = async () => {
|
const reloadAllMessage = async () => {
|
||||||
@@ -210,8 +211,9 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 加载字典值
|
// 加载字典值
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
loadKeys(dictKeys);
|
await loadKeys(dictKeys);
|
||||||
|
render.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取消息
|
// 获取消息
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
&-wrapper {
|
&-wrapper {
|
||||||
background: var(--color-bg-2);
|
background: var(--color-bg-2);
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
|
|
||||||
.card-list-info {
|
.card-list-info {
|
||||||
height: var(--header-info-height);
|
height: var(--header-info-height);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { RouteLocationRaw, Router } from 'vue-router';
|
|||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import { isLogin } from '@/utils/auth';
|
import { isLogin } from '@/utils/auth';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { LOGIN_ROUTE_NAME, UPDATE_PASSWORD_ROUTE_NAME } from '@/router/constants';
|
import { LOGIN_ROUTE_NAME, UPDATE_PASSWORD_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +31,7 @@ export default function setupUserLoginInfoGuard(router: Router) {
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Message.error('获取用户信息失败');
|
||||||
// 获取失败退出登录
|
// 获取失败退出登录
|
||||||
await userStore.logout();
|
await userStore.logout();
|
||||||
next({
|
next({
|
||||||
|
|||||||
@@ -3,8 +3,28 @@ import type { DictState } from './types';
|
|||||||
import type { Options } from '@/types/global';
|
import type { Options } from '@/types/global';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { getDictValueList } from '@/api/system/dict-value';
|
import { getDictValueList } from '@/api/system/dict-value';
|
||||||
|
import { isArray } from '@/utils/is';
|
||||||
|
|
||||||
export const ALL_OPTION: Options = { label: '全部', value: '' };
|
const AllOption: Options = { label: '全部', value: '' };
|
||||||
|
|
||||||
|
// 获取拼接的选项
|
||||||
|
const getPrependOptions = (perpendOption: boolean | Options | Options[] | RadioOption | RadioOption[]): Options[] => {
|
||||||
|
if (!perpendOption) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (perpendOption === true) {
|
||||||
|
// 默认选项
|
||||||
|
return [{ ...AllOption }];
|
||||||
|
} else if (isArray(perpendOption)) {
|
||||||
|
// 数组选项
|
||||||
|
return perpendOption.map(s => {
|
||||||
|
return { ...s } as Options;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 单一选项
|
||||||
|
return [{ ...perpendOption as Options }];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default defineStore('dict', {
|
export default defineStore('dict', {
|
||||||
state: (): DictState => ({}),
|
state: (): DictState => ({}),
|
||||||
@@ -27,38 +47,30 @@ export default defineStore('dict', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 获取字典选项
|
// 获取字典选项
|
||||||
toOptions(key: string, firstOption: boolean | Record<string, any> = false): Options[] {
|
toOptions(key: string, perpendOption: boolean | Options | Options[] = false): Options[] {
|
||||||
if (firstOption === true) {
|
let perpendOptions = getPrependOptions(perpendOption);
|
||||||
return [{ ...ALL_OPTION }, ...this.$state[key]];
|
const options = this.$state[key] ?? [];
|
||||||
} else if (firstOption) {
|
return [...perpendOptions, ...options];
|
||||||
return [{ ...ALL_OPTION, ...firstOption }, ...this.$state[key]];
|
|
||||||
} else {
|
|
||||||
return this.$state[key];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 转为 unref 的字典选项
|
// 转为 unref 的字典选项
|
||||||
toUnrefOptions(key: string, firstOption: boolean | Record<string, any> = false): Options[] {
|
toUnrefOptions(key: string, perpendOption: boolean | Options | Options[] = false): Options[] {
|
||||||
return this.toOptions(key, firstOption)
|
return this.toOptions(key, perpendOption)
|
||||||
.map(s => {
|
.map(s => {
|
||||||
return { ...s };
|
return { ...s };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取字典选项
|
// 获取字典选项
|
||||||
toRadioOptions(key: string, firstOption: boolean | Record<string, any> = false): RadioOption[] {
|
toRadioOptions(key: string, perpendOption: boolean | RadioOption | RadioOption[] = false): RadioOption[] {
|
||||||
if (firstOption === true) {
|
let perpendOptions = getPrependOptions(perpendOption);
|
||||||
return [{ ...ALL_OPTION }, ...this.$state[key]] as RadioOption[];
|
const options = this.$state[key] ?? [];
|
||||||
} else if (firstOption) {
|
return [...perpendOptions, ...options] as RadioOption[];
|
||||||
return [{ ...ALL_OPTION, ...firstOption }, ...this.$state[key]] as RadioOption[];
|
|
||||||
} else {
|
|
||||||
return this.$state[key] as RadioOption[];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 转为 unref 的字典选项
|
// 转为 unref 的字典选项
|
||||||
toUnrefRadioOptions(key: string, firstOption: boolean | Record<string, any> = false): RadioOption[] {
|
toUnrefRadioOptions(key: string, perpendOption: boolean | RadioOption | RadioOption[] = false): RadioOption[] {
|
||||||
return this.toRadioOptions(key, firstOption)
|
return this.toRadioOptions(key, perpendOption)
|
||||||
.map(s => {
|
.map(s => {
|
||||||
return { ...s };
|
return { ...s };
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export interface TimeSeriesColor {
|
|||||||
export interface TimeSeriesOption {
|
export interface TimeSeriesOption {
|
||||||
name: string;
|
name: string;
|
||||||
type: TimeSeriesType;
|
type: TimeSeriesType;
|
||||||
|
smooth: boolean;
|
||||||
area: boolean;
|
area: boolean;
|
||||||
lineColor: string;
|
lineColor: string;
|
||||||
itemBorderColor: string;
|
itemBorderColor: string;
|
||||||
@@ -126,7 +127,7 @@ export const createTimeSeries = (option: Partial<TimeSeriesOption>): LineSeriesO
|
|||||||
name: option.name,
|
name: option.name,
|
||||||
data: option.data || [],
|
data: option.data || [],
|
||||||
type: option.type || 'line',
|
type: option.type || 'line',
|
||||||
smooth: true,
|
smooth: option.smooth ?? true,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: 10,
|
symbolSize: 10,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ export function isString(obj: any): obj is string {
|
|||||||
return opt.call(obj) === '[object String]';
|
return opt.call(obj) === '[object String]';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isBoolean(obj: any): obj is boolean {
|
||||||
|
return opt.call(obj) === '[object Boolean]';
|
||||||
|
}
|
||||||
|
|
||||||
export function isNumber(obj: any): obj is number {
|
export function isNumber(obj: any): obj is number {
|
||||||
return opt.call(obj) === '[object Number]' && obj === obj; // eslint-disable-line
|
return opt.call(obj) === '[object Number]' && obj === obj; // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
:deep(.card) {
|
:deep(.card) {
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
background-color: var(--color-bg-2);
|
background-color: var(--color-bg-2);
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
|
|||||||
@@ -301,7 +301,7 @@
|
|||||||
.panel-item {
|
.panel-item {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--color-bg-2);
|
background: var(--color-bg-2);
|
||||||
|
|||||||
@@ -295,7 +295,7 @@
|
|||||||
|
|
||||||
.exec-form-container, .exec-command-container, .exec-history-container {
|
.exec-form-container, .exec-command-container, .exec-history-container {
|
||||||
background: var(--color-bg-2);
|
background: var(--color-bg-2);
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<div class="table-left-bar-handle">
|
<div class="table-left-bar-handle">
|
||||||
<!-- 标题 -->
|
<!-- 标题 -->
|
||||||
<div class="table-title">
|
<div class="table-title">
|
||||||
告警记录列表
|
告警事件列表
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 右侧操作 -->
|
<!-- 右侧操作 -->
|
||||||
@@ -229,7 +229,7 @@
|
|||||||
|
|
||||||
// 获取指标名称
|
// 获取指标名称
|
||||||
const getMetricsField = (metricsId: number, field: string) => {
|
const getMetricsField = (metricsId: number, field: string) => {
|
||||||
return (monitorMetrics as Array<MetricsQueryResponse>).find(m => m.id === metricsId)?.[field];
|
return (monitorMetrics as Array<MetricsQueryResponse> || []).find(m => m.id === metricsId)?.[field];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 提取标签
|
// 提取标签
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 数据集 -->
|
<!-- 数据集 -->
|
||||||
<a-form-item field="metricsId" label="数据集">
|
<a-form-item field="metricsMeasurement" label="数据集">
|
||||||
<a-select v-model="formModel.metricsMeasurement"
|
<a-select v-model="formModel.metricsMeasurement"
|
||||||
:options="toOptions(MetricsMeasurementKey)"
|
:options="toOptions(MetricsMeasurementKey)"
|
||||||
placeholder="数据集"
|
placeholder="数据集"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const FalseAlarm = {
|
|||||||
// 告警条件 字典项
|
// 告警条件 字典项
|
||||||
export const TriggerConditionKey = 'alarmTriggerCondition';
|
export const TriggerConditionKey = 'alarmTriggerCondition';
|
||||||
|
|
||||||
// 告警记录处理状态 字典项
|
// 告警事件处理状态 字典项
|
||||||
export const HandleStatusKey = 'alarmEventHandleStatus';
|
export const HandleStatusKey = 'alarmEventHandleStatus';
|
||||||
|
|
||||||
// 是否为误报 字典项
|
// 是否为误报 字典项
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
placeholder="请输入策略描述"
|
placeholder="请输入策略描述"
|
||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 通知模板 -->
|
<!-- 通知渠道 -->
|
||||||
<a-form-item field="notifyIdList" label="通知模板">
|
<a-form-item field="notifyIdList" label="通知渠道">
|
||||||
<notify-template-selector v-model="formModel.notifyIdList"
|
<notify-template-selector v-model="formModel.notifyIdList"
|
||||||
biz-type="ALARM"
|
biz-type="ALARM"
|
||||||
multiple
|
multiple
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
:unmount-on-close="true"
|
:unmount-on-close="true"
|
||||||
:ok-button-props="{ disabled: loading }"
|
:ok-button-props="{ disabled: loading }"
|
||||||
:cancel-button-props="{ disabled: loading }"
|
:cancel-button-props="{ disabled: loading }"
|
||||||
:on-before-ok="handlerOk"
|
:on-before-ok="handleOk"
|
||||||
@cancel="handleClose">
|
@cancel="handleClose">
|
||||||
<a-spin class="full drawer-form-large" :loading="loading">
|
<a-spin class="full drawer-form-large" :loading="loading">
|
||||||
<a-form :model="formModel"
|
<a-form :model="formModel"
|
||||||
@@ -17,11 +17,12 @@
|
|||||||
<!-- 监控指标 -->
|
<!-- 监控指标 -->
|
||||||
<a-form-item field="metricsId" label="监控指标">
|
<a-form-item field="metricsId" label="监控指标">
|
||||||
<monitor-metrics-selector v-model="formModel.metricsId"
|
<monitor-metrics-selector v-model="formModel.metricsId"
|
||||||
class="metrics-selector"
|
:class="[ hasTags ? 'metrics-selector-has-tag' : 'metrics-selector-no-tag']"
|
||||||
placeholder="请选择监控指标"
|
placeholder="请选择监控指标"
|
||||||
allow-clear />
|
allow-clear />
|
||||||
<!-- 添加标签 -->
|
<!-- 添加标签 -->
|
||||||
<a-button title="添加标签"
|
<a-button v-if="hasTags"
|
||||||
|
title="添加标签"
|
||||||
:disabled="formModel.allEffect === 1"
|
:disabled="formModel.allEffect === 1"
|
||||||
@click="addTag">
|
@click="addTag">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@@ -34,20 +35,26 @@
|
|||||||
<a-form-item v-if="formModel.allEffect === 0"
|
<a-form-item v-if="formModel.allEffect === 0"
|
||||||
:field="'tag-' + (index + 1)"
|
:field="'tag-' + (index + 1)"
|
||||||
:label="'指标标签-' + (index + 1)">
|
:label="'指标标签-' + (index + 1)">
|
||||||
<a-space :size="12">
|
<a-space :size="12" class="tag-wrapper">
|
||||||
<!-- 标签名称 -->
|
<!-- 标签名称 -->
|
||||||
<a-input v-model="tag.key"
|
<a-input v-model="tag.key"
|
||||||
style="width: 128px;"
|
style="width: 108px;"
|
||||||
placeholder="指标标签名称" />
|
placeholder="标签名称" />
|
||||||
<!-- 标签值 -->
|
<!-- 标签值 -->
|
||||||
<a-select v-model="tag.value"
|
<a-select v-model="tag.value"
|
||||||
class="tag-values"
|
class="tag-values"
|
||||||
style="width: 260px"
|
style="width: 260px"
|
||||||
:max-tag-count="2"
|
:max-tag-count="2"
|
||||||
placeholder="标签值"
|
:options="measurementTags[measurement] || []"
|
||||||
tag-nowrap
|
placeholder="输入或选择标签值"
|
||||||
multiple
|
multiple
|
||||||
allow-create />
|
allow-create>
|
||||||
|
<template #empty>
|
||||||
|
<a-empty>
|
||||||
|
请输入标签值
|
||||||
|
</a-empty>
|
||||||
|
</template>
|
||||||
|
</a-select>
|
||||||
<!-- 移除 -->
|
<!-- 移除 -->
|
||||||
<a-button title="移除"
|
<a-button title="移除"
|
||||||
style="width: 32px"
|
style="width: 32px"
|
||||||
@@ -72,7 +79,7 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<!-- 全部生效 -->
|
<!-- 全部生效 -->
|
||||||
<a-col :span="12">
|
<a-col v-if="hasTags" :span="12">
|
||||||
<a-form-item field="allEffect"
|
<a-form-item field="allEffect"
|
||||||
label="全部生效"
|
label="全部生效"
|
||||||
tooltip="开启后则忽略标签, 并生效与已配置标签的规则 (通常用于默认策略)"
|
tooltip="开启后则忽略标签, 并生效与已配置标签的规则 (通常用于默认策略)"
|
||||||
@@ -190,16 +197,17 @@
|
|||||||
import type { MetricsQueryResponse } from '@/api/monitor/metrics';
|
import type { MetricsQueryResponse } from '@/api/monitor/metrics';
|
||||||
import type { RuleTag } from '../types/const';
|
import type { RuleTag } from '../types/const';
|
||||||
import type { FormHandle } from '@/types/form';
|
import type { FormHandle } from '@/types/form';
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, watch } from 'vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import formRules from '../types/form.rules';
|
import formRules from '../types/form.rules';
|
||||||
import { MetricsUnitKey } from '../types/const';
|
import { MetricsUnitKey, MeasurementKey } from '../types/const';
|
||||||
import { assignOmitRecord } from '@/utils';
|
import { assignOmitRecord } from '@/utils';
|
||||||
import { TriggerConditionKey, LevelKey, DefaultCondition, DefaultLevel, } from '../types/const';
|
import { TriggerConditionKey, LevelKey, DefaultCondition, DefaultLevel, } from '../types/const';
|
||||||
import { createAlarmRule, updateAlarmRule } from '@/api/monitor/alarm-rule';
|
import { createAlarmRule, updateAlarmRule } from '@/api/monitor/alarm-rule';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { useDictStore, useCacheStore } from '@/store';
|
import { useDictStore, useCacheStore } from '@/store';
|
||||||
|
import { getMonitorHostTags } from '@/api/monitor/monitor-host';
|
||||||
import MonitorMetricsSelector from '@/components/monitor/metrics/selector/index.vue';
|
import MonitorMetricsSelector from '@/components/monitor/metrics/selector/index.vue';
|
||||||
|
|
||||||
const emits = defineEmits(['added', 'updated']);
|
const emits = defineEmits(['added', 'updated']);
|
||||||
@@ -214,6 +222,9 @@
|
|||||||
const formRef = ref<any>();
|
const formRef = ref<any>();
|
||||||
const formModel = ref<AlarmRuleUpdateRequest>({});
|
const formModel = ref<AlarmRuleUpdateRequest>({});
|
||||||
const tags = ref<Array<RuleTag>>([]);
|
const tags = ref<Array<RuleTag>>([]);
|
||||||
|
const hasTags = ref(false);
|
||||||
|
const measurement = ref('');
|
||||||
|
const measurementTags = ref<Record<string, string[]>>({});
|
||||||
|
|
||||||
const defaultForm = (): AlarmRuleUpdateRequest => {
|
const defaultForm = (): AlarmRuleUpdateRequest => {
|
||||||
return {
|
return {
|
||||||
@@ -223,7 +234,7 @@
|
|||||||
tags: undefined,
|
tags: undefined,
|
||||||
level: DefaultLevel,
|
level: DefaultLevel,
|
||||||
ruleSwitch: 1,
|
ruleSwitch: 1,
|
||||||
allEffect: 0,
|
allEffect: 1,
|
||||||
triggerCondition: DefaultCondition,
|
triggerCondition: DefaultCondition,
|
||||||
threshold: undefined,
|
threshold: undefined,
|
||||||
consecutiveCount: 1,
|
consecutiveCount: 1,
|
||||||
@@ -232,18 +243,28 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 指标单位
|
// 检查是否有 tags
|
||||||
const metricsUnit = computed(() => {
|
watch(() => formModel.value.metricsId, (metricsId) => {
|
||||||
const metricsId = formModel.value.metricsId;
|
|
||||||
if (!metricsId) {
|
if (!metricsId) {
|
||||||
return '';
|
hasTags.value = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// 读取指标单位
|
// 获取数据集
|
||||||
const unit = (monitorMetrics as Array<MetricsQueryResponse>).find(m => m.id === metricsId)?.unit;
|
const measurementValue = (monitorMetrics as Array<MetricsQueryResponse> || []).find(m => m.id === metricsId)?.measurement;
|
||||||
if (!unit) {
|
if (!measurementValue) {
|
||||||
return '';
|
hasTags.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
measurement.value = measurementValue;
|
||||||
|
// 获取标签
|
||||||
|
const value = getDictValue(MeasurementKey, measurementValue, 'hasTags');
|
||||||
|
if (value === true) {
|
||||||
|
hasTags.value = true;
|
||||||
|
// 加载全部标签
|
||||||
|
loadTags();
|
||||||
|
} else {
|
||||||
|
hasTags.value = false;
|
||||||
}
|
}
|
||||||
return getDictValue(MetricsUnitKey, unit, 'alarmUnit');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开新增
|
// 打开新增
|
||||||
@@ -284,7 +305,8 @@
|
|||||||
|
|
||||||
// 添加标签
|
// 添加标签
|
||||||
const addTag = () => {
|
const addTag = () => {
|
||||||
tags.value.push({ key: '', value: [] });
|
const hasNameTag = tags.value.some(s => s.key === 'name');
|
||||||
|
tags.value.push({ key: hasNameTag ? '' : 'name', value: [] });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 移除标签
|
// 移除标签
|
||||||
@@ -292,8 +314,37 @@
|
|||||||
tags.value.splice(index, 1);
|
tags.value.splice(index, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 指标单位
|
||||||
|
const metricsUnit = computed(() => {
|
||||||
|
const metricsId = formModel.value.metricsId;
|
||||||
|
if (!metricsId) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// 读取指标单位
|
||||||
|
const unit = (monitorMetrics as Array<MetricsQueryResponse> || []).find(m => m.id === metricsId)?.unit;
|
||||||
|
if (!unit) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return getDictValue(MetricsUnitKey, unit, 'alarmUnit');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载全部标签
|
||||||
|
const loadTags = () => {
|
||||||
|
const tags = measurementTags.value[measurement.value];
|
||||||
|
if (tags) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 加载标签
|
||||||
|
getMonitorHostTags({
|
||||||
|
measurement: measurement.value,
|
||||||
|
policyId: formModel.value.policyId,
|
||||||
|
}).then(({ data }) => {
|
||||||
|
measurementTags.value[measurement.value as any] = data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 确定
|
// 确定
|
||||||
const handlerOk = async () => {
|
const handleOk = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
// 验证参数
|
// 验证参数
|
||||||
@@ -301,6 +352,20 @@
|
|||||||
if (error) {
|
if (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!hasTags.value) {
|
||||||
|
// 无 tag
|
||||||
|
formModel.value.allEffect = 1;
|
||||||
|
} else {
|
||||||
|
// 有 tag
|
||||||
|
if (formModel.value.allEffect === 1) {
|
||||||
|
// 全部生效
|
||||||
|
tags.value = [];
|
||||||
|
} else {
|
||||||
|
// 检查 tag
|
||||||
|
if (!tags.value.length) {
|
||||||
|
Message.error('请选择全部生效或添加对应的标签');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (let tag of tags.value) {
|
for (let tag of tags.value) {
|
||||||
if (!tag.key) {
|
if (!tag.key) {
|
||||||
Message.error('请输入标签名称');
|
Message.error('请输入标签名称');
|
||||||
@@ -311,11 +376,13 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (formHandle.value == 'add') {
|
if (formHandle.value == 'add') {
|
||||||
// 新增
|
// 新增
|
||||||
await createAlarmRule({
|
await createAlarmRule({
|
||||||
...formModel.value,
|
...formModel.value,
|
||||||
tags: formModel.value.allEffect === 1 ? '[]' : JSON.stringify(tags.value)
|
tags: JSON.stringify(tags.value)
|
||||||
});
|
});
|
||||||
Message.success('创建成功');
|
Message.success('创建成功');
|
||||||
emits('added');
|
emits('added');
|
||||||
@@ -323,13 +390,13 @@
|
|||||||
// 修改
|
// 修改
|
||||||
await updateAlarmRule({
|
await updateAlarmRule({
|
||||||
...formModel.value,
|
...formModel.value,
|
||||||
tags: formModel.value.allEffect === 1 ? '[]' : JSON.stringify(tags.value)
|
tags: JSON.stringify(tags.value)
|
||||||
});
|
});
|
||||||
Message.success('修改成功');
|
Message.success('修改成功');
|
||||||
emits('updated');
|
emits('updated');
|
||||||
}
|
}
|
||||||
// 清空
|
handleClose();
|
||||||
handlerClear();
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -339,22 +406,32 @@
|
|||||||
|
|
||||||
// 关闭
|
// 关闭
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
handlerClear();
|
handleClear();
|
||||||
|
setVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handleClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
:deep(.metrics-selector) {
|
:deep(.metrics-selector-no-tag) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.metrics-selector-has-tag) {
|
||||||
width: calc(100% - 42px);
|
width: calc(100% - 42px);
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.alarm-level-select, .condition-select {
|
.alarm-level-select, .condition-select {
|
||||||
|
|
||||||
:deep(.arco-select-view-suffix) {
|
:deep(.arco-select-view-suffix) {
|
||||||
@@ -365,4 +442,5 @@
|
|||||||
:deep(.tag-values .arco-select-view-inner) {
|
:deep(.tag-values .arco-select-view-inner) {
|
||||||
flex-wrap: nowrap !important;
|
flex-wrap: nowrap !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -203,7 +203,7 @@
|
|||||||
|
|
||||||
// 获取指标名称
|
// 获取指标名称
|
||||||
const getMetricsField = (metricsId: number, field: string) => {
|
const getMetricsField = (metricsId: number, field: string) => {
|
||||||
return (monitorMetrics as Array<MetricsQueryResponse>).find(m => m.id === metricsId)?.[field];
|
return (monitorMetrics as Array<MetricsQueryResponse> || []).find(m => m.id === metricsId)?.[field];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换规则开关
|
// 切换规则开关
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 数据集 -->
|
<!-- 数据集 -->
|
||||||
<a-form-item field="metricsId" label="数据集">
|
<a-form-item field="metricsMeasurement" label="数据集">
|
||||||
<a-select v-model="formModel.metricsMeasurement"
|
<a-select v-model="formModel.metricsMeasurement"
|
||||||
:options="toOptions(MetricsMeasurementKey)"
|
:options="toOptions(MetricsMeasurementKey)"
|
||||||
placeholder="数据集"
|
placeholder="数据集"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
:hide-content="true">
|
:hide-content="true">
|
||||||
<a-tab-pane :key="TabKeys.OVERVIEW" title="主机概览" />
|
<a-tab-pane :key="TabKeys.OVERVIEW" title="主机概览" />
|
||||||
<a-tab-pane :key="TabKeys.CHART" title="监控图表" />
|
<a-tab-pane :key="TabKeys.CHART" title="监控图表" />
|
||||||
<a-tab-pane :key="TabKeys.ALARM" title="告警记录" />
|
<a-tab-pane :key="TabKeys.ALARM" title="告警事件" />
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
<a-divider direction="vertical"
|
<a-divider direction="vertical"
|
||||||
style="height: 22px; margin: 0 16px 0 8px;"
|
style="height: 22px; margin: 0 16px 0 8px;"
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 右侧 -->
|
<!-- 右侧 -->
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<!-- 告警记录标签 -->
|
<!-- 告警事件标签 -->
|
||||||
<div v-if="activeKey === TabKeys.OVERVIEW" class="handle-wrapper">
|
<div v-if="activeKey === TabKeys.OVERVIEW" class="handle-wrapper">
|
||||||
<a-tag v-if="overrideTimestamp">更新时间: {{ dateFormat(new Date(overrideTimestamp)) }}</a-tag>
|
<a-tag v-if="overrideTimestamp">更新时间: {{ dateFormat(new Date(overrideTimestamp)) }}</a-tag>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user