Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add smtp protocol and support smtp monitoring #1407

Merged
merged 4 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package org.dromara.hertzbeat.collector.collect.smtp;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.smtp.SMTP;
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.SmtpProtocol;
import org.dromara.hertzbeat.common.entity.message.CollectRep;
import org.dromara.hertzbeat.common.util.CommonUtil;

import java.io.IOException;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
* @author dongfeng
*/
@Slf4j
public class SmtpCollectImpl extends AbstractCollect {
public SmtpCollectImpl() {
}

@Override
public void collect(CollectRep.MetricsData.Builder builder, long monitorId, String app, Metrics metrics) {
long startTime = System.currentTimeMillis();
if (metrics == null || metrics.getSmtp() == null) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Smtp collect must has Smtp params");
return;
}
SmtpProtocol smtpProtocol = metrics.getSmtp();
String host = smtpProtocol.getHost();
String port = smtpProtocol.getPort();
int timeout = CollectUtil.getTimeout(smtpProtocol.getTimeout());
SMTP smtp = null;
try {
smtp = new SMTP();
smtp.setConnectTimeout(timeout);
smtp.setCharset(StandardCharsets.UTF_8);
smtp.connect(host, Integer.parseInt(port));
if (smtp.isConnected()) {
long responseTime = System.currentTimeMillis() - startTime;
List<String> aliasFields = metrics.getAliasFields();

Map<String, String> resultMap = execCmdAndParseResult(smtp, smtpProtocol.getCmd(), smtpProtocol);
resultMap.put(CollectorConstants.RESPONSE_TIME, Long.toString(responseTime));
if (resultMap.size() < aliasFields.size()) {
log.error("smtp response data not enough: {}", resultMap);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("The cmd execution results do not match the expected number of metrics.");
return;
}
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());
} else {
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg("Peer connect failed,Timeout " + timeout + "ms");
return;
}
smtp.disconnect();
} catch (SocketException socketException) {
String errorMsg = CommonUtil.getMessageFromThrowable(socketException);
log.debug(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg("The peer refused to connect: service port does not listening or firewall: " + errorMsg);
} catch (IOException ioException) {
String errorMsg = CommonUtil.getMessageFromThrowable(ioException);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg("Peer connect failed: " + errorMsg);
} catch (Exception e) {
String errorMsg = CommonUtil.getMessageFromThrowable(e);
log.warn(errorMsg, e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} finally {
if (smtp != null) {
try {
smtp.disconnect();
} catch (Exception e) {
log.warn(e.getMessage());
}
}
}
}

@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_SMTP;
}

private static Map<String, String> execCmdAndParseResult(SMTP smtp, String cmd, SmtpProtocol smtpProtocol) throws IOException {
Map<String, String> result = new HashMap<>(8);
// 存入smtp连接的响应
result.put("smtpBanner", smtp.getReplyString());
smtp.helo(smtpProtocol.getEmail());
// 获取helo的响应
String replyString = smtp.getReplyString();
result.put("heloInfo", replyString);
String[] lines = replyString.split("\n");
for (String line : lines) {
if (line.startsWith("250")) {
result.put("response", "OK");
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public interface DispatchConstants {
* protocol telnet
*/
String PROTOCOL_TELNET = "telnet";
/**
* protocol smtp
*/
String PROTOCOL_SMTP = "smtp";
/**
* protocol udp
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ org.dromara.hertzbeat.collector.collect.mongodb.MongodbSingleCollectImpl
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.ftp.FtpCollectImpl
org.dromara.hertzbeat.collector.collect.mq.RocketmqSingleCollectImpl
org.dromara.hertzbeat.collector.collect.udp.UdpCollectImpl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ public class Metrics {
* 使用telnet协议的监控配置信息
*/
private TelnetProtocol telnet;
/**
* Monitoring configuration information using the public smtp protocol
* 使用smtp协议的监控配置信息
*/
private SmtpProtocol smtp;
/**
* Use udp implemented by socket for service port detection configuration information
* 使用socket实现的udp进行服务端口探测配置信息
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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 SmtpProtocol {
/**
* email主机ip或域名
*/
private String host;

/**
* email主机端口
*/
private String port;

/**
* 超时时间
*/
private String timeout;

/**
* helo命令的测试者(email)
*/
private String email;

/**
* 发送的命令
*/
private String cmd;
}
172 changes: 172 additions & 0 deletions manager/src/main/resources/define/app-smtp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# 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: smtp
# 监控类型国际化名称
name:
zh-CN: SMTP监控
en-US: SMTP MONITORS
# The description and help of this monitoring type
# 监控类型的帮助描述信息
help:
zh-CN: HertzBeat 对 SMTP 服务的(Banner,helo响应)相关指标进行监测。
en-US: HertzBeat monitors the banner and hello response related indicators of the SMTP service.
zh-TW: HertzBeat對SMTP服務的(Banner,helo響應)相關名額進行監測。
# 监控所需输入参数定义(根据定义渲染页面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: SMTP的Host
en-US: Target Host
# 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: port
# name-param field display i18n name
# name-参数字段显示名称
name:
zh-CN: 端口
en-US: Port
# 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,65535]'
# required-true or false
# 是否是必输项 true-必填 false-可选
required: true
# default value 25
# 默认值 25
defaultValue: 25
# 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
# field-param field key
# field-字段名称标识符
- field: email
name:
zh-CN: email
en-US: email
type: text
# required-true or false
# 是否是必输项 true-必填 false-可选
required: true
# 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: response
type: 1
i18n:
zh-CN: 响应状态
en-US: Response
- field: smtpBanner
type: 1
i18n:
zh-CN: SMTP的Banner
en-US: SMTPBanner
- field: heloInfo
type: 1
i18n:
zh-CN: Helo日志
en-US: HeloInfo
# - field: emailMaxSize
# type: 0
# unit: byte
# i18n:
# zh-CN: 最大邮件大小
# en-US: EmailMaxSize
# - field: serverInfo
# type: 1
# i18n:
# zh-CN: 服务器相关信息
# en-US: ServerInfo
# - field: heloInfo
# type: 1
# i18n:
# zh-CN: Helo日志
# en-US: HeloInfo

# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
# 采集协议, 目前支持sql, ssh, http, telnet, wmi, snmp, sdk
protocol: smtp
# Specific collection configuration when protocol is telnet protocol
# 当protocol为telnet协议时具体的采集配置
smtp:
# telnet host
# 远程登录主机
host: ^_^host^_^
# port
# 端口
port: ^_^port^_^
# timeout
# 超时时间
timeout: ^_^timeout^_^
# email
# email(helo命令所需)
email: ^_^email^_^
Loading