summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshizhendong <[email protected]>2023-01-06 15:45:41 +0800
committershizhendong <[email protected]>2023-01-06 15:45:41 +0800
commit2de0f25498cb7951bd005fa9af8d922ed0c1af9e (patch)
tree7d7f936f40a966dcca697f65c1502593ca0c2d6e
parentfc8b027fad8a629763b541d82acb6753012b576a (diff)
feat: NEZ-2488 新增 agent 故障诊断接口rel-23.01.01
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java19
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java160
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java104
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java84
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java9
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java8
-rw-r--r--nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java32
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
*