diff options
| author | shizhendong <[email protected]> | 2023-01-06 15:45:41 +0800 |
|---|---|---|
| committer | shizhendong <[email protected]> | 2023-01-06 15:45:41 +0800 |
| commit | 2de0f25498cb7951bd005fa9af8d922ed0c1af9e (patch) | |
| tree | 7d7f936f40a966dcca697f65c1502593ca0c2d6e | |
| parent | fc8b027fad8a629763b541d82acb6753012b576a (diff) | |
feat: NEZ-2488 新增 agent 故障诊断接口rel-23.01.01
7 files changed, 413 insertions, 3 deletions
diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java index fbb4e572..aa1480f0 100644 --- a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java @@ -74,12 +74,25 @@ public class DiagnoseClient { /** * add Diagnose Msg * - * @param map + * @param diagnoseMsg */ - public static void addDiagnoseMsg(Map<Object, Object> map) { + public static void addDiagnoseMsg(Map<Object, Object> diagnoseMsg) { // query Diagnose Msg List<Map<Object, Object>> mapList = DiagnoseClient.queryDiagnoseMsg(); - mapList.add(map); + mapList.add(diagnoseMsg); + + THREAD_LOCAL.set(mapList); + } + + /** + * add Diagnose Msg List + * + * @param diagnoseMsgList + */ + public static void addDiagnoseMsg(List<Map<Object, Object>> diagnoseMsgList) { + // query Diagnose Msg + List<Map<Object, Object>> mapList = DiagnoseClient.queryDiagnoseMsg(); + mapList.addAll(diagnoseMsgList); THREAD_LOCAL.set(mapList); } diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java new file mode 100644 index 00000000..796e1d3f --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java @@ -0,0 +1,160 @@ +package com.nis.modules.diagnose.chain.agent; + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.util.AgentUtil; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; + +import java.util.List; +import java.util.Map; + +/** + * AgentComponentsCheckInterceptor + * 检查 Agent 组件状态 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class AgentComponentsCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static final String AGENT_AUTH_SUCCESS = "TRUE"; + private static final String COMPONENT_AVAILABLE_STATUS = "UP"; + private static final String COMPONENT_UNAVAILABLE_STATUS = "DOWN"; + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[AgentComponentsCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + Agent agent = (Agent) chain.object(); + + // check Components Status + List<Map<Object, Object>> diagnoseMsgList = this.checkComponentsStatus(agent); + + // update check msg + DiagnoseClient.addDiagnoseMsg(diagnoseMsgList); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.components") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + } + + /** + * check Components Status + * + * @param agent + * @return + */ + private List<Map<Object, Object>> checkComponentsStatus(Agent agent) { + String resultJsonStr = Tool.StrUtil.EMPTY_JSON; + try { + resultJsonStr = AgentUtil.requestGet(agent, "/healthy", null, String.class); + } catch (Exception e) { + log.error(e, "[checkComponentsStatus] [request agent healthy api error] [agent: {}]", Tool.JSONUtil.toJsonStr(agent)); + } + log.info("[checkComponentsStatus] [agent healthy api] [result: {}]", resultJsonStr); + + List<Map<Object, Object>> componentsStatusList = Tool.ListUtil.list(true); + + Map resultObj = JSONObject.parseObject(resultJsonStr, Map.class); + if (Tool.BooleanUtil.or( + Tool.MapUtil.isEmpty(resultObj), + Tool.ObjectUtil.notEqual(RCode.SUCCESS.getCode(), resultObj.get("code")))) { + // nzagent error + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.nzagent") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.nzagent") + .map()); + } else { + Object auth = JSONPath.read(resultJsonStr, "data.auth"); + if (Tool.ObjectUtil.notEqual(AGENT_AUTH_SUCCESS, auth)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.auth") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.auth") + .map()); + } + + Object cortex = JSONPath.read(resultJsonStr, "data.cortex"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, cortex)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.cortex") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.cortex") + .map()); + } + + Object loki = JSONPath.read(resultJsonStr, "data.loki"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, loki)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.loki") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.loki") + .map()); + } + + Object snmpExporter = JSONPath.read(resultJsonStr, "data.snmp_exporter"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, snmpExporter)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.snmpExporter") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.snmpExporter") + .map()); + } + + Object blackboxExporter = JSONPath.read(resultJsonStr, "data.blackbox_exporter"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, blackboxExporter)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.blackboxExporter") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.blackboxExporter") + .map()); + } + + Object prometheus = JSONPath.read(resultJsonStr, "data.prometheus"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, prometheus)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.prometheus") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.prometheus") + .map()); + } + + Object nzagent = JSONPath.read(resultJsonStr, "data.confagent"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, nzagent)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.nzagent") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.nzagent") + .map()); + } + } + + // 所有检查通过 PASS + if (Tool.CollUtil.isEmpty(componentsStatusList)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.components") + .put("state", DiagnoseState.PASS.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map()); + } + return componentsStatusList; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java new file mode 100644 index 00000000..60a2f6f6 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java @@ -0,0 +1,104 @@ +package com.nis.modules.diagnose.chain.agent; + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.apache.commons.lang3.time.StopWatch; + +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Map; + +/** + * AgentConnectableCheckInterceptor + * 检查 Agent Host&Port 网络情况,端口是否开放 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class AgentConnectableCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[AgentConnectableCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + Agent agent = (Agent) chain.object(); + + // check Host Is Connectable + boolean isConnectable = this.checkHostIsConnectable(agent.getHost(), agent.getPort()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.connectable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (isConnectable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.agent.resolution.connectable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.connectable") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Host Is Connectable + * + * @param host + * @param port + * @return + */ + public boolean checkHostIsConnectable(String host, int port) { + log.info("[checkHostIsConnectable] [begin] [host: {}] [port: {}]", host, port); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isConnectable = false; + + Socket socket = new Socket(); + try { + InetSocketAddress socketAddress = new InetSocketAddress(host, port); + socket.connect(socketAddress, 5000); + isConnectable = socket.isConnected(); + } catch (Exception e) { + log.error(e, "[checkHostIsConnectable] [error in check process] [host: {}] [port: {}]", host, port); + } finally { + Tool.IoUtil.close(socket); + sw.stop(); + } + + log.info("[checkHostIsConnectable] [check completed] [host: {}] [port: {}] [connected: {}] [Run Time: {}]", host, port, isConnectable, sw.toString()); + return isConnectable; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java new file mode 100644 index 00000000..2013fdde --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java @@ -0,0 +1,84 @@ +package com.nis.modules.diagnose.chain.agent; + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.apache.commons.lang3.time.StopWatch; + +import java.net.InetAddress; +import java.util.Map; + +/** + * AgentNetworkCheckInterceptor + * 检查 Agent Host 网络情况,是否可达 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class AgentNetworkCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + // process object + Agent agent = (Agent) chain.object(); + + // check Ip IsR eachable + boolean ipIsReachable = this.checkIpIsReachable(agent.getHost()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.reachable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (ipIsReachable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.agent.resolution.reachable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Ip IsR eachable + * + * @param host + * @return a {@code boolean} indicating if the address is reachable. + */ + private boolean checkIpIsReachable(String host) { + log.info("[checkIpIsReachable] [begin] [host: {}]", host); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isReachable = false; + try { + InetAddress inetAddress = InetAddress.getByName(host); + // timeout the time, in milliseconds, before the call aborts, default 5s + isReachable = inetAddress.isReachable(5000); + } catch (Exception e) { + log.error(e, "[checkIpIsReachable] [error in check process] [host: {}]", host); + } finally { + sw.stop(); + } + + log.info("[checkIpIsReachable] [check completed] [host: {}] [reachable: {}] [Run Time: {}]", host, isReachable, sw.toString()); + return isReachable; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java b/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java index 6beb5b12..91a15eaf 100644 --- a/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java @@ -34,4 +34,13 @@ public class DiagnoseController { return R.ok().putData("list", diagnoseMsgList); } + @GetMapping("/agent/diagnose/{id}") + public R agentDiagnose(@PathVariable(value = "id", required = false) Integer agentId, + @RequestHeader(required = false, defaultValue = "en") String language) { + ValidateUtils.is(agentId).notNull(RCode.AGENT_ID_ISNULL); + + List<Map<Object, Object>> diagnoseMsgList = diagnoseService.agentErrorDiagnosis(agentId, language); + return R.ok().putData("list", diagnoseMsgList); + } + } diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java b/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java index 6d813618..6ceaa16d 100644 --- a/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java @@ -21,5 +21,13 @@ public interface DiagnoseService { */ List<Map<Object, Object>> assetErrorDiagnosis(Integer assetId, String language); + /** + * agent Diagnosis + * + * @param agentId + * @param language + * @return + */ + List<Map<Object, Object>> agentErrorDiagnosis(Integer agentId, String language); } diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java index af5b27cb..da54e55a 100644 --- a/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java @@ -3,9 +3,14 @@ package com.nis.modules.diagnose.service.impl; import cn.hutool.log.Log; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.RCode; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.agent.AgentComponentsCheckInterceptor; +import com.nis.modules.diagnose.chain.agent.AgentConnectableCheckInterceptor; +import com.nis.modules.diagnose.chain.agent.AgentNetworkCheckInterceptor; import com.nis.modules.diagnose.chain.asset.AgentStateCheckOfPingInterceptor; import com.nis.modules.diagnose.chain.asset.AssetNetworkCheckInterceptor; import com.nis.modules.diagnose.chain.asset.AssetStateConfCheckInterceptor; @@ -30,6 +35,9 @@ public class DiagnoseServiceImpl implements DiagnoseService { private static final Log log = Log.get(); @Autowired + private AgentService agentService; + + @Autowired private AssetAssetService assetService; @Autowired @@ -60,6 +68,30 @@ public class DiagnoseServiceImpl implements DiagnoseService { } } + @Override + public List<Map<Object, Object>> agentErrorDiagnosis(Integer agentId, String language) { + try { + Agent agent = agentService.getById(agentId); + ValidateUtils.is(agent).notNull(RCode.AGENT_NOTEXSITS); + + // diagnose client. set diagnose chain + DiagnoseClient diagnoseClient = new DiagnoseClient.Builder() + .addInterceptor(new AgentNetworkCheckInterceptor()) + .addInterceptor(new AgentConnectableCheckInterceptor()) + .addInterceptor(new AgentComponentsCheckInterceptor()) + .build(); + + // diagnose + diagnoseClient.diagnose(agent); + + // Diagnose Msg List + List<Map<Object, Object>> diagnoseMsgList = this.queryDiagnoseMsgByLanguage(language); + return diagnoseMsgList; + } finally { + DiagnoseClient.cleanDiagnoseMsg(); + } + } + /** * query Diagnose Msg By Language * |
