Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
lishuai committed Nov 3, 2023
2 parents ff7bcdb + 60bae91 commit aaae50e
Show file tree
Hide file tree
Showing 18 changed files with 852 additions and 3 deletions.
17 changes: 14 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<url>https://github.com/JavaFamilyClub/javafamily-service</url>
<description>javafamily tools service</description>
<description>javafamily common service</description>

<properties>
<swagger.parser.version>1.0.50</swagger.parser.version>
<javafamily.parent.version>2.3.2-SNAPSHOT</javafamily.parent.version>
</properties>

<modules>
<module>javafamily-swagger2word</module>
<module>prometheus-webhook-feishu</module>
<module>xxl-job-admin-mysql</module>
<module>prometheus-webhook-dingtalk</module>
<module>prometheus-webhook-qywechat</module>

<module>javafamily-swagger2word</module>
<module>xxl-job-admin-mysql</module>
</modules>

<distributionManagement>
Expand Down Expand Up @@ -55,6 +58,14 @@

<dependencyManagement>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>club.javafamily</groupId>-->
<!-- <artifactId>javafamily-parent</artifactId>-->
<!-- <version>${javafamily.parent.version}</version>-->
<!-- <type>pom</type>-->
<!-- <scope>import</scope>-->
<!-- </dependency>-->

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-parser</artifactId>
Expand Down
30 changes: 30 additions & 0 deletions prometheus-webhook-qywechat/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Docker image
# VERSION 0.0.1
# Author: Jack Li
# base image using java8
#FROM openjdk:8-jre-alpine
FROM openjdk:8

LABEL maintainer="JavaFamily javafamily.club@outlook.com"
LABEL author="Jack Li"

# temp folder. link locale:/var/lib/docker to container:/tmp
#VOLUME /tmp

# add jar to container and renaming to app.jar
ARG JAR_FILE
ADD ./target/${JAR_FILE} app.jar

ENV JAVA_OPTS="\
# -Xms4g \
# -Xmx4g \
"

ENV ACTIVE_PROFILE prod

ENV QYWECHAT_TOKEN ""

# run command
ENTRYPOINT java ${JAVA_OPTS} \
-Djava.security.egd=file:/dev/./urandom \
-jar /app.jar --spring.profiles.active=${ACTIVE_PROFILE}
119 changes: 119 additions & 0 deletions prometheus-webhook-qywechat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Prometheus 企业微信 AlertManager

> 基于企业微信 WebHook 机器人的 Alert Manager 的报警实现
## 1. 使用

``` xml
docker run -d --name prom-alert-feishu -p 9095:8080 --restart=always \
-e QYWECHAT_TOKEN=xxxx \
javafamily/prometheus-webhook-qywechat:2.3.2-SNAPSHOT
```



> 其中 `QYWECHAT_TOKEN`环境变量为可选参数, 为企业微信 webhook 地址或 URL 最后一部分 TOKEN,即 `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${QYWECHAT_TOKEN}`
>
> * 如果只对一个企业微信群通知,可以添加该环境变量即可;
> * 如果需要对多个企业微信群通知, 需要在 `Prometheus` 报警 rule 的 `annotations`中通过指定 `token` 参数为不同企业微信群通知;


## 2. Api

> 通知的内容通过 Prometheus 的报警规则配置 `annotations/template` 指定,template 支持 `${xxx}` 占位, XXX 取自 `annotations/xxx` 配置。也可以通过 `annotations/content` 直接指定,不做任何处理直接展示。
>
> **需注意, 企业微信通知如果是关键字通知的话,通知内容中需要包含关键字!**
### 2.1 文本通知

`${basePath}/alert/text`

> 文本通知只需要指定 `template` 或者 `content`定义模板内容即可
![img.png](img/README//img.png)

### 2.2 Markdown 通知

`${basePath}/alert/mk`

> 企业微信的 Markdown 通知只需要指定 `template` 或者 `content`定义模板内容即可
![image-20230806184852558](img\README\image-20230806184852558.png)

### 2.3 News 通知

`${basePath}/alert/news`

> 企业微信的 news 通知可以指定标题(`titleTemplate`/`title`), 通知内容(`template/content`), 主题图片(`pic`), 跳转链接(`link`)
![image-20230806192007510](img/README/image-20230806192007510.png)


## 3. 配置报警 rule

``` xml
# 相关的规则设置定义在一个group下。在每一个group中我们可以定义多个告警规则(rule)
groups:
# 组名。报警规则组名称
- name: 内存预警
rules:
- alert: 内存使用率预警
# expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。
expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes+node_memory_Buffers_bytes+node_memory_Cached_bytes )) / node_memory_MemTotal_bytes * 100 > 98
# for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending。
for: 1m # for语句会使 Prometheus 服务等待指定的时间, 然后执行查询表达式。(for 表示告警持续的时长,若持续时长小于该时间就不发给alertmanager了,大于该时间再发。for的值不要小于prometheus中的scrape_interval,例如scrape_interval为30s,for为15s,如果触发告警规则,则再经过for时长后也一定会告警,这是因为最新的度量指标还没有拉取,在15s时仍会用原来值进行计算。另外,要注意的是只有在第一次触发告警时才会等待(for)时长。)
# labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。
labels:
# severity: 指定告警级别。有三种等级,分别为 warning, critical 和 emergency 。严重等级依次递增。
severity: critical
# annotations: 附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager。
annotations:
title: "内存使用率预警"
serviceName: "{{ $labels.serviceName }}"
instance: "{{ $labels.instance }}"
value: "{{ $value }}"
pic: "https://pic.fonthaha.com/fonthaha/file/2022/01/27/bb1ff4d2a42b2329910686ab41928afe.png"
link: "http://124.223.75.119:92/prometheus/targets"
# 通过 template 指定通知内容模板
template: "**${serviceName}**(${instance}) 内存使用率已经超过阈值 **98%**, 请及时处理!\n当前值: ${value}%"
# 【可选】通过 token 指定通知到不同企业微信群
token: "{{ $labels.token }}"

- name: 磁盘预警
rules:
- alert: 磁盘使用率预警
expr: (node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 > 90
for: 1m
labels:
severity: critical
annotations:
title: "磁盘使用率预警"
serviceName: "{{ $labels.serviceName }}"
instance: "{{ $labels.instance }}"
mountpoint: "{{ $labels.mountpoint }}"
value: "{{ $value }}"
pic: "https://pic.fonthaha.com/fonthaha/file/2022/01/27/bb1ff4d2a42b2329910686ab41928afe.png"
link: "http://124.223.75.119:92/prometheus/targets"
template: "**${serviceName}**(${instance}) 服务器磁盘设备使用率超过 **90%**, 请及时处理!\n挂载点: ${mountpoint}\n当前值: ${value}%!"
token: "{{ $labels.token }}"

- name: 实例存活报警
rules:
- alert: 实例存活报警
expr: up == 0
for: 30s
labels:
severity: emergency
annotations:
title: "节点宕机报警"
serviceName: "{{ $labels.serviceName }}"
instance: "{{ $labels.instance }}"
pic: "https://pic.fonthaha.com/fonthaha/file/2022/01/27/bb1ff4d2a42b2329910686ab41928afe.png"
link: "http://124.223.75.119:92/prometheus/targets"
template: "节点 **${serviceName}**(${instance}) 断联, 请及时处理!"
token: "{{ $labels.token }}"
```



Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added prometheus-webhook-qywechat/img/README/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
124 changes: 124 additions & 0 deletions prometheus-webhook-qywechat/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>javafamily-service</artifactId>
<groupId>club.javafamily</groupId>
<version>2.3.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>prometheus-webhook-qywechat</artifactId>

<properties>
<DOCKER_ACCOUNT>account</DOCKER_ACCOUNT>
<DOCKER_PWD>pwd</DOCKER_PWD>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>club.javafamily</groupId>
<artifactId>qywechat-notification-spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>club.javafamily</groupId>
<artifactId>javafamily-utils-core</artifactId>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<executions>
<execution>
<id>default</id>
<phase>verify</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<!--镜像仓库地址 -->
<repository>javafamily/${project.artifactId}</repository>
<!--镜像tag -->
<tag>${project.version}</tag>
<!--镜像仓库用户名和密码 -->
<username>${DOCKER_ACCOUNT}</username>
<password>${DOCKER_PWD}</password>

<!--自定义构建参数,可传递到Dockerfile文件中 -->
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>

<noCache>true</noCache>
<dockerfile>${basedir}/Dockerfile</dockerfile>
<contextDirectory>${basedir}</contextDirectory>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package club.javafamily.prom;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.TimeZone;

/**
* @author Jack Li
* @date 2022/7/17 下午4:15
* @description
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));

SpringApplication.run(Application.class, args);

System.out.println("AlertManager 企业微信通知处理器启动成功!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package club.javafamily.prom.conf;

import club.javafamily.nf.properties.QyWechatProperties;
import club.javafamily.utils.Tool;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
* @author Jack Li
* @date 2023/3/25 下午11:34
* @description
*/
@Component
public class QyWechatConfigListener implements ApplicationListener<ApplicationStartedEvent> {

private final QyWechatProperties properties;

public QyWechatConfigListener(QyWechatProperties properties) {
this.properties = properties;
}

@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
fixHookUrl(properties);
}

public static void fixHookUrl(QyWechatProperties properties) {
if(StringUtils.hasText(properties.getHookUrl())
&& !(properties.getHookUrl().startsWith("http://")
|| properties.getHookUrl().startsWith("https://")))
{
properties.setHookUrl("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key="
+ properties.getHookUrl());
}
}
}
Loading

0 comments on commit aaae50e

Please sign in to comment.