告警设置、告警上报
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
package com.tongran.agent.client.core.config;
|
||||
|
||||
import com.tongran.agent.client.core.eo.AlarmEO;
|
||||
import com.tongran.agent.client.core.eo.NativeNetworkInterfaceEO;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -22,7 +26,7 @@ public class GlobalConfig {
|
||||
public static String CLIENT_ID;
|
||||
|
||||
/**
|
||||
* 交换机
|
||||
* 交换机信息
|
||||
*/
|
||||
public static String SWITCH_COMMUNITY; //团名
|
||||
public static String SWITCH_IP; //交换机IP
|
||||
@@ -40,7 +44,7 @@ public class GlobalConfig {
|
||||
public static boolean isCollect = false;
|
||||
public static Map<String, Long> taskIds = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* 系统监控
|
||||
* 采集系统监控
|
||||
*/
|
||||
public static boolean cpuCollect = false; //cpu采集
|
||||
public static long cpuInterval = 300; //cpu采集间隔
|
||||
@@ -53,7 +57,7 @@ public class GlobalConfig {
|
||||
public static boolean dockerCollect = false; //docker采集
|
||||
public static long dockerInterval = 300; //docker采集间隔
|
||||
/**
|
||||
* 系统其他监控
|
||||
* 采集系统其他监控
|
||||
*/
|
||||
public static boolean systemSwapSizeFreeCollect = false; //交换卷/文件的可用空间(字节)采集
|
||||
public static long systemSwapSizeFreeInterval = 300; //交换卷/文件的可用空间(字节)采集间隔
|
||||
@@ -90,7 +94,7 @@ public class GlobalConfig {
|
||||
public static boolean procNumCollect = false; //进程数采集
|
||||
public static long procNumInterval = 300; //进程数采集间隔
|
||||
/**
|
||||
* 交换机监控
|
||||
* 采集交换机监控
|
||||
*/
|
||||
public static boolean switchNetCollect = false; //交换机网络采集
|
||||
public static long switchNetInterval = 300; //交换机网络采集间隔
|
||||
@@ -103,7 +107,7 @@ public class GlobalConfig {
|
||||
public static boolean switchFanCollect = false; //风扇采集
|
||||
public static long switchFanInterval = 300; //风扇采集间隔
|
||||
/**
|
||||
* 交换机其他监控
|
||||
* 采集交换机其他监控
|
||||
*/
|
||||
public static boolean switchSysDescrCollect = false; //系统描述采集
|
||||
public static long switchSysDescrInterval = 300; //系统描述采集间隔
|
||||
@@ -135,6 +139,28 @@ public class GlobalConfig {
|
||||
public static long switchHwCurrentPowerInterval = 300; //系统实时功率(mW)采集间隔
|
||||
|
||||
|
||||
/**
|
||||
* 告警
|
||||
*/
|
||||
public static boolean IS_ALARM = false;
|
||||
public static long ALARM_INTERVAL = 120;
|
||||
public static List<AlarmEO> ALARM_LIST; //告警设置信息
|
||||
/**
|
||||
* 告警监控
|
||||
*/
|
||||
public static boolean systemCpuUti = false; //CPU使用率
|
||||
public static boolean memoryUtilization = false; //内存利用率
|
||||
public static boolean systemSwapSizePercent = false; //可用交换空间百分比
|
||||
public static boolean systemUsersNum = false; //登录用户数
|
||||
public static boolean vfsFsUtil = false; //挂载点的空间利用率
|
||||
public static boolean netIfStatus = false; //网络运行状态UP变down
|
||||
public static boolean netUtil = false; //网络带宽使用率
|
||||
public static boolean containerMemUtil = false; //容器内存使用率
|
||||
public static boolean extraPorts = false; //多余端口
|
||||
|
||||
/**
|
||||
* 所有网络接口
|
||||
*/
|
||||
public static List<NativeNetworkInterfaceEO> NET_LIST;
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ public enum MsgEnum {
|
||||
|
||||
系统其他上报("OTHER_SYSTEM"),
|
||||
|
||||
告警上报("ALARM"),
|
||||
|
||||
开启系统采集("SYSTEM_COLLECT_START"),
|
||||
|
||||
开启系统采集应答("SYSTEM_COLLECT_START_RSP"),
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.tongran.agent.client.core.eo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AlarmEO {
|
||||
|
||||
//告警内容类型
|
||||
private String type;
|
||||
|
||||
//是否开启标识:默认false
|
||||
private boolean collect;
|
||||
|
||||
//告警阈值
|
||||
private String threshold;
|
||||
|
||||
//比较类型:0、大于;1、大于且等于;2、小于;3、小于且等于;
|
||||
private int compareType;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.tongran.agent.client.core.eo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NativeNetworkInterfaceEO {
|
||||
private String name;
|
||||
private String displayName;
|
||||
private boolean up;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.tongran.agent.client.core.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "告警信息")
|
||||
public class AlarmVO {
|
||||
@Schema(description = "告警内容类型")
|
||||
private String type;
|
||||
|
||||
private String result;
|
||||
|
||||
@Schema(description = "时间戳")
|
||||
private long timestamp;
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.alibaba.fastjson2.TypeReference;
|
||||
import com.tongran.agent.client.core.config.GlobalConfig;
|
||||
import com.tongran.agent.client.core.enums.MsgEnum;
|
||||
import com.tongran.agent.client.core.eo.AgentVersionUpdateEO;
|
||||
import com.tongran.agent.client.core.eo.AlarmEO;
|
||||
import com.tongran.agent.client.core.eo.ScriptPolicyEO;
|
||||
import com.tongran.agent.client.netty.annotation.AgentDispatcher;
|
||||
import com.tongran.agent.client.netty.basics.AgentHandler;
|
||||
@@ -19,6 +20,7 @@ import com.tongran.agent.client.scheduler.service.Java8FileDownloader;
|
||||
import com.tongran.agent.client.scheduler.task.SpecificTimeRequest;
|
||||
import com.tongran.agent.client.scheduler.task.SpecificTimeTaskService;
|
||||
import com.tongran.agent.client.service.AgentService;
|
||||
import com.tongran.agent.client.utils.AgentDataUtil;
|
||||
import com.tongran.agent.client.utils.AgentUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -201,63 +203,24 @@ public class AgentEndpoint {
|
||||
public class AlarmSetHandler implements AgentHandler {
|
||||
@Override
|
||||
public UpMsgResponse upHandle(String data, String clientId) {
|
||||
// //更改全局变量
|
||||
// JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
// if(jsonObject.containsKey("switchBoard")){
|
||||
// String switchBoard = jsonObject.getString("switchBoard");
|
||||
// jsonObject = JSONObject.parseObject(switchBoard);
|
||||
// if(jsonObject.containsKey("community")){
|
||||
// GlobalConfig.SWITCH_COMMUNITY = jsonObject.getString("community");
|
||||
// }
|
||||
// if(jsonObject.containsKey("ip")){
|
||||
// GlobalConfig.SWITCH_IP = jsonObject.getString("ip");
|
||||
// }
|
||||
// if(jsonObject.containsKey("port")){
|
||||
// GlobalConfig.SWITCH_PORT = jsonObject.getInteger("port");
|
||||
// }
|
||||
// if(jsonObject.containsKey("netOID")){
|
||||
// String netOID = jsonObject.getString("netOID");
|
||||
// LinkedHashMap<String, String> map = JSON.parseObject(netOID, new TypeReference<LinkedHashMap<String, String>>() {});
|
||||
// GlobalConfig.SWITCH_NET_OID = map;
|
||||
// }
|
||||
// if(jsonObject.containsKey("moduleOID")){
|
||||
// String moduleOID = jsonObject.getString("moduleOID");
|
||||
// LinkedHashMap<String, String> map = JSON.parseObject(moduleOID, new TypeReference<LinkedHashMap<String, String>>() {});
|
||||
// GlobalConfig.SWITCH_MODULE_OID = map;
|
||||
// }
|
||||
// if(jsonObject.containsKey("mpuOID")){
|
||||
// String mpuOID = jsonObject.getString("mpuOID");
|
||||
// LinkedHashMap<String, String> map = JSON.parseObject(mpuOID, new TypeReference<LinkedHashMap<String, String>>() {});
|
||||
// GlobalConfig.SWITCH_MPU_OID = map;
|
||||
// }
|
||||
// if(jsonObject.containsKey("pwrOID")){
|
||||
// String pwrOID = jsonObject.getString("pwrOID");
|
||||
// LinkedHashMap<String, String> map = JSON.parseObject(pwrOID, new TypeReference<LinkedHashMap<String, String>>() {});
|
||||
// GlobalConfig.SWITCH_PWR_OID = map;
|
||||
// }
|
||||
// if(jsonObject.containsKey("fanOID")){
|
||||
// String fanOID = jsonObject.getString("fanOID");
|
||||
// LinkedHashMap<String, String> map = JSON.parseObject(fanOID, new TypeReference<LinkedHashMap<String, String>>() {});
|
||||
// GlobalConfig.SWITCH_FAN_OID = map;
|
||||
// }
|
||||
// if(jsonObject.containsKey("otherOID")){
|
||||
// String otherOID = jsonObject.getString("otherOID");
|
||||
// LinkedHashMap<String, String> map = JSON.parseObject(otherOID, new TypeReference<LinkedHashMap<String, String>>() {});
|
||||
// GlobalConfig.SWITCH_OTHER_OID = map;
|
||||
// }
|
||||
// }
|
||||
// GlobalConfig.isCollect = true;
|
||||
// GlobalConfig.CLIENT_ID = clientId;
|
||||
// //调用采集任务
|
||||
// try {
|
||||
// appInitializer.run();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// JSONObject json = new JSONObject();
|
||||
// json.put("resCode",1);
|
||||
//更改全局变量
|
||||
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
if(jsonObject.containsKey("alarms")){
|
||||
String alarms = jsonObject.getString("alarms");
|
||||
GlobalConfig.ALARM_LIST = JSON.parseObject(alarms, new TypeReference<List<AlarmEO>>() {});
|
||||
if(CollectionUtil.isNotEmpty(GlobalConfig.ALARM_LIST)){
|
||||
GlobalConfig.IS_ALARM = AgentDataUtil.hasAnyActiveAlarm(GlobalConfig.ALARM_LIST);
|
||||
}
|
||||
}
|
||||
agentService.alarmMonitor();
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.round(timestamp / 1000.0);
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("resCode",1);
|
||||
json.put("resMag","");
|
||||
json.put("timestamp",timestamp);
|
||||
return UpMsgResponse.builder().clientId(clientId).dataType(MsgEnum.告警设置应答.getValue())
|
||||
.content("").build();
|
||||
.content(json.toString()).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.tongran.agent.client.scheduler.service;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
@@ -12,6 +13,7 @@ import com.tongran.agent.client.netty.model.Message;
|
||||
import com.tongran.agent.client.service.*;
|
||||
import com.tongran.agent.client.utils.AgentUtil;
|
||||
import com.tongran.agent.client.utils.AssertLog;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -34,6 +36,7 @@ public class BusinessTasks {
|
||||
private final AtomicInteger task7Counter = new AtomicInteger(0);
|
||||
private final AtomicInteger task8Counter = new AtomicInteger(0);
|
||||
private final AtomicInteger task9Counter = new AtomicInteger(0);
|
||||
private final AtomicInteger task10Counter = new AtomicInteger(0);
|
||||
|
||||
protected final SessionManager sessionManager;
|
||||
|
||||
@@ -69,6 +72,9 @@ public class BusinessTasks {
|
||||
@Resource
|
||||
private SystemService systemService;
|
||||
|
||||
@Resource
|
||||
private AlarmService alarmService;
|
||||
|
||||
@Resource
|
||||
private ApplicationProperties properties;
|
||||
|
||||
@@ -130,8 +136,11 @@ public class BusinessTasks {
|
||||
// 判定客户端与服务端是否连接
|
||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||
// 发送磁盘信息包
|
||||
String data = "";
|
||||
List<DiskVO> list = diskService.diskList(timestamp);
|
||||
String data = JSONArray.toJSONString(list);
|
||||
if(CollectionUtil.isNotEmpty(list)){
|
||||
data = JSONArray.toJSONString(list);
|
||||
}
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.磁盘上报.getValue()).data(data).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
}
|
||||
@@ -150,8 +159,11 @@ public class BusinessTasks {
|
||||
// 判定客户端与服务端是否连接
|
||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||
// 发送容器包
|
||||
String data = "";
|
||||
List<DockerVO> list = dockerService.dockerList(timestamp);
|
||||
String data = JSONArray.toJSONString(list);
|
||||
if(CollectionUtil.isNotEmpty(list)){
|
||||
data = JSONArray.toJSONString(list);
|
||||
}
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.容器上报.getValue()).data(data).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
}
|
||||
@@ -190,8 +202,11 @@ public class BusinessTasks {
|
||||
// 判定客户端与服务端是否连接
|
||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||
// 发送网卡信息包
|
||||
String data = "";
|
||||
List<NetVO> list = netService.netList(timestamp);
|
||||
String data = JSONArray.toJSONString(list);
|
||||
if(CollectionUtil.isNotEmpty(list)){
|
||||
data = JSONArray.toJSONString(list);
|
||||
}
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.网络上报.getValue()).data(data).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
}
|
||||
@@ -210,8 +225,11 @@ public class BusinessTasks {
|
||||
// 判定客户端与服务端是否连接
|
||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||
// 发送挂载点信息包
|
||||
String data = "";
|
||||
List<PointVO> list = diskService.pointList(timestamp);
|
||||
String data = JSONArray.toJSONString(list);
|
||||
if(CollectionUtil.isNotEmpty(list)){
|
||||
data = JSONArray.toJSONString(list);
|
||||
}
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.挂载上报.getValue()).data(data).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
}
|
||||
@@ -233,8 +251,11 @@ public class BusinessTasks {
|
||||
// List<SwitchBoardVO> list = switchBoardService.switchBoardList(timestamp);
|
||||
// String data = JSONArray.toJSONString(list);
|
||||
// Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.交换机上报.getValue()).data(data).build();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
String data = switchBoardService.getSwitchDataByType(type);
|
||||
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
if(StringUtils.isNotBlank(data)){
|
||||
jsonObject = JSONObject.parseObject(data);
|
||||
}
|
||||
jsonObject.put("timestamp", timestamp);
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.交换机上报.getValue()).data(jsonObject.toString()).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
@@ -248,6 +269,7 @@ public class BusinessTasks {
|
||||
@Async("taskExecutor")
|
||||
public void systemTask(String type) {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.round(timestamp / 1000.0);
|
||||
int count = task9Counter.incrementAndGet();
|
||||
AssertLog.info("系统信息采集定时任务执行 - 时间: {},task #{}", LocalDateTime.now(), count);
|
||||
// 判定客户端与服务端是否连接
|
||||
@@ -257,8 +279,11 @@ public class BusinessTasks {
|
||||
// systemVO.setTimestamp(timestamp);
|
||||
// String data = JSON.toJSONString(systemVO);
|
||||
// Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.系统其他上报.getValue()).data(data).build();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
String data = systemService.otherSystem(type);
|
||||
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
if(StringUtils.isNotBlank(data)){
|
||||
jsonObject = JSONObject.parseObject(data);
|
||||
}
|
||||
jsonObject.put("timestamp", timestamp);
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.系统其他上报.getValue()).data(jsonObject.toString()).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
@@ -266,4 +291,26 @@ public class BusinessTasks {
|
||||
AssertLog.info("系统信息采集定时任务执行 - task #{} completed", count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务10:告警监控任务
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
public void alarmTask() {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.round(timestamp / 1000.0);
|
||||
int count = task10Counter.incrementAndGet();
|
||||
AssertLog.info("告警监控定时任务执行 - 时间: {},task #{}", LocalDateTime.now(), count);
|
||||
// 判定客户端与服务端是否连接
|
||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||
String data = "";
|
||||
List<AlarmVO> list = alarmService.alarmMonitor(timestamp);
|
||||
if(CollectionUtil.isNotEmpty(list)){
|
||||
data = JSONArray.toJSONString(list);
|
||||
}
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.告警上报.getValue()).data(data).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
}
|
||||
AssertLog.info("告警监控定时任务执行 - task #{} completed", count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,4 +8,6 @@ public interface AgentService {
|
||||
void switchCollectStart(String data);
|
||||
|
||||
void switchCollectStop();
|
||||
|
||||
void alarmMonitor();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.tongran.agent.client.service;
|
||||
|
||||
import com.tongran.agent.client.core.vo.AlarmVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AlarmService {
|
||||
List<AlarmVO> alarmMonitor(long timestamp);
|
||||
}
|
||||
@@ -377,5 +377,19 @@ public class AgentServiceImpl implements AgentService {
|
||||
GlobalConfig.switchHwCurrentPowerInterval = 300; //系统实时功率(mW)采集间隔
|
||||
}
|
||||
|
||||
@Override
|
||||
public void alarmMonitor() {
|
||||
if(GlobalConfig.IS_ALARM){
|
||||
//开启告警监控
|
||||
long milli = AgentUtil.getMillisToNextMinute() + 60000;
|
||||
dynamicTaskService.scheduleTask("alarmTask",
|
||||
businessTasks::alarmTask, milli, GlobalConfig.ALARM_INTERVAL*1000L);
|
||||
}else{
|
||||
//关闭告警监控
|
||||
dynamicTaskService.cancelTask("alarmTask");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,456 @@
|
||||
package com.tongran.agent.client.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.model.Container;
|
||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||
import com.github.dockerjava.core.DockerClientImpl;
|
||||
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
|
||||
import com.github.dockerjava.transport.DockerHttpClient;
|
||||
import com.tongran.agent.client.core.config.GlobalConfig;
|
||||
import com.tongran.agent.client.core.eo.AlarmEO;
|
||||
import com.tongran.agent.client.core.eo.NativeNetworkInterfaceEO;
|
||||
import com.tongran.agent.client.core.vo.AlarmVO;
|
||||
import com.tongran.agent.client.service.AlarmService;
|
||||
import com.tongran.agent.client.utils.AgentDataUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
import oshi.hardware.HardwareAbstractionLayer;
|
||||
import oshi.hardware.NetworkIF;
|
||||
import oshi.software.os.OSFileStore;
|
||||
import oshi.software.os.OperatingSystem;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class AlarmServiceImpl implements AlarmService {
|
||||
@Override
|
||||
public List<AlarmVO> alarmMonitor(long timestamp) {
|
||||
List<AlarmVO> alarmVOList = new ArrayList<>();
|
||||
List<AlarmEO> list = GlobalConfig.ALARM_LIST.stream().filter(a -> a.isCollect() == true).collect(Collectors.toList());
|
||||
if(CollectionUtil.isNotEmpty(list)){
|
||||
for (AlarmEO alarmEO : list) {
|
||||
String type = alarmEO.getType();
|
||||
String threshold = alarmEO.getThreshold();
|
||||
int compareType = alarmEO.getCompareType();
|
||||
AlarmVO alarmVO = AlarmVO.builder().type(type).timestamp(timestamp).build();
|
||||
switch(type) {
|
||||
case "systemCpuUti": //CPU使用率
|
||||
alarmVO.setResult(handleSystemCpuUti(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "memoryUtilization": //内存利用率
|
||||
alarmVO.setResult(handleMemoryUtilization(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "systemSwapSizePercent": //可用交换空间百分比
|
||||
alarmVO.setResult(handleSystemSwapSizePercent(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "systemUsersNum": //登录用户数
|
||||
alarmVO.setResult(handleSystemUsersNum(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "vfsFsUtil": //挂载点的空间利用率
|
||||
alarmVO.setResult(handleVfsFsUtil(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "netUtil": //网络带宽使用率
|
||||
alarmVO.setResult(handleNetUtil(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "containerMemUtil": //容器内存使用率
|
||||
alarmVO.setResult(handleContainerMemUtil(threshold, compareType));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "netIfStatus": //网络运行状态UP变down
|
||||
alarmVO.setResult(handleNetIfStatus());
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
case "extraPorts": //多余端口
|
||||
alarmVO.setResult(handleExtraPorts(threshold));
|
||||
alarmVOList.add(alarmVO);
|
||||
break;
|
||||
default: //其他
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return alarmVOList;
|
||||
}
|
||||
|
||||
private String handleSystemCpuUti(String threshold, int compareType){
|
||||
try {
|
||||
SystemInfo si = new SystemInfo();
|
||||
HardwareAbstractionLayer hal = si.getHardware();
|
||||
CentralProcessor processor = hal.getProcessor();
|
||||
long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1); // 等待1秒
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 计算使用率
|
||||
double cpuUsage = processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100;
|
||||
boolean isFalse = false;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
isFalse = compare(cpuUsage, threshold, compareType);
|
||||
}
|
||||
if(isFalse){
|
||||
return "当前CPU使用率:"+cpuUsage +"%";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String handleMemoryUtilization(String threshold, int compareType){
|
||||
try {
|
||||
Map<String, Long> memInfo = AgentDataUtil.parseMemInfo();
|
||||
long total = memInfo.get("MemTotal");
|
||||
long available = memInfo.getOrDefault("MemAvailable",
|
||||
memInfo.get("MemFree") +
|
||||
memInfo.getOrDefault("Buffers", 0L) +
|
||||
memInfo.getOrDefault("Cached", 0L) +
|
||||
memInfo.getOrDefault("SReclaimable", 0L));
|
||||
// 总内存使用率
|
||||
double totalUsage = (double)(total - available) / total * 100;
|
||||
boolean isFalse = false;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
isFalse = compare(totalUsage, threshold, compareType);
|
||||
}
|
||||
if(isFalse){
|
||||
return "当前内存利用率:"+totalUsage +"%";
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String handleSystemSwapSizePercent(String threshold, int compareType){
|
||||
try {
|
||||
Map<String, Long> memInfo = AgentDataUtil.parseMemInfo();
|
||||
long swapTotal = memInfo.getOrDefault("SwapTotal", 0L);
|
||||
long swapFree = memInfo.getOrDefault("SwapFree", 0L);
|
||||
double swapSizePercent = (double) swapFree / swapTotal * 100; //可用交换空间百分比
|
||||
boolean isFalse = false;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
isFalse = compare(swapSizePercent, threshold, compareType);
|
||||
}
|
||||
if(isFalse){
|
||||
return "当前可用交换空间百分比:"+swapSizePercent +"%";
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String handleSystemUsersNum(String threshold, int compareType){
|
||||
SystemInfo si = new SystemInfo();
|
||||
OperatingSystem os = si.getOperatingSystem();
|
||||
int userNum = os.getSessions().size();
|
||||
boolean isFalse = false;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
isFalse = compare(userNum, threshold, compareType);
|
||||
}
|
||||
if(isFalse){
|
||||
return "当前登录用户数:"+userNum;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String handleVfsFsUtil(String threshold, int compareType){
|
||||
String result = "";
|
||||
SystemInfo si = new SystemInfo();
|
||||
for (OSFileStore fs : si.getOperatingSystem().getFileSystem().getFileStores()) {
|
||||
String mount = fs.getMount();
|
||||
long totalSpace = fs.getTotalSpace();
|
||||
long freeSpace = fs.getFreeSpace();
|
||||
double usagePercentage = totalSpace > 0 ?
|
||||
(double) (totalSpace - freeSpace) / totalSpace * 100 : 0;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
boolean isFalse = compare(usagePercentage, threshold, compareType);
|
||||
if(isFalse){
|
||||
result +="挂载点:"+mount+",当前空间利用率:"+usagePercentage+"%;";
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String handleNetUtil(String threshold, int compareType){
|
||||
String result = "";
|
||||
try {
|
||||
SystemInfo si = new SystemInfo();
|
||||
HardwareAbstractionLayer hal = si.getHardware();
|
||||
// 获取所有网络接口
|
||||
List<NetworkIF> networkIFs = hal.getNetworkIFs();
|
||||
// 第一次采样
|
||||
for (NetworkIF net : networkIFs) {
|
||||
net.updateAttributes();
|
||||
}
|
||||
// 等待1秒
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
// 第二次采样并计算速率
|
||||
for (NetworkIF net : networkIFs) {
|
||||
// 只显示以太网接口
|
||||
if (net.getName().startsWith("eth") ||
|
||||
net.getName().startsWith("en") ||
|
||||
net.getDisplayName().toLowerCase().contains("ethernet")) {
|
||||
long prevBytesSent = net.getBytesSent();
|
||||
net.updateAttributes();
|
||||
long bytesSent = net.getBytesSent() - prevBytesSent;
|
||||
// 获取最大带宽
|
||||
double maxBandwidth = getInterfaceMaxBandwidth(net);
|
||||
// 计算使用率百分比
|
||||
double sentUsagePercentage = (bytesToMbps(bytesSent) / maxBandwidth) * 100;
|
||||
boolean isFalse = false;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
isFalse = compare(sentUsagePercentage, threshold, compareType);
|
||||
}
|
||||
if(isFalse){
|
||||
result += "网络接口:"+ net.getName() + ",当前发送流量带宽使用率:" + sentUsagePercentage +"%;";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String handleContainerMemUtil(String threshold, int compareType){
|
||||
// 配置Docker客户端
|
||||
DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
|
||||
.withDockerHost("unix:///var/run/docker.sock")
|
||||
.withDockerTlsVerify(false) // 根据你的配置调整
|
||||
.build();
|
||||
DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
|
||||
.dockerHost(config.getDockerHost())
|
||||
.sslConfig(config.getSSLConfig())
|
||||
.maxConnections(100)
|
||||
.connectionTimeout(Duration.ofSeconds(30))
|
||||
.responseTimeout(Duration.ofSeconds(45))
|
||||
.build();
|
||||
DockerClient dockerClient = DockerClientImpl.getInstance(config, httpClient);
|
||||
String result = "";
|
||||
try {
|
||||
// 获取正在运行的容器列表
|
||||
List<Container> containers = dockerClient.listContainersCmd()
|
||||
.withShowAll(false) // 只显示运行中的容器
|
||||
.exec();
|
||||
// 打印容器信息
|
||||
System.out.println("运行中的Docker容器:");
|
||||
System.out.println("容器ID\t\t镜像\t\t状态\t\t名称");
|
||||
for (Container container : containers) {
|
||||
String id = container.getId().substring(0, 12); // 只显示短ID
|
||||
String name = container.getNames()[0].replaceFirst("/", "");
|
||||
// 执行 docker stats 命令(--no-stream 表示只输出一次)
|
||||
Process process = new ProcessBuilder(
|
||||
"docker", "stats", "--no-stream", id,
|
||||
"--format", "'table {{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.NetIO}}"
|
||||
).start();
|
||||
// 读取命令输出
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(process.getInputStream())
|
||||
);
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] parts = line.trim().split("\\s+");
|
||||
String memUtil = parts[4]; // 内存使用率
|
||||
memUtil = memUtil.replace("%","");
|
||||
if(StringUtils.isNotBlank(memUtil)){
|
||||
boolean isFalse = false;
|
||||
if(StringUtils.isNotBlank(threshold)){
|
||||
isFalse = compare(Double.parseDouble(memUtil), threshold, compareType);
|
||||
}
|
||||
if(isFalse){
|
||||
result += "容器:"+name+",当前内存使用率"+memUtil+"%;";
|
||||
}
|
||||
}
|
||||
}
|
||||
// 等待命令执行完成并获取退出码
|
||||
int exitCode = process.waitFor();
|
||||
if (exitCode != 0) {
|
||||
System.err.println("命令执行失败,退出码: " + exitCode);
|
||||
}
|
||||
reader.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
dockerClient.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String handleNetIfStatus(){
|
||||
String result = "";
|
||||
try {
|
||||
List<NativeNetworkInterfaceEO> list = getAllNetworkInterfaces();
|
||||
if(CollectionUtil.isNotEmpty(GlobalConfig.NET_LIST)){
|
||||
List<String> natList = list.stream().filter(n -> n.isUp() == false).map(NativeNetworkInterfaceEO::getName).collect(Collectors.toList());
|
||||
List<NativeNetworkInterfaceEO> temp = GlobalConfig.NET_LIST.stream().filter(n -> n.isUp())
|
||||
.collect(Collectors.toList());
|
||||
for (NativeNetworkInterfaceEO n : temp) {
|
||||
if(natList.contains(n.getName())){
|
||||
result += "网络接口:"+n.getName()+",运行状态由UP转为DOWN;";
|
||||
}
|
||||
}
|
||||
}
|
||||
GlobalConfig.NET_LIST = list;
|
||||
} catch (SocketException e) {
|
||||
System.err.println("获取网络接口信息失败: " + e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String handleExtraPorts(String threshold){
|
||||
String result = "";
|
||||
try {
|
||||
List<Integer> list = scanPortsUsingNmap();
|
||||
for (Integer port : list) {
|
||||
boolean flag = verifyPort(port, threshold);
|
||||
if(!flag){
|
||||
result += "端口:"+port+"已开放;";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean compare(double value, String threshold, int compareType){
|
||||
boolean isFalse = false;
|
||||
switch(compareType) {
|
||||
case 1: //大于且等于
|
||||
if(value >= Double.parseDouble(threshold)){
|
||||
isFalse = true;
|
||||
}
|
||||
break;
|
||||
case 2: //小于
|
||||
if(value < Double.parseDouble(threshold)){
|
||||
isFalse = true;
|
||||
}
|
||||
break;
|
||||
case 3: //小于且等于
|
||||
if(value <= Double.parseDouble(threshold)){
|
||||
isFalse = true;
|
||||
}
|
||||
break;
|
||||
default: //大于
|
||||
if(value > Double.parseDouble(threshold)){
|
||||
isFalse = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return isFalse;
|
||||
}
|
||||
|
||||
private static double bytesToMbps(long bytes) {
|
||||
return bytes * 8.0 / 1_000_000; // bytes to megabits
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取接口的理论最大带宽(Mbps)
|
||||
*/
|
||||
private double getInterfaceMaxBandwidth(NetworkIF netIf) {
|
||||
String name = netIf.getName().toLowerCase();
|
||||
long speed = netIf.getSpeed(); // 获取接口速度(bps)
|
||||
|
||||
if (speed > 0) {
|
||||
return speed / 1_000_000.0; // 转换为Mbps
|
||||
}
|
||||
|
||||
// 如果无法获取速度,根据常见接口类型估算
|
||||
if (name.contains("eth") || name.contains("en") || name.contains("gigabit")) {
|
||||
return 1000.0; // 千兆以太网
|
||||
} else if (name.contains("10g") || name.contains("10000")) {
|
||||
return 10000.0; // 万兆以太网
|
||||
} else {
|
||||
return 100.0; // 默认百兆以太网
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有网络接口信息
|
||||
*/
|
||||
public List<NativeNetworkInterfaceEO> getAllNetworkInterfaces() throws SocketException {
|
||||
List<NativeNetworkInterfaceEO> interfaces = new ArrayList<>();
|
||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
while (networkInterfaces.hasMoreElements()) {
|
||||
NetworkInterface ni = networkInterfaces.nextElement();
|
||||
NativeNetworkInterfaceEO interfaceInfo = NativeNetworkInterfaceEO.builder()
|
||||
.name(ni.getName())
|
||||
.displayName(ni.getDisplayName())
|
||||
.up(ni.isUp())
|
||||
.build();
|
||||
interfaces.add(interfaceInfo);
|
||||
}
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有开放端口
|
||||
*/
|
||||
public List<Integer> scanPortsUsingNmap() throws Exception {
|
||||
List<Integer> openPorts = new ArrayList<>();
|
||||
Process process = Runtime.getRuntime().exec("nmap -p 1-65535 localhost");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
Pattern pattern = Pattern.compile("\\d+/tcp open"); // Adjust the regex based on nmap output format you expect
|
||||
while ((line = reader.readLine()) != null) {
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (matcher.find()) { // Assuming the output format is "port/protocol state" where state is "open" for open ports
|
||||
String portStr = matcher.group(0).split("/")[0]; // Extract the port number part before "/tcp" or "/udp" etc.
|
||||
openPorts.add(Integer.parseInt(portStr)); // Add the port number to the list of open ports
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
return openPorts;
|
||||
}
|
||||
|
||||
public boolean verifyPort(int port, String threshold){
|
||||
String[] ports = threshold.split(";");
|
||||
for (int i = 0; i < ports.length; i++) {
|
||||
String p = ports[i];
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
String[] arr = p.split("-");
|
||||
start = Integer.parseInt(arr[0]);
|
||||
if(arr.length == 2){
|
||||
end = Integer.parseInt(arr[1]);
|
||||
}
|
||||
if(start <= port && port <= end){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.tongran.agent.client.utils;
|
||||
|
||||
import com.tongran.agent.client.core.eo.AlarmEO;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AgentDataUtil {
|
||||
@@ -23,4 +26,9 @@ public class AgentDataUtil {
|
||||
}
|
||||
return memInfo;
|
||||
}
|
||||
|
||||
public static boolean hasAnyActiveAlarm(List<AlarmEO> alarmEOList) {
|
||||
return alarmEOList.stream()
|
||||
.anyMatch(AlarmEO::isCollect);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user