飞书 Webhook

This commit is contained in:
徐晓伟 2024-02-22 11:26:23 +08:00
parent fe40bad984
commit 05ae3f7df5
9 changed files with 155 additions and 7 deletions

View File

@ -132,6 +132,22 @@
- [docker 镜像](https://hub.docker.com/r/xuxiaoweicomcn/nacos-sentinel)
- 飞书数据格式
```json
{
"logId": "日志ID",
"serverAddr": "Nacos地址",
"online": "是否上线",
"namespace": "命名空间",
"serviceName": "服务名称",
"ip": "服务IP",
"port": "服务端口",
"groupName": "群组名称",
"clusterName": "集群名称"
}
```
### 环境变量
| 环境变量名称 | 默认值 | 说明 |
@ -147,6 +163,7 @@
| NACOS_SENTINEL_WEBHOOK_WEIXN_URL | | 企业微信 Webhook 地址,为空时不启用 |
| NACOS_SENTINEL_WEBHOOK_WEIXN_MENTIONED_LIST | | userid的列表提醒群中的指定成员(@某个成员)@all表示提醒所有人如果开发者获取不到userid可以使用 `NACOS_SENTINEL_WEBHOOK_WEIXN_MENTIONED_MOBILE_LIST`,多个值使用英文逗号隔开 |
| NACOS_SENTINEL_WEBHOOK_WEIXN_MENTIONED_MOBILE_LIST | | 手机号列表,提醒手机号对应的群成员(@某个成员)@all表示提醒所有人多个值使用英文逗号隔开 |
| NACOS_SENTINEL_WEBHOOK_FEISHU_URL | | 飞书 Webhook 地址,为空时不启用。飞书数据格式参见上方内容 |
## [代码格式规范 spring-javaformat](https://github.com/spring-io/spring-javaformat)

View File

@ -2,9 +2,11 @@ package cn.com.xuxiaowei.nacos.sentinel.listener;
import cn.com.xuxiaowei.nacos.sentinel.entity.Discovery;
import cn.com.xuxiaowei.nacos.sentinel.properties.NacosSentinelDiscoveryProperties;
import cn.com.xuxiaowei.nacos.sentinel.properties.NacosSentinelWebhookFeishuProperties;
import cn.com.xuxiaowei.nacos.sentinel.properties.NacosSentinelWebhookWeixinProperties;
import cn.com.xuxiaowei.nacos.sentinel.repository.NacosDiscoveryRepository;
import cn.com.xuxiaowei.nacos.sentinel.utils.StringUtils;
import cn.com.xuxiaowei.nacos.sentinel.webhook.WebHookFeishu;
import cn.com.xuxiaowei.nacos.sentinel.webhook.WebHookUtils;
import cn.com.xuxiaowei.nacos.sentinel.webhook.WebHookWeixinMarkdown;
import com.alibaba.nacos.api.PropertyKeyConst;
@ -44,6 +46,8 @@ public class NacosDiscoveryListener {
private NacosSentinelWebhookWeixinProperties nacosSentinelWebhookWeixinProperties;
private NacosSentinelWebhookFeishuProperties nacosSentinelWebhookFeishuProperties;
private NacosDiscoveryRepository nacosDiscoveryRepository;
@Autowired
@ -57,6 +61,12 @@ public class NacosDiscoveryListener {
this.nacosSentinelWebhookWeixinProperties = nacosSentinelWebhookWeixinProperties;
}
@Autowired
public void setNacosSentinelWebhookFeishuProperties(
NacosSentinelWebhookFeishuProperties nacosSentinelWebhookFeishuProperties) {
this.nacosSentinelWebhookFeishuProperties = nacosSentinelWebhookFeishuProperties;
}
@Autowired
public void setNacosDiscoveryRepository(NacosDiscoveryRepository nacosDiscoveryRepository) {
this.nacosDiscoveryRepository = nacosDiscoveryRepository;
@ -220,10 +230,13 @@ public class NacosDiscoveryListener {
String serverAddr = nacosSentinelDiscoveryProperties.getServerAddr();
String namespace = nacosSentinelDiscoveryProperties.getNamespace();
String weixinWebhookUrl = nacosSentinelWebhookWeixinProperties.getUrl();
List<String> mentionedList = nacosSentinelWebhookWeixinProperties.getMentionedList();
List<String> mentionedMobileList = nacosSentinelWebhookWeixinProperties.getMentionedMobileList();
String feishuWebhookUrl = nacosSentinelWebhookFeishuProperties.getUrl();
if (!adds.isEmpty()) {
log.info("");
log.info("【{}】Nacos 上线服务: {}", subscribeLogId, serviceName);
@ -233,9 +246,11 @@ public class NacosDiscoveryListener {
int port = instance.getPort();
String clusterName = instance.getClusterName();
String groupName = StringUtils.extractAtLeft(instance.getServiceName());
log.info("【{}】Nacos 上线服务名称: {}IP: {},端口: {},群组名称: {},集群名称: {}", subscribeLogId, serviceName,
StringUtils.formatLength(ip, 15), StringUtils.formatLength(port, 5),
StringUtils.extractAtLeft(instance.getServiceName()), clusterName);
StringUtils.formatLength(ip, 15), StringUtils.formatLength(port, 5), groupName,
clusterName);
Discovery getByUnique = nacosDiscoveryRepository.getByUnique(serviceName, ip, port);
@ -250,8 +265,7 @@ public class NacosDiscoveryListener {
if (org.springframework.util.StringUtils.hasText(weixinWebhookUrl)) {
String content = String.format(
"Nacos【%s:%s】<font color=\"info\">上线服务</font>【%s】:\n服务名称: %s\nIP: %s\n端口: %s\n群组名称: %s\n集群名称: %s",
serverAddr, namespace, subscribeLogId, serviceName, ip, port,
StringUtils.extractAtLeft(instance.getServiceName()), clusterName);
serverAddr, namespace, subscribeLogId, serviceName, ip, port, groupName, clusterName);
WebHookWeixinMarkdown webHook = new WebHookWeixinMarkdown(content);
webHook.setMentionedList(mentionedList);
webHook.setMentionedMobileList(mentionedMobileList);
@ -264,6 +278,26 @@ public class NacosDiscoveryListener {
}
}
if (org.springframework.util.StringUtils.hasText(feishuWebhookUrl)) {
WebHookFeishu webHook = new WebHookFeishu().setLogId(subscribeLogId)
.setServerAddr(serverAddr)
.setOnline("上线")
.setNamespace(namespace)
.setServiceName(serviceName)
.setIp(ip)
.setPort(port + "")
.setGroupName(groupName)
.setClusterName(clusterName);
try {
Map<String, Object> post = WebHookUtils.post(feishuWebhookUrl, webHook);
log.info("【{}】发送飞书 Webhook 响应:{}", subscribeLogId, post);
}
catch (Exception e) {
log.error(String.format("【%s】发送飞书 Webhook 异常:", subscribeLogId), e);
}
}
}
}
@ -294,6 +328,25 @@ public class NacosDiscoveryListener {
log.error(String.format("【%s】发送企业微信 Webhook 异常:", subscribeLogId), e);
}
}
if (org.springframework.util.StringUtils.hasText(feishuWebhookUrl)) {
WebHookFeishu webHook = new WebHookFeishu().setLogId(subscribeLogId)
.setServerAddr(serverAddr)
.setOnline("下线")
.setNamespace(namespace)
.setServiceName(serviceName)
.setIp(ip)
.setPort(port + "");
try {
Map<String, Object> post = WebHookUtils.post(feishuWebhookUrl, webHook);
log.info("【{}】发送飞书 Webhook 响应:{}", subscribeLogId, post);
}
catch (Exception e) {
log.error(String.format("【%s】发送飞书 Webhook 异常:", subscribeLogId), e);
}
}
}
}

View File

@ -0,0 +1,20 @@
package cn.com.xuxiaowei.nacos.sentinel.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Nacos 监控 飞书 Webhook 配置
*
* @author xuxiaowei
* @since 0.0.1
*/
@Data
@Component
@ConfigurationProperties("nacos.sentinel.webhook.feishu")
public class NacosSentinelWebhookFeishuProperties {
private String url;
}

View File

@ -0,0 +1,9 @@
package cn.com.xuxiaowei.nacos.sentinel.webhook;
/**
* @author xuxiaowei
* @since 0.0.1
*/
public interface WebHook {
}

View File

@ -0,0 +1,32 @@
package cn.com.xuxiaowei.nacos.sentinel.webhook;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author xuxiaowei
* @since 0.0.1
*/
@Data
@Accessors(chain = true)
public class WebHookFeishu implements WebHook {
private String logId;
private String serverAddr;
private String online;
private String namespace;
private String serviceName;
private String ip;
private String port;
private String groupName;
private String clusterName;
}

View File

@ -0,0 +1,11 @@
{
"logId": "日志ID",
"serverAddr": "Nacos地址",
"online": "是否上线",
"namespace": "命名空间",
"serviceName": "服务名称",
"ip": "服务IP",
"port": "服务端口",
"groupName": "群组名称",
"clusterName": "集群名称"
}

View File

@ -15,14 +15,14 @@ import java.util.Map;
@Slf4j
public class WebHookUtils {
public static Map<String, Object> post(String url, WebHookWeixin webHook) {
public static Map<String, Object> post(String url, WebHook webHook) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WebHookWeixin> httpEntity = new HttpEntity<>(webHook, httpHeaders);
HttpEntity<WebHook> httpEntity = new HttpEntity<>(webHook, httpHeaders);
return restTemplate.postForObject(url, httpEntity, Map.class);
}

View File

@ -4,6 +4,6 @@ package cn.com.xuxiaowei.nacos.sentinel.webhook;
* @author xuxiaowei
* @since 0.0.1
*/
public interface WebHookWeixin {
public interface WebHookWeixin extends WebHook{
}

View File

@ -19,6 +19,12 @@ nacos:
mentioned-list: ${NACOS_SENTINEL_WEBHOOK_WEIXN_MENTIONED_LIST:}
mentioned-mobile-list: ${NACOS_SENTINEL_WEBHOOK_WEIXN_MENTIONED_MOBILE_LIST:}
---
nacos:
sentinel:
webhook:
feishu:
url: ${NACOS_SENTINEL_WEBHOOK_FEISHU_URL:}
---
logging:
level:
org.springframework.web: debug