🔨 优化标签查询逻辑.

This commit is contained in:
lijiahangmax
2025-10-07 14:26:40 +08:00
parent 25082b9ea1
commit 2103698417
17 changed files with 296 additions and 223 deletions

View File

@@ -93,11 +93,11 @@ public class AlarmPolicyRuleController {
@GetMapping("/list")
@Operation(summary = "查询全部监控告警规则")
@Parameter(name = "policyId", description = "policyId", required = true)
@Parameter(name = "metricsMeasurement", description = "metricsMeasurement")
@Parameter(name = "measurement", description = "measurement")
@PreAuthorize("@ss.hasPermission('monitor:alarm-policy:query')")
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(@RequestParam("policyId") Long policyId,
@RequestParam(value = "metricsMeasurement", required = false) String metricsMeasurement) {
return alarmPolicyRuleService.getAlarmPolicyRuleList(policyId, metricsMeasurement);
@RequestParam(value = "measurement", required = false) String measurement) {
return alarmPolicyRuleService.getAlarmPolicyRuleList(policyId, measurement);
}
@DemoDisableApi

View File

@@ -106,6 +106,17 @@ public class MonitorHostController {
return monitorHostService.getMonitorHostChart(request);
}
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/host-tags")
@Operation(summary = "查询监控告警标签")
@Parameter(name = "policyId", description = "policyId", required = true)
@Parameter(name = "measurement", description = "measurement")
@PreAuthorize("@ss.hasPermission('monitor:monitor-host:query')")
public List<String> getMonitorHostPolicyRuleTags(@RequestParam("policyId") Long policyId,
@RequestParam(value = "measurement", required = false) String measurement) {
return monitorHostService.getMonitorHostPolicyRuleTags(policyId, measurement);
}
@DemoDisableApi
@OperatorLog(MonitorHostOperatorType.UPDATE)
@PutMapping("/update")

View File

@@ -95,6 +95,20 @@ public interface MonitorHostDAO extends IMapper<MonitorHostDO> {
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
*

View File

@@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit;
*/
public interface AlarmPolicyCacheKeyDefine {
CacheKeyDefine MONITOR_ALARM_POLICY = new CacheKeyBuilder()
CacheKeyDefine ALARM_POLICY = new CacheKeyBuilder()
.key("alarm:policy:list")
.desc("告警策略")
.type(AlarmPolicyCacheDTO.class)
@@ -49,6 +49,7 @@ public interface AlarmPolicyCacheKeyDefine {
CacheKeyDefine ALARM_RULE_SILENCE = new CacheKeyBuilder()
.key("alarm:silence:{}:{}")
.desc("告警规则沉默标志 ${agentKey} ${ruleId}")
.type(Long.class)
.struct(RedisCacheStruct.STRING)
.build();

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2023 - present Dromara, All rights reserved.
*
* https://visor.dromara.org
* https://visor.dromara.org.cn
* https://visor.orionsec.cn
*
* Members:
* Jiahang Li - ljh1553488six@139.com - author
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.visor.module.monitor.define.cache;
import cn.orionsec.kit.lang.define.cache.key.CacheKeyBuilder;
import cn.orionsec.kit.lang.define.cache.key.CacheKeyDefine;
import cn.orionsec.kit.lang.define.cache.key.struct.RedisCacheStruct;
import java.util.concurrent.TimeUnit;
/**
* 监控主机缓存 key
*
* @author Jiahang Li
* @version 1.0.0
* @since 2025-9-14 00:12
*/
public interface MonitorHostCacheKeyDefine {
CacheKeyDefine MONITOR_HOST_POLICY_HOST_TAGS = new CacheKeyBuilder()
.key("monitor:host:policy:host-tags:{}")
.desc("告警规则沉默标志 ${policyId}")
.type(String.class)
.struct(RedisCacheStruct.HASH)
.timeout(8, TimeUnit.HOURS)
.build();
}

View File

@@ -43,7 +43,7 @@ public enum MeasurementEnum {
/**
* cpu
*/
CPU("cpu", (s) -> {
CPU("cpu", true, (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);
@@ -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_PERCENT, double.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.LOAD5, 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_PERCENT, double.class);
s.accept(MetricsConst.DISK_FS_INODES_USED_PERCENT, double.class);
@@ -83,7 +83,7 @@ public enum MeasurementEnum {
/**
* io
*/
IO("io", s -> {
IO("io", false, 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);
@@ -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_RECV_BYTES_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_UDP_CONNECTIONS, int.class);
s.accept(MetricsConst.NET_INET_CONNECTIONS, int.class);
@@ -121,10 +121,14 @@ public enum MeasurementEnum {
;
private final String measurement;
private final boolean hasTags;
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.hasTags = hasTags;
this.fields = new HashedMap<>();
register.accept(this.fields::put);
}

View File

@@ -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);
}
}

View File

@@ -73,11 +73,11 @@ public interface AlarmPolicyRuleService {
/**
* 查询全部监控告警规则
*
* @param policyId policyId
* @param metricsMeasurement metricsMeasurement
* @param policyId policyId
* @param measurement measurement
* @return rows
*/
List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String metricsMeasurement);
List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String measurement);
/**
* 通过 metricsId 删除监控告警规则

View File

@@ -66,6 +66,15 @@ public interface MonitorHostService {
*/
List<TimeChartSeries> getMonitorHostChart(MonitorHostChartRequest request);
/**
* 查询监控告警规则主机标签
*
* @param policyId policyId
* @param measurement measurement
* @return tags
*/
List<String> getMonitorHostPolicyRuleTags(Long policyId, String measurement);
/**
* 更新监控主机
*

View File

@@ -160,13 +160,13 @@ public class AlarmPolicyRuleServiceImpl implements AlarmPolicyRuleService {
}
@Override
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String metricsMeasurement) {
public List<AlarmPolicyRuleVO> getAlarmPolicyRuleList(Long policyId, String measurement) {
// 查询
return alarmPolicyRuleDAO.of()
.createWrapper()
.eq(AlarmPolicyRuleDO::getPolicyId, policyId)
.eq(Strings.isNotBlank(metricsMeasurement), AlarmPolicyRuleDO::getMetricsMeasurement, metricsMeasurement)
// 同的指标在一起
.eq(Strings.isNotBlank(measurement), AlarmPolicyRuleDO::getMetricsMeasurement, measurement)
// 同的指标在一起
.orderByAsc(AlarmPolicyRuleDO::getMetricsId)
// 通过 p0 > p1 排序
.orderByAsc(AlarmPolicyRuleDO::getLevel)

View File

@@ -173,14 +173,14 @@ public class AlarmPolicyServiceImpl implements AlarmPolicyService {
@Override
public List<AlarmPolicyVO> getAlarmPolicyListByCache() {
// 查询缓存
List<AlarmPolicyCacheDTO> list = RedisMaps.valuesJson(AlarmPolicyCacheKeyDefine.MONITOR_ALARM_POLICY);
List<AlarmPolicyCacheDTO> list = RedisMaps.valuesJson(AlarmPolicyCacheKeyDefine.ALARM_POLICY);
if (list.isEmpty()) {
// 查询数据库
list = alarmPolicyDAO.of().list(AlarmPolicyConvert.MAPPER::toCache);
// 设置屏障 防止穿透
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);

View File

@@ -35,10 +35,12 @@ import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.utils.Assert;
import org.dromara.visor.common.utils.LockerUtils;
import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils;
import org.dromara.visor.framework.redis.core.utils.RedisMaps;
import org.dromara.visor.module.asset.api.HostApi;
import org.dromara.visor.module.asset.entity.dto.host.HostDTO;
import org.dromara.visor.module.infra.api.SystemUserApi;
import org.dromara.visor.module.monitor.dao.MonitorHostDAO;
import org.dromara.visor.module.monitor.define.cache.MonitorHostCacheKeyDefine;
import org.dromara.visor.module.monitor.engine.AlarmEngine;
import org.dromara.visor.module.monitor.engine.MonitorContext;
import org.dromara.visor.module.monitor.entity.domain.MonitorHostDO;
@@ -146,8 +148,13 @@ public class MonitorAgentEndpointServiceImpl implements MonitorAgentEndpointServ
update.setMonitorConfig(JSON.toJSONString(newConfig));
}
monitorHostDAO.updateById(update);
// 删除元数据缓存
Long policyId = monitorHost.getPolicyId();
if (policyId != null) {
RedisMaps.delete(MonitorHostCacheKeyDefine.MONITOR_HOST_POLICY_HOST_TAGS.format(policyId));
}
}
// 设置配置缓存
// 重新加载监控主机上下文
if (newConfig != null) {
monitorContext.reloadMonitorHost(agentKey);
}

View File

@@ -40,6 +40,7 @@ import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.framework.influxdb.core.query.FluxQueryBuilder;
import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils;
import org.dromara.visor.framework.mybatis.core.query.Conditions;
import org.dromara.visor.framework.redis.core.utils.RedisMaps;
import org.dromara.visor.module.asset.api.HostAgentApi;
import org.dromara.visor.module.asset.api.HostApi;
import org.dromara.visor.module.asset.entity.dto.host.HostAgentLogDTO;
@@ -51,6 +52,7 @@ import org.dromara.visor.module.monitor.constant.MetricsConst;
import org.dromara.visor.module.monitor.convert.MonitorHostConvert;
import org.dromara.visor.module.monitor.dao.AlarmPolicyDAO;
import org.dromara.visor.module.monitor.dao.MonitorHostDAO;
import org.dromara.visor.module.monitor.define.cache.MonitorHostCacheKeyDefine;
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.MonitorHostDO;
@@ -74,6 +76,7 @@ import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 监控主机 服务实现类
@@ -235,6 +238,48 @@ public class MonitorHostServiceImpl implements MonitorHostService {
return seriesList;
}
@Override
public List<String> getMonitorHostPolicyRuleTags(Long policyId, String measurement) {
MeasurementEnum measurementEnum = MeasurementEnum.of(measurement);
if (measurementEnum == null) {
return Collections.emptyList();
}
// 查询缓存
String cacheKey = MonitorHostCacheKeyDefine.MONITOR_HOST_POLICY_HOST_TAGS.format(policyId);
String value = RedisMaps.get(cacheKey, measurement);
if (!Strings.isBlank(value)) {
return JSON.parseArray(value, String.class);
}
// 查询规则下的全部主机
List<MonitorHostMetaDTO> metas = monitorHostDAO.selectByPolicyId(policyId)
.stream()
.map(MonitorHostDO::getMonitorMeta)
.filter(Objects::nonNull)
.map(s -> JSON.parseObject(s, MonitorHostMetaDTO.class))
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 映射数据
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<String> tags = metas.stream()
.map(tagsGetter)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
// 设置缓存
RedisMaps.putJson(cacheKey, MonitorHostCacheKeyDefine.MONITOR_HOST_POLICY_HOST_TAGS, measurement, tags);
return tags;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Integer updateMonitorHostById(MonitorHostUpdateRequest request) {
@@ -272,7 +317,15 @@ public class MonitorHostServiceImpl implements MonitorHostService {
if (policyId == null) {
monitorHostDAO.setPolicyIdWithNullById(id);
}
// 更新缓存
// 删除元数据缓存
List<String> tagsCacheKeyList = Stream.of(policyId, monitorHost.getPolicyId())
.filter(Objects::nonNull)
.map(MonitorHostCacheKeyDefine.MONITOR_HOST_POLICY_HOST_TAGS::format)
.collect(Collectors.toList());
if (!tagsCacheKeyList.isEmpty()) {
RedisMaps.delete(tagsCacheKeyList);
}
// 重新加载监控主机上下文
monitorContext.reloadMonitorHost(host.getAgentKey());
log.info("MonitorHostService-updateMonitorHostById effect: {}", effect);
return effect;