Spring Boot Admin2 自定义异常监控

news/2024/5/16 13:35:19/文章来源:https://blog.csdn.net/weixin_40972073/article/details/128046695

其他相关文章:

  1. Spring Boot Admin 参考指南
  2. SpringBoot Admin服务离线、不显示健康信息的问题
  3. Spring Boot Admin2 @EnableAdminServer的加载
  4. Spring Boot Admin2 AdminServerAutoConfiguration详解
  5. Spring Boot Admin2 实例状态监控详解
  6. Spring Boot Admin2 自定义JVM监控通知

有时候客户往往会先于我们发现产品的异常,经常是他们跟我们反馈,为了改变这种状况,我们需要监控服务发生的各种异常。而正好SBA2 提供了HTTP请求相关的异常统计指标。那么我们经过适当的设计就可以达到每次有异常发生的时候就发送通知,实现原理就是:查询的最新异常累计值大于原有值时,表示新发生异常

看下提醒效果:

在这里插入图片描述

同样的马上代码:

NotifierAutoConfiguration.exceptionAlarm

@Bean(initMethod = "start", destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.boot.admin.notify.exception", name = "enabled", havingValue = "true")
@ConfigurationProperties("spring.boot.admin.notify.exception")
@Lazy(false)
public ExceptionAlarm exceptionAlarm(InstanceRepository repository, AlarmMessage alarmMessage) {return new ExceptionAlarm(repository, alarmMessage);
}

ExceptionAlarm

@Slf4j
public class ExceptionAlarm {private final RestTemplate restTemplate = new RestTemplate();private Scheduler scheduler;private Disposable subscription;private InstanceRepository repository;private AlarmMessage alarmMessage;/*** 开关*/private boolean enabled = true;/*** 检测频率,秒*/private long interval = 10;/*** 排除异常*/private String exclude = "None,BizException";/*** 排除实例*/private String excludeInstances = "";/*** 提醒模版*/private final String ALARM_TPL = "服务实例【%s】,发生异常【%s】";/*** 最后一次检测时的异常次数*/private final Map<String, Map<String, Integer>> instanceCount = new HashMap<>();public ExceptionAlarm(InstanceRepository repository, AlarmMessage alarmMessage) {this.repository = repository;this.alarmMessage = alarmMessage;}private void checkFn(Long aLong) {if (!enabled) {return;}log.debug("check exception for all instances");//检查所有实例repository.findAll().filter(instance -> !excludeInstances.contains(instance.getRegistration().getName())).map(instance -> {String instanceName = instance.getRegistration().getName();List<String> exceptionList = getExceptionTag(instance);for (String exception : exceptionList) {Integer value = getValue(instance, exception);Integer lastValue = instanceCount.getOrDefault(instanceName, new HashMap<>()).get(exception);//查询的异常统计值大于原有值时,表示新发生异常if (lastValue != null && value > lastValue) {String content = String.format(ALARM_TPL, instanceName, exception);alarmMessage.sendData(content);instanceCount.get(instanceName).put(exception, value);} else {Map<String, Integer> map = instanceCount.getOrDefault(instanceName, new HashMap<>());map.put(exception, value);instanceCount.put(instanceName, map);}}return Mono.just(0d);}).subscribe();}private Integer getValue(Instance instance, String tags) {String reqUrl = instance.getRegistration().getManagementUrl() + "/metrics/http.server.requests?tag=exception:" + tags;ResponseEntity<String> responseEntity = restTemplate.getForEntity(reqUrl, String.class);String body = responseEntity.getBody();JSONObject bodyObject = JSON.parseObject(body);JSONArray measurementsArray = bodyObject.getJSONArray("measurements");if (measurementsArray != null && !measurementsArray.isEmpty()) {return measurementsArray.getJSONObject(0).getInteger("value");}return 0;}private List<String> getExceptionTag(Instance instance) {try {String reqUrl = instance.getRegistration().getManagementUrl() + "/metrics/http.server.requests";log.debug("check jvm {},uri {}", instance.getRegistration().getName(), reqUrl);ResponseEntity<String> responseEntity = restTemplate.getForEntity(reqUrl, String.class);String body = responseEntity.getBody();JSONObject bodyObject = JSON.parseObject(body);JSONArray tagsArray = bodyObject.getJSONArray("availableTags");if (tagsArray != null && !tagsArray.isEmpty()) {for (Object tag : tagsArray) {JSONObject tagObject = (JSONObject) tag;if ("exception".equals(tagObject.getString("tag"))) {List<String> valuesList = tagObject.getJSONArray("values").toJavaList(String.class);return valuesList.stream().filter(s -> !exclude.contains(s)).collect(Collectors.toList());}}}} catch (Exception ex) {log.error(ex.getMessage());}return Collections.emptyList();}public long getInterval() {return interval;}public void setInterval(long interval) {this.interval = interval;}public String getExclude() {return exclude;}public void setExclude(String exclude) {this.exclude = exclude;}public boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}public String getExcludeInstances() {return excludeInstances;}public void setExcludeInstances(String excludeInstances) {this.excludeInstances = excludeInstances;}private void start() {this.scheduler = Schedulers.newSingle("exception-check");this.subscription = Flux.interval(Duration.ofSeconds(this.interval)).subscribeOn(this.scheduler).subscribe(this::checkFn);initInstanceCount();}private void initInstanceCount() {repository.findAll().map(instance -> {String instanceName = instance.getRegistration().getName();List<String> exceptionList = getExceptionTag(instance);for (String exception : exceptionList) {Integer value = getValue(instance, exception);Map<String, Integer> map = instanceCount.getOrDefault(instanceName, new HashMap<>());map.put(exception, value);instanceCount.put(instanceName, map);}return Mono.just(0d);}).subscribe();}private void stop() {if (this.subscription != null) {this.subscription.dispose();this.subscription = null;}if (this.scheduler != null) {this.scheduler.dispose();this.scheduler = null;}}
}

其中

/*** 排除异常*/
private String exclude = "None,BizException";

该处代码用来排除不告警的异常,因为我们的很多业务异常也会被SBA2记录,此类异常不太具有参考价值,排除。

private void start() {this.scheduler = Schedulers.newSingle("exception-check");this.subscription = Flux.interval(Duration.ofSeconds(this.interval)).subscribeOn(this.scheduler).subscribe(this::checkFn);initInstanceCount();
}private void initInstanceCount() {repository.findAll().map(instance -> {String instanceName = instance.getRegistration().getName();List<String> exceptionList = getExceptionTag(instance);for (String exception : exceptionList) {Integer value = getValue(instance, exception);Map<String, Integer> map = instanceCount.getOrDefault(instanceName, new HashMap<>());map.put(exception, value);instanceCount.put(instanceName, map);}return Mono.just(0d);}).subscribe();
}

该处代码用于在SBA2启动的时候重新价值对应服务的异常到内存中,由于SBA2默认都是将异常保存在内存中,每次重启就会丢失。
其他同JVM监控,不再叙述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_36934.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GEO振弦式钢筋计的组装

&#xff08;1&#xff09;按钢筋直径选配相应的钢筋计&#xff0c;如果规格不符合&#xff0c;应选择尽量接近于结构钢筋直径 的钢筋计&#xff0c;例如&#xff1a;钢筋直径为 35mm&#xff0c;可使用 NZR-36 或 NZR-32 的钢筋计&#xff0c;此时仪器的最小 读数应进行修…

MapReduce

4.1 MapReduce概述 2003年和2004年&#xff0c;Google公司在国际会议上分别发表了两篇关于Google分布式文件系统和MapReduce的论文&#xff0c;公布了Google的GFS和MapReduce的基本原理和主要设计思想。 4.1.1 MapReduce定义 MapReduce是一个分布式运算程序的编程框架&#…

【无百度智能云与实体经济“双向奔赴”: 一场1+1>2的双赢 标题】

实体经济&#xff0c;已经成为检验科技企业潜力的试金石。 在最近的财报季中&#xff0c;各家大厂的财报里“实体经济”都是关键字眼&#xff0c;已经成为各家心照不宣的共同目的地。 当然&#xff0c;条条大路通罗马。每一家的战略思路和打法都不一样。11月22日&#xff0c;…

DOTA-PEG-麦芽糖 maltose-DOTA 麦芽糖-四氮杂环十二烷四乙酸

DOTA-PEG-麦芽糖 maltose-DOTA 麦芽糖-四氮杂环十二烷四乙酸 PEG接枝修饰麦芽糖&#xff0c;麦芽糖-聚乙二醇-四氮杂环十二烷四乙酸&#xff0c;DOTA-PEG-麦芽糖 中文名称&#xff1a;麦芽糖-四氮杂环十二烷四乙酸 英文名称&#xff1a;maltose-DOTA 别称&#xff1a;DOTA修…

HCIA 访问控制列表ACL

一、前言 ACL又称访问控制列表&#xff0c;其实这个东西在很多地方都有用&#xff0c;可能名字不太一样但原理和功能都差不太多&#xff0c;比如服务器、防火墙&#xff0c;都有类似的东西&#xff0c;功能其实也就是“过滤”掉不想收到的数据包。为什么不想收到一些数据包呢&…

The Seven Tools of Causal Inference with Reflections on Machine Learning 文章解读

目录 THE THREE LAYER CAUSAL HIERARCHY. 4 THE SEVEN TOOLS OF CAUSAL INFERENCE (OR WHAT YOU CAN DO WITH A CAUSAL MODEL THAT YOU COULD NOT DO WITHOUT?) 7 Tool 1: Encoding Causal Assumptions – Transparency and Testability. 10 Tool 2: Do-calculus and the …

深入浅出基于HLS流媒体协议视频加密的解决方案

一套简单的基于HLS流媒体协议&#xff0c;使用video.js NodeJS FFmpeg等相关技术实现的m3u8tsaes128视频加密及播放的解决方案示例。 项目简介 起初是为了将工作中已有的基于Flash的视频播放器替换为不依赖Flash的HTML5视频播放器&#xff0c;主要使用了现有的video.js开源播…

【学习笔记25】JavaScript字符串的基本认识

JavaScript字符串的基本认识一、严格模式二、字符串1、字面量2、构造函数3、包装类型三、字符集&#xff08;了解&#xff09;1、ASCII&#xff1a;128个2、GBK国标码&#xff1a;前128位ASCII&#xff0c;从129开始为汉字3、unicode(万国码)四、字符串的length与下标一、严格模…

学弟:功能测试转测试开发容易吗?

最近看到后台留言问&#xff1a;功能测试转测试开发容易吗&#xff1f; 从这个问题&#xff0c;我能读出一些信息如下&#xff1a; 不知道你从事测试工作多久了&#xff0c;可以看出您特别羡慕测试开发工程师&#xff1b;你可能一直从事功能测试工作&#xff0c;工作模式或大…

排名预测系统

排名预测系统 题目链接 题目背景&#xff1a; 本题大模拟来自真实的需求&#xff0c;即&#xff1a;综合三场网络赛的名次&#xff0c;来预计一个正式队伍在所有正式参赛队伍中的名次以此来估计自己能不能拿牌。本来只有一道题&#xff0c;即为你们看到的T5&#xff0c;经过…

HTTP响应详解

目录 一.状态码 小结&#xff08;记住&#xff09; 二.认识响应正文&#xff08;body&#xff09; 三.如何构造http请求 一.状态码 是一个数字&#xff0c;这个数字描述了当前这次请求的状态&#xff08;成功&#xff0c;失败&#xff0c;失败的原因&#xff09; http的状态…

logcat日志文件分析

3:显示时间戳日志 adb logcat -v time > d:\文件\log.txt 日志文件分析 输出的日志格式由5部分组成 1:写下日志的时间 2:优先级&#xff0c;日志优先级从低到高分以下几种 v -verbose 最低级别&#xff0c;开发调试中的一些详细信息&#xff0c;仅在开发中使用&#…

以分割栅格为例实现FME模板的方案优化

一、利用FME分割栅格 &#xff08;一&#xff09;问题的产生 对于FME使用者来说&#xff0c;利用FME完成栅格的批量分割是一件极为平常且容易的事情。只需要输入栅格和确定分割方案就可以实现利用FME对栅格数据的分割&#xff0c;再配合FME的“扇出”功能&#xff0c;就能够实…

【colab安装mmcv-full和mmclassification】

colab安装mmcv-full和mmclassification改变cuda和pytorch版本查看torch版本安装mmcv-full安装mmclassification克隆并安装mmcls切换到目录源码安装检查mmcls版本改变cuda和pytorch版本 !pip --default-timeout1000 install torch1.9.0cu111 -f https://download.pytorch.org/w…

常用辅助类

CountDownLatch 应用场景&#xff1a;1.多线程任务汇总。2.多线程任务阻塞住&#xff0c;等待发令枪响&#xff0c;一起执行。 减法计数器 每次有线程调用&#xff0c;数量-1&#xff0c;当计数器归零&#xff0c;countDownLatch.await()就会被唤醒向下执行。 import java.uti…

c语言tips-带参main函数

0.写在最前 最近因为工作需要开始重新学c语言&#xff0c;越学越发现c语言深不可测&#xff0c;当初用python轻轻松松处理的一些数据&#xff0c;但是c语言写起来却异常的复杂&#xff0c;这个板块就记录一下我的c语言复习之路 1. main函数的两种表现形式 main函数是c/cpp语言的…

Docker学习(5)—— 在Docker上安装软件

一. 安装Tomcat 1. 下载最新版 (1) 拉取Tomcat镜像 docker pull tomcat (2) 查看是否拉取到Tomcat镜像 docker images tomcat (3) 创建Tomcat容器并启动 docker run -d -p 8080:8080 tomcat 这时访问tomcat首页报404错误&#xff0c;有以下两个原因&#xff1a;①防火…

XSS绕过安全狗WAF

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XSS绕过安全狗WAF。 一、测试环境搭建 我们使用Vmware虚拟机搭建靶场环境。在Vmware虚拟机上&#xff0c;安装有PHPStudy&#xff0c;如下所示&#xff1a; 然后安装安全狗WAF&#xff0c;安全狗WAF有一系列的…

【kafka】一、kafka介绍

kafka概述 定义 kafka是一个分布式的基于发布/订阅模式的消息队列&#xff0c;主要应用于大数据实时处理领域。 消息队列 1&#xff09;解耦 允许你独立的扩展或修改两边的处理过程&#xff0c;只要确保它们遵守同样的接口约束。 2&#xff09;可恢复性 系统的一部分组件…

安装Python

搭建 Python 环境 要想能够进行 Python 开发, 就需要搭建好 Python 的环境. 需要安装的环境主要是两个部分: 1、运行环境: Python 2、开发环境: PyCharm 一、安装Python 1.1、官网下载Python 搜索引擎输入 Python 进入Python官网 1.2、找到下载页面 因为是在Windows环境…