From 3204ad69ef0f886ad142afa33d54a655799e6b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9C=E9=A3=8E?= <74083801+ZY945@users.noreply.github.com> Date: Sat, 9 Dec 2023 11:41:07 +0800 Subject: [PATCH] add ntp protocol and support ntp monitoring (#1411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 东风 <1335799468@qq.com> --- .../collector/collect/ntp/NtpCollectImpl.java | 128 +++++++++++++++ .../collector/dispatch/DispatchConstants.java | 4 + ...ertzbeat.collector.collect.AbstractCollect | 1 + .../hertzbeat/common/entity/job/Metrics.java | 5 + .../entity/job/protocol/NtpProtocol.java | 30 ++++ manager/src/main/resources/define/app-ntp.yml | 153 ++++++++++++++++++ 6 files changed, 321 insertions(+) create mode 100644 collector/src/main/java/org/dromara/hertzbeat/collector/collect/ntp/NtpCollectImpl.java create mode 100644 common/src/main/java/org/dromara/hertzbeat/common/entity/job/protocol/NtpProtocol.java create mode 100644 manager/src/main/resources/define/app-ntp.yml diff --git a/collector/src/main/java/org/dromara/hertzbeat/collector/collect/ntp/NtpCollectImpl.java b/collector/src/main/java/org/dromara/hertzbeat/collector/collect/ntp/NtpCollectImpl.java new file mode 100644 index 00000000000..03799112a7a --- /dev/null +++ b/collector/src/main/java/org/dromara/hertzbeat/collector/collect/ntp/NtpCollectImpl.java @@ -0,0 +1,128 @@ +package org.dromara.hertzbeat.collector.collect.ntp; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.net.ntp.NTPUDPClient; +import org.apache.commons.net.ntp.NtpV3Packet; +import org.apache.commons.net.ntp.TimeInfo; +import org.apache.commons.net.ntp.TimeStamp; +import org.dromara.hertzbeat.collector.collect.AbstractCollect; +import org.dromara.hertzbeat.collector.dispatch.DispatchConstants; +import org.dromara.hertzbeat.collector.util.CollectUtil; +import org.dromara.hertzbeat.common.constants.CollectorConstants; +import org.dromara.hertzbeat.common.constants.CommonConstants; +import org.dromara.hertzbeat.common.entity.job.Metrics; +import org.dromara.hertzbeat.common.entity.job.protocol.NtpProtocol; +import org.dromara.hertzbeat.common.entity.message.CollectRep; +import org.dromara.hertzbeat.common.util.CommonUtil; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @author dongfeng + */ +@Slf4j +public class NtpCollectImpl extends AbstractCollect { + public NtpCollectImpl() { + } + + @Override + public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) { + long startTime = System.currentTimeMillis(); + if (metrics == null || metrics.getNtp() == null) { + builder.setCode(CollectRep.Code.FAIL); + builder.setMsg("NTP collect must have NTP params"); + return; + } + NtpProtocol ntpProtocol = metrics.getNtp(); + String host = ntpProtocol.getHost(); + int timeout = CollectUtil.getTimeout(ntpProtocol.getTimeout()); + + NTPUDPClient client = null; + + try { + client = new NTPUDPClient(); + client.setDefaultTimeout(timeout); + client.open(); + InetAddress serverAddress = InetAddress.getByName(host); + TimeInfo timeInfo = client.getTime(serverAddress); + long responseTime = System.currentTimeMillis() - startTime; + + timeInfo.computeDetails(); + + // 获取ntp服务器信息 + Map resultMap = getNTPInfo(timeInfo); + resultMap.put(CollectorConstants.RESPONSE_TIME, Long.toString(responseTime)); + + List aliasFields = metrics.getAliasFields(); + CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder(); + for (String field : aliasFields) { + String fieldValue = resultMap.get(field); + valueRowBuilder.addColumns(Objects.requireNonNullElse(fieldValue, CommonConstants.NULL_VALUE)); + } + builder.addValues(valueRowBuilder.build()); + client.close(); + } catch (SocketException socketException) { + String errorMsg = CommonUtil.getMessageFromThrowable(socketException); + log.debug(errorMsg); + builder.setCode(CollectRep.Code.FAIL); + builder.setMsg("NTPUDPClient open is fail: " + errorMsg); + } catch (UnknownHostException unknownHostException) { + String errorMsg = CommonUtil.getMessageFromThrowable(unknownHostException); + log.debug(errorMsg); + builder.setCode(CollectRep.Code.UN_CONNECTABLE); + builder.setMsg("NTPServerAddress is unknownHost: " + errorMsg); + } catch (IOException ioException) { + String errorMsg = CommonUtil.getMessageFromThrowable(ioException); + log.info(errorMsg); + builder.setCode(CollectRep.Code.UN_CONNECTABLE); + builder.setMsg("Receive timed out: " + timeout + "ms"); + } catch (Exception e) { + String errorMsg = CommonUtil.getMessageFromThrowable(e); + log.warn(errorMsg, e); + builder.setCode(CollectRep.Code.FAIL); + builder.setMsg(errorMsg); + } finally { + if (client != null) { + try { + client.close(); + } catch (Exception e) { + log.warn(e.getMessage()); + } + } + } + } + + private Map getNTPInfo(TimeInfo timeInfo) { + Map valueMap = new HashMap<>(16); + + TimeStamp timeStamp = timeInfo.getMessage().getTransmitTimeStamp(); + Date date = timeStamp.getDate(); + + NtpV3Packet message = timeInfo.getMessage(); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + valueMap.put("time", Long.toString(timeStamp.getTime())); + valueMap.put("date", simpleDateFormat.format(date)); + valueMap.put("offset", Long.toString(timeInfo.getOffset())); + valueMap.put("delay", Long.toString(timeInfo.getDelay())); + valueMap.put("version", Integer.toString(message.getVersion())); + valueMap.put("mode", Integer.toString(message.getMode())); + valueMap.put("stratum", Integer.toString(message.getStratum())); + valueMap.put("referenceId", String.valueOf(message.getReferenceId())); + valueMap.put("precision", Integer.toString(message.getPrecision())); + return valueMap; + } + + @Override + public String supportProtocol() { + return DispatchConstants.PROTOCOL_NTP; + } +} \ No newline at end of file diff --git a/collector/src/main/java/org/dromara/hertzbeat/collector/dispatch/DispatchConstants.java b/collector/src/main/java/org/dromara/hertzbeat/collector/dispatch/DispatchConstants.java index 820cc2ed49e..b67ea1506b3 100644 --- a/collector/src/main/java/org/dromara/hertzbeat/collector/dispatch/DispatchConstants.java +++ b/collector/src/main/java/org/dromara/hertzbeat/collector/dispatch/DispatchConstants.java @@ -39,6 +39,10 @@ public interface DispatchConstants { * protocol smtp */ String PROTOCOL_SMTP = "smtp"; + /** + * protocol ntp + */ + String PROTOCOL_NTP = "ntp"; /** * protocol udp */ diff --git a/collector/src/main/resources/META-INF/services/org.dromara.hertzbeat.collector.collect.AbstractCollect b/collector/src/main/resources/META-INF/services/org.dromara.hertzbeat.collector.collect.AbstractCollect index 2b8a22393b1..bce577cc0b9 100644 --- a/collector/src/main/resources/META-INF/services/org.dromara.hertzbeat.collector.collect.AbstractCollect +++ b/collector/src/main/resources/META-INF/services/org.dromara.hertzbeat.collector.collect.AbstractCollect @@ -9,6 +9,7 @@ org.dromara.hertzbeat.collector.collect.snmp.SnmpCollectImpl org.dromara.hertzbeat.collector.collect.ssh.SshCollectImpl org.dromara.hertzbeat.collector.collect.telnet.TelnetCollectImpl org.dromara.hertzbeat.collector.collect.smtp.SmtpCollectImpl +org.dromara.hertzbeat.collector.collect.ntp.NtpCollectImpl org.dromara.hertzbeat.collector.collect.ftp.FtpCollectImpl org.dromara.hertzbeat.collector.collect.mq.RocketmqSingleCollectImpl org.dromara.hertzbeat.collector.collect.udp.UdpCollectImpl diff --git a/common/src/main/java/org/dromara/hertzbeat/common/entity/job/Metrics.java b/common/src/main/java/org/dromara/hertzbeat/common/entity/job/Metrics.java index 1edf9669995..b3950f2174a 100644 --- a/common/src/main/java/org/dromara/hertzbeat/common/entity/job/Metrics.java +++ b/common/src/main/java/org/dromara/hertzbeat/common/entity/job/Metrics.java @@ -120,6 +120,11 @@ public class Metrics { * 使用smtp协议的监控配置信息 */ private SmtpProtocol smtp; + /** + * Monitoring configuration information using the public ntp protocol + * 使用ntp协议的监控配置信息 + */ + private NtpProtocol ntp; /** * Use udp implemented by socket for service port detection configuration information * 使用socket实现的udp进行服务端口探测配置信息 diff --git a/common/src/main/java/org/dromara/hertzbeat/common/entity/job/protocol/NtpProtocol.java b/common/src/main/java/org/dromara/hertzbeat/common/entity/job/protocol/NtpProtocol.java new file mode 100644 index 00000000000..4e7b614bb5b --- /dev/null +++ b/common/src/main/java/org/dromara/hertzbeat/common/entity/job/protocol/NtpProtocol.java @@ -0,0 +1,30 @@ +package org.dromara.hertzbeat.common.entity.job.protocol; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author dongfeng + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NtpProtocol { + /** + * NTP主机ip或域名 + */ + private String host; + + /** + * NTP主机端口 + */ + private String port; + + /** + * 超时时间 + */ + private String timeout; +} diff --git a/manager/src/main/resources/define/app-ntp.yml b/manager/src/main/resources/define/app-ntp.yml new file mode 100644 index 00000000000..057fa63913e --- /dev/null +++ b/manager/src/main/resources/define/app-ntp.yml @@ -0,0 +1,153 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +# The monitoring type category:service-application service monitoring db-database monitoring mid-middleware custom-custom monitoring os-operating system monitoring +# 监控类型所属类别:service-应用服务 program-应用程序 db-数据库 custom-自定义 os-操作系统 bigdata-大数据 mid-中间件 webserver-web服务器 cache-缓存 cn-云原生 network-网络监控等等 +category: service +# The monitoring type eg: linux windows tomcat mysql aws... +# 监控类型 eg: linux windows tomcat mysql aws... +app: ntp +# 监控类型国际化名称 +name: + zh-CN: NTP监控 + en-US: NTP MONITORS +# The description and help of this monitoring type +# 监控类型的帮助描述信息 +help: + zh-CN: HertzBeat 对 NTP 服务的(响应时间、时间戳、时间、偏移量、延迟、版本号、模式、层级、参考ID、精度)相关指标进行监测。 + en-US: HertzBeat monitors the relevant indicators of NTP services, including response time, timestamp, time, offset, delay, version number, mode, hierarchy, reference ID, and accuracy. + zh-TW: HertzBeat對NTP服務的(回應時間、時間戳記、時間、偏移量、延遲、版本號、模式、層級、參攷ID、精度)相關名額進行監測。 +# 监控所需输入参数定义(根据定义渲染页面UI) +# Input params define for monitoring(render web ui by the definition) +params: + # field-param field key + # field-字段名称标识符 + - field: host + # name-param field display i18n name + # name-参数字段显示名称 + name: + zh-CN: NTP服务的Host + en-US: Host of NTP service + # type-param field type(most mapping the html input type) + # type-字段类型,样式(大部分映射input标签type属性) + type: host + # required-true or false + # 是否是必输项 true-必填 false-可选 + required: true + # field-param field key + # field-字段名称标识符 + - field: timeout + # name-param field display i18n name + # name-参数字段显示名称 + name: + zh-CN: 连接超时时间(ms) + en-US: Connect Timeout(ms) + # type-param field type(most mapping the html input type) + # type-字段类型,样式(大部分映射input标签type属性) + type: number + # when type is number, range is required + # 当type为number时,用range表示范围 + range: '[0,100000]' + # required-true or false + # 是否是必输项 true-必填 false-可选 + required: true + # default value 6000 + # 默认值 6000 + defaultValue: 6000 +# collect metrics config list +# 采集指标配置列表 +metrics: + # metrics - summary + # 监控指标 - summary + - name: summary + i18n: + zh-CN: 概要 + en-US: Summary + # metrics scheduling priority(0->127)->(high->low), metrics with the same priority will be scheduled in parallel + # priority 0's metrics is availability metrics, it will be scheduled first, only availability metrics collect success will the scheduling continue + # 指标采集调度优先级(0->127)->(优先级高->低) 优先级低的指标会等优先级高的指标采集完成后才会被调度, 相同优先级的指标会并行调度采集 + # 优先级为0的指标为可用性指标,即它会被首先调度,采集成功才会继续调度其它指标,采集失败则中断调度 + priority: 0 + # 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 label-是否是指标标签字段 unit:指标单位 + # field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field + # field-指标名称, type-指标类型(0-number数字,1-string字符串), unit-指标单位('%','ms','MB'), label-是否是指标标签字段 + fields: + - field: responseTime + type: 0 + unit: ms + i18n: + zh-CN: 响应时间 + en-US: ResponseTime + - field: time + type: 0 + unit: ms + i18n: + zh-CN: 时间戳 + en-US: time + - field: date + type: 1 + i18n: + zh-CN: 时间 + en-US: date + - field: offset + type: 0 + unit: ms + i18n: + zh-CN: 偏移量 + en-US: offset + - field: delay + type: 0 + unit: ms + i18n: + zh-CN: 延迟 + en-US: delay + - field: version + type: 0 + i18n: + zh-CN: 版本号 + en-US: version + - field: mode + type: 0 + i18n: + zh-CN: 模式 + en-US: mode + - field: stratum + type: 0 + i18n: + zh-CN: 层级 + en-US: stratum + - field: referenceId + type: 1 + i18n: + zh-CN: 参考ID + en-US: referenceId + - field: precision + type: 0 + i18n: + zh-CN: 精度 + en-US: precision + + # the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk + # 采集协议, 目前支持sql, ssh, http, telnet, wmi, snmp, sdk + protocol: ntp + # Specific collection configuration when protocol is telnet protocol + # 当protocol为telnet协议时具体的采集配置 + ntp: + # telnet host + # 远程登录主机 + host: ^_^host^_^ + # timeout + # 超时时间 + timeout: ^_^timeout^_^