# simple-prometheus **Repository Path**: Goslee/simple-prometheus ## Basic Information - **Project Name**: simple-prometheus - **Description**: 解决方案:轻量级监控告警(开源项目)异常监听,飞书推送,钉钉推送,全局埋点,轻量化 - **Primary Language**: Java - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: https://gitee.com/Goslee/simple-prometheus - **GVP Project**: No ## Statistics - **Stars**: 11 - **Forks**: 2 - **Created**: 2024-09-05 - **Last Updated**: 2025-09-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: SpringBoot, 异常监听, 消息推送, 异常告警 ## README
Logo
## simple-prometheus
#### 一个轻量级的异常监控(简单点,再简单点)

🍬Make it simple, make it simple.
star

------------------------------------------------------------------------------- ### 📚背景概述 针对小项目做的一个异常监控,主要是为了方便开发人员快速定位问题,减少沟通成本,提高开发效率。主要围绕着轻量化,快速上手,开箱即用的理念,让开发者或者关心此类问题的人,尽可能减少部分成本去搭建大规模的中间件,如果需要搭建很大规模的中间件和服务,会浪费掉时间和精力以及资金方面的成本,此工具就是让小型企业减少如上所述的成本问题而建立。 ### 🧬系统需求 ![jdk版本](https://img.shields.io/badge/java-8%2B-red.svg?style=for-the-badge&logo=appveyor) ![maven版本](https://img.shields.io/badge/spring%20cloud-2020.0.1%2B-red.svg?style=for-the-badge&logo=appveyor) ![spring boot](https://img.shields.io/badge/spring%20boot-2.4.2%2B-red.svg?style=for-the-badge&logo=appveyor) ### 📐当前版本 ![目前工程版本](https://img.shields.io/badge/version-1.0.1-green.svg?style=for-the-badge&logo=appveyor) ### 🍊实现方式 #### 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 io.gitee.goslee spring-boot-starter-simple-prometheus 1.0.1 ``` - 如果启动失败尝试添加如下依赖(后续我会修复) ```txt net.jodah expiringmap 0.5.8 true ``` - 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/xxx" code: ",200000,200001,200002,200003," developer: # 开发消息群飞书的 webhook - url: "https://open.feishu.cn/open-apis/bot/v2/hook/xxx" code: ",500," ``` 钉钉示例 ```yaml #监控 sprometheus: default: "dingding" dingding: #是否开启异常告警 enabled: true #需要包含的trace包路径 includedTracePackage: - "com.gosling" - "com.mysql" - "java.sql.SQLException" - "java.net" #钉钉群消息 business: # 业务消息群1 钉钉 - url: "https://oapi.dingtalk.com/robot/send?access_token=3c36" code: ",200000,200001,200002,200003," secret: "SEC9a6b2202a0b92847fd7098630d20b4" developer: # 开发消息群钉钉的 - url: "https://oapi.dingtalk.com/robot/send?access_token=3c36" code: ",500," secret: "SEC9a6b2202a0b92847fd7098630d20b4" ``` - 配置说明 | 名称 | 参数类型 | 说明 | 必须配置 | |------------------------|---------|-----------------------------|------| | default | string | 默认发送至那个配置下 | 是 | | enabled | boolean | 是否开启异常告警 | 是 | | included_trace_package | string | 需要包含的trace包路径 | 是 | | url | string | 业务/开发消息群集合 飞书(或其他)的 webhook | 是 | | code | string | 业务码 | 是 | | secret | string | 钉钉的加签串 | 否-钉钉必填 | ### 🍺代码层面使用(多种方式) #### 方式一: ```java //在报错的位置编写此代码 SPrometheusUtil.insert("异常测试", SPrometheusTitleEnum.OTHER); ``` #### 方式二: ```java //在报错的位置编写此代码 SPrometheusUtil.insert("异常测试", SPrometheusTitleEnum.OTHER, JSONObject.toJSONString(req)); ``` #### 方式三: ```java //在报错的位置编写此代码 Exp exp = new Exp(); exp.setMsg("test...已经收到监听事件"); exp.setUri("/admin/test1"); exp.setSendChannel(SendChannel.FEISHU); exp.setAtAll(SConstants.YES); exp.setReqData(JSONObject.toJSONString(req)); exp.setTitleEnum(SPrometheusTitleEnum.OTHER); SPrometheusUtil.insert(exp); ``` #### 方式四: ```java Exp exp = new Exp(); //... exp.setMsg(originMsg); //如果你想要保留你发送消息的原格式,不做任何更改 //例如你需要发送飞书的表格,针对飞书文档编写的msg消息或者你自己想要保留的格式,那么可以用此方式 SPrometheusUtil.insertOrg(exp); ``` > Exp实体类说明 ```java @Data @AllArgsConstructor @NoArgsConstructor public class Exp { @Msg(msg = "监控分类") private SPrometheusTitleEnum titleEnum = SPrometheusTitleEnum.OTHER; @Msg(msg = "接口地址") private String uri; @Msg(msg = "错误信息") private String msg = SConstants.DEFAULT_MSG; @Msg(msg = "请求参数") private String reqData; @Msg(msg = "是否@所有人 @all") private Integer atAll = SConstants.NO; @Msg(msg = "推送媒介 1:飞书(默认) 2:钉钉 3:邮件") private String sendChannel = SendChannel.FEISHU; } ``` #### 方式五:手动抛出异常 SPrometheusException ```java throw new SPrometheusException(SPrometheusTitleEnum.OTHER, "用户信息为空"); ``` #### 方式六:异常监听注解 @SPrometheus ```java @SPrometheus(title = SPrometheusTitleEnum.OTHER, uri = "admin/test1", scene = Scene.BUSINESS) public void test(String id) { if (StrUtil.isBlank(id)){ System.out.println("主键ID为空"); throw new NullPointerException("主键ID为空"); } } ``` #### 可预知的异常 如:参数校验异常,业务流程中提前被定义的异常等 这种异常的等级并不是特别高,有些需要业务人员参与关注,而大多数情况下,业务人员不需要关注、开发人员更不需要去关注 所以这种异常需要控制通知的频率以及通知的范围,避免群消息过于繁多,导致在关键时候错过想要关注的重要消息 #### 无法预估的异常 开发的未知异常则无需做指定位置和提前定义,如:空指针异常,类型转换错误,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); } ``` ### 🍐框架结构 ![img.png](src/main/resources/static/img_1.png) ### 📖后续 TODO pmo - 完善email通知 - 完善钉钉通知--已完成 - 完善QQ通知 - 完善微信通知 - 完善NACOS监听 - 完善通知到个人 ### ⭐Star simple-prometheus⭐ ### 🐞提供bug反馈或建议 1、在gitee上提交issues 2、扫描下方二维码,关注公众号,发送消息,我会第一时间回复 ![img.png](src/main/resources/static/img.png) 谢谢您宝贵的star O(∩_∩)O~~