# simple-prometheus
**Repository Path**: kevin_zhan/simple-prometheus
## Basic Information
- **Project Name**: simple-prometheus
- **Description**: 轻量级监控告警
- **Primary Language**: Unknown
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2024-09-06
- **Last Updated**: 2024-09-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 🛠️simple-prometheus
#### 一个轻量级的异常监控(简单点,再简单点)
🍬Make it simple, make it simple.
-------------------------------------------------------------------------------
### 📚背景概述
针对小项目做的一个异常监控,主要是为了方便开发人员快速定位问题,减少沟通成本,提高开发效率。主要围绕着轻量化,快速上手,开箱即用的理念,让开发者或者关心此类问题的人,尽可能减少部分成本去搭建大规模的中间件,如果需要搭建很大规模的中间件和服务,会浪费掉时间和精力以及资金方面的成本,此工具就是让小型企业减少如上所述的成本问题而建立。
### 🧬系统需求
  
### 📐当前版本

### 🍊实现方式
#### 1、基于spring的aop方式实现监控,发送消息用event监听发布订阅
> 针对单机来说具有很好的性能,分布式部署建议将event替换为MQ
1. [x] 环绕切面实现拦截异常,新创建一个异常类型,主要用于异常推送监控
切面的拦截与日志的拦截规则一致,分别为【RequestMapping、GetMapping、PostMapping】,方式为环绕通知,不影响原功能使用增强型方式。
2. [x] 如果是系统异常未被指定(Exception)则发送至开发群
3. [x] 如果是指定监控异常(SPrometheusException)则发送至相关业务人员群
4. [x] 如果是非指定监控异常则无需处理,视为普通业务异常
5. [x] 如果不想抛异常,只想在指定位置发送一条消息,则使用对外提供的工具类即可
#### 2、代码报错位置查找设计
异常信息是此功能的核心部分,那么就会涉及到如何能准确的拿到我们需要的异常信息以及堆栈,其实除了异常信息描述外,堆栈信息才是找到问题的关键, 由于栈信息有很大部分我们是不需要关注的,我们只需要关注业务代码报错部分即可,再者其是先进后出,那么说明抛异常的最终位置在最外层,那么第一个筛选后的栈信息就是最终业务报错的位置
### 🐞异常通知的具体内容
服务名称、请求地址、接口描述、异常信息、异常追踪、错误码、异常定位、链路id、异常时间、接口耗时、请求IP、请求参数
### 👉快速上手
- 在需要使用的模块引入pom依赖
> 后续添加
```txt
com.goslee
spring-boot-starter-simple-prometheus
1.0.0
```
- application.yml中做如下的配置
```yaml
#监控
sprometheus:
default: "feishu"
feishu:
#是否开启异常告警
enabled: true
#需要包含的trace包路径
includedTracePackage:
- "com.gosling"
- "com.mysql"
- "java.sql.SQLException"
- "java.net"
#飞书群消息
business:
# 业务消息群1 飞书的 webhook
- url: "https://open.feishu.cn/open-apis/bot/v2/hook/7765e2d4-bb62-441d-ae5d-d3c495c2115b"
code: ",200000,200001,200002,200003,"
developer:
# 开发消息群飞书的 webhook
- url: "https://open.feishu.cn/open-apis/bot/v2/hook/7765e2d4-bb62-441d-ae5d-d3c495c2115b"
code: ",500,"
```
- 配置说明
| 名称 | 参数类型 | 说明 | 必须配置 |
|------------------------|---------|-----------------------------|------|
| default | string | | 是 |
| enabled | boolean | 是否开启异常告警 | 是 |
| included_trace_package | string | 需要包含的trace包路径 | 是 |
| url | string | 业务/开发消息群集合 飞书(或其他)的 webhook | 是 |
| code | string | 业务码 | 是 |
### 🍺代码层面使用(三种方式)
- 方式一:
```java
//在报错的位置编写此代码
SPrometheusUtil.insert(500,"异常测试");
```
- 方式二:
```java
//在报错的位置编写此代码
SPrometheusUtil.insert(500,"异常测试",JSONObject.toJSONString(req));
```
- 方式三:
```java
//在报错的位置编写此代码
Exp exp = new Exp();
exp.setCode(500);
exp.setMsg("异常测试");
SPrometheusUtil.insert(exp);
```
业务异常需要提前做定义
可预知的异常,如:参数校验异常,业务流程中提前被定义的异常等
这种异常的等级并不是特别高,有些需要业务人员参与关注,而大多数情况下,业务人员不需要关注、开发人员更不需要去关注
所以这种异常需要控制通知的频率以及通知的范围,避免群消息过于繁多,导致在关键时候找不到想要关注的重要消息
- 需要手动在类上添加 @Tag(name = "xxx")注解
- 在方法上添加 @Operation(summary = "xxx")注解
- 然后修改抛出的异常为 PrometheusException 例如 throw new PrometheusException("签章异常...");
开发的未知异常则无需做指定位置和提前定义
无法预估的异常,如:空指针异常,类型转换错误,sql执行异常,超时等
如果出现这种情况,那么这种异常需要及时处理,异常的等级也是最高的P0级别
这种异常将会直接发送至飞书开发群
### 📦实际效果
> 当系统出现了一个业务异常后,那么就会有如下飞书通知
创建一个异常测试
```java
@PostMapping("/test/test")
@Operation(summary = "APP[风控系统回调发起支付]")
public void prepayment(@Valid @RequestBody LoanOrderQueryVO vo) {
if (1 == 1) {
throw new PrometheusException("空指针");
}
}
```
飞书收到群消息
```textmate
服务名称:gosling-server
请求地址:/app-api/test/test
接口描述:其它|系统异常
异常信息:请求参数缺失:id
异常追踪:com.gosling.framework.web.core.handler.GlobalExceptionHandler.missingServletRequestParameterExceptionHandler(GlobalExceptionHandler.java:110)
错误码:100000
异常定位:com.gosling.framework.web.core.handler.GlobalExceptionHandler.missingServletRequestParameterExceptionHandler(GlobalExceptionHandler.java:110)
链路id:94bb8b920be3401e9e0474224c30939e
异常时间:2024-09-06 11:05:15
接口耗时:1.0091 秒
请求IP:192.168.1.1
active:test
请求参数:{"id":""}
```
### 🚽全局异常处使用(可选)
如果想要通知更全面,可以选择
```java
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public BaseResult> missingServletRequestParameterExceptionHandler(HttpServletRequest request, MissingServletRequestParameterException ex) {
log.error("全局异常处理:参数传参异常", ex);
String message = String.format("请求参数缺失:%s", ex.getParameterName());
Exp exp = new Exp();
exp.setUri(request.getRequestURI());
exp.setMsg(message);
exp.setReqData(getParams(request));
exp.setTitleEnum(PrometheusTitleEnum.OTHER);
PrometheusUtil.insert(repayReq);
return BaseResult.error(message);
}
```
### 🍐框架结构

### 🐞提供bug反馈或建议
1、在gitee上提交issues
2、扫描下方二维码,关注公众号,发送消息,我会第一时间回复

### ⭐Star simple-prometheus⭐
O(∩_∩)O~~