在SpringBoot中自定义指标并使用Prometheus监控报警

公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享

在10 分钟教你使用Prometheus监控Spring Boot工程中介绍了如何使用Prometheus监控Spring Boot提供的默认指标,这篇介绍如何自定义业务指标,并使用Prometheus进行监控并报警,同时在 Grafana 进行展现

示例介绍

我们模拟一个账务系统,主要功能有:充值与提现,其中会定义5 个业务指标,如下

  • 充值次数
  • 充值金额
  • 提现次数
  • 提现金额
  • 余额

针对以上5 业务指标,会使用prometheus的三种Metrics类型,如下

  1. Counter:只增不减的计数器,用作定义充值次数提现次数

  2. Gauge:可增可减的仪表盘,侧重于反应系统的当前状态,用作定义余额

  3. Summary:用于记录某些东西的平均大小,也可以计算总和,用作定义充值金额提现金额

最终我们对以上指标进行 grafana 进行展现,同时对余额小于500 进行告警通知,效果如下

监控与验证

Spring Boot 工程配置
  1. 添加 maven 依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
  1. 在application.properties,开启监控的端点
#监控的端点
management.endpoints.web.exposure.include=*
#应用程序名称,在prometheus 上会显示
management.metrics.tags.application=${spring.application.name}
#tomcat 指标需要开启
server.tomcat.mbeanregistry.enabled=true
  1. 编写业务代码,提供体现和充值方法,并在init方法中定义五个业务指标,使用了三种Metrics类型
@Service
@Slf4j
public class AccountServiceImpl implements IAccountService {
    @Autowired
    private MeterRegistry registry;
    //入金笔数
    private Counter depositCounter; 
    // 出金笔数
    private Counter withdrawCounter; 
   //入金金额
    private DistributionSummary depositAmountSummary;
   // 出金金额
    private DistributionSummary withdrawAmountSummary; 
   //余额
    private BigDecimal balance = new BigDecimal(1000);

    @PostConstruct
    private void init() {
        depositCounter = registry.counter("deposit_counter", "currency", "btc");
        withdrawCounter = registry.counter("withdraw_counter", "currency", "btc");
        depositAmountSummary = registry.summary("deposit_amount", "currency", "btc");
        withdrawAmountSummary = registry.summary("withdraw_amount", "currency", "btc");
        Gauge.builder("balanceGauge", () -> balance)
                .tags("currency", "btc")
                .description("余额")
                .register(registry);
    }


    @Override
    // 充值操作
    public void depositOrder(BigDecimal amount) {
        log.info("depositOrder amount:{}", amount);
        try {
            //余额增加
            balance = balance.add(amount);
            //充值笔数埋点
            depositCounter.increment();
            //充值金额埋点
            depositAmountSummary.record(amount.doubleValue());

        } catch (Exception e) {
            log.info("depositOrder error", e);
        } finally {
            log.info("depositOrder result:{}", amount);
        }
    }

    @Override
    //提现操作
    public void withdrawOrder(BigDecimal amount) {
        log.info(" withdrawOrder amount:{}", amount);
        try {
            if (balance.subtract(amount).compareTo(BigDecimal.ZERO) < 0) {
                throw new Exception("提现金额不足,提现失败");
            }
            //余额减少
            balance = balance.subtract(amount);
            // 提现笔数埋点数据
            withdrawCounter.increment();
            // 提现金额埋点
            withdrawAmountSummary.record(amount.doubleValue());
        } catch (Exception e) {
            log.info("withdrawOrder error", e);
        } finally {
            log.info("withdrawOrder result:{}", amount);
        }
    }

}

  1. Controller 方法,定义了充值提现接口
@RestController
@RequestMapping(ControllerConstants.PATH_PREFIX + "/account")
public class AccountController {

    @Autowired
    IAccountService accountService;

    /**
     * 充值
     */
    @RequestMapping(value = "/deposit", method = RequestMethod.GET)
    public void deposit(@RequestParam("amount") BigDecimal amount) {
        accountService.depositOrder(amount);
    }

    /**
     * 提现
     */
    @RequestMapping(value = "/withdraw", method = RequestMethod.GET)
    public void withdraw(@RequestParam("amount") BigDecimal amount) {
        accountService.withdrawOrder(amount);
    }

}
  1. 启动服务查看,访问actuator/prometheus接口,如果能查询以下指标则配置成功

    ##充值笔数
    deposit_counter_total
    ## 充值总金额
    deposit_amount_sum
    ##提现笔数
    withdraw_counter_total
    ##提现总金额
    withdraw_amount_sum
    ## 余额
    balanceGauge
    

Promethues 配置
  1. prometheus.yml文件中进行配置业务系统采集点,5s 拉取一次指标,由于prometheus server 部署在docker 中,所以访问主机IP 用host.docker.internal

    #业务系统监控          
      - job_name: 'SpringBoot'
        # Override the global default and
        scrape_interval: 5s
        metrics_path: '/actuator/prometheus'
        static_configs:
          - targets: ['host.docker.internal:8080']       
    

  1. 告警规则配置,在容器启动时用主机的/data/prometheus目录映射到容器的/prometheus目录,因此在主机/data/prometheus/目录创建rules文件夹,并创建告警文件business-alert.rules,这里告警对余额小于 500 则进行告警

    groups:
    - name: businessAlert
      rules:
      - alert: balanceAlert
        expr: balanceGauge{application="backend"} < 500
        for: 20s
        labels:
          severity: page
          team: g2park
        annotations:
          summary: "{{ $labels.currency }} balance is insufficient "
          description: "{{ $labels.currency }} balance : {{ $value }}"
    
  2. 启动Prometheus,进行验证,查询采集目标,已生效

    查询充值次数,已采集

    点击Alters,可以看到业务告警已经生效

AlterManager配置
  1. /data/prometheus/alertmanager目录下,新增告警模板notify-template.tmpl,此目录映射到altermanager 的/etc/alertmanager目录,模板包含告警和自愈两部分,2006-01-02 15:04:05是go语言的日志格式,固定值,加28800e9表示转换为东八区时间,即北京时间

    {{ define "test.html" }} 
    {{- if gt (len .Alerts.Firing) 0 -}}
    {{ range .Alerts }}
    <h1 align="left" style="color:red;">告警</h1>
    <pre>
    告警级别: {{ .Labels.severity }} 级 <br>
    告警类型: {{ .Labels.alertname }} <br>
    故障主机: {{ .Labels.instance }} <br>
    告警主题: {{ .Annotations.summary }} <br>
    告警详情: {{ .Annotations.description }} <br>
    告警时间:{{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}<br>  
    </pre>
    {{ end }}
    {{ end }}
    {{- if gt (len .Alerts.Resolved) 0 -}}
    {{ range .Alerts }}
    <h1 align="left" style="color:green;">恢复</h1>
    <pre>
    告警名称:{{ .Labels.alertname }}<br>
    告警级别:{{ .Labels.severity }}<br>
    告警机器:{{ .Labels.instance }}<br>
    告警主题:{{ .Annotations.summary }}<br>
    告警主题:{{ .Annotations.description }}<br>
    告警时间:{{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}<br> 
    恢复时间:{{ (.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}<br> 
    </pre>
    {{- end }}
    {{- end }}
    {{- end }}
    
  2. 修改alertmanager.yml为以下内容,替换对应账号即可

    global:
      smtp_smarthost: smtp.qq.com:465
      smtp_from: 9238223@qq.com
      smtp_auth_username: 9238223@qq.com
      smtp_auth_identity: 9238223@qq.com
      smtp_auth_password: 123
      smtp_require_tls: false
    templates: #添加模板
      - '/etc/alertmanager/notify-template.tmpl'   #指定路径    
    route:
      group_by: ['alertname']
      receiver: 'default-receiver'
      group_wait: 30s
      group_interval: 5m
      repeat_interval: 1h
    receivers:
      - name: default-receiver
        email_configs:
          - to: abc123@foxmail.com
            html: '{{ template "test.html" . }}'
            send_resolved: true
            headers: { Subject: "系统监控告警{{- if gt (len .Alerts.Resolved) 0 -}}恢复{{ end }}" }  
    

    global: 这是一个全局配置部分,用于配置全局的Alertmanager设置。

    • smtp_smarthost: 这是SMTP服务器的地址和端口,用于发送邮件通知。
    • smtp_from: 这是邮件发送方的邮件地址,即发送邮件的地址。

    route: 用于配置警报的路由规则。

    • group_by: ['alertname']: 这是一个标签列表,用于按照警报名称(alertname)进行分组。
    • receiver: 'default-receiver': 这是指定默认接收者的名称,即接收警报通知的收件人。
    • group_wait: 30s: 在发送警报通知前等待的时间,以便将相同的警报分组在一起。
    • group_interval: 5m: 这是发送同一组警报通知之间的最小时间间隔。
    • repeat_interval: 1h: 这是在重复发送未解决的警报通知之前等待的时间间隔。

    receivers: 接收者部分,用于配置接收告警通知的收件人。

    • name: default-receiver: 这是默认接收者的名称。

    • email_configs: 用于指定接收邮件通知的收件人和其他相关设置。

      • to: abc123@foxmail.com: 这是收件人的邮件地址,即接收警报通知的邮箱地址。

      • send_resolved: true: 这是一个布尔值,指示是否发送已解决的警报通知。在这个例子中,设置为true,表示发送已解决的警报通知。

  3. 启动Altermanager,进行验证

    docker start alertmanager
    

    访问stauts,如果出现以下结果则成功

  4. 告警验证,系统默认余额为1000,调用backend/account/withdraw提现接口,使余额降至500,进行报警

​ 等待20s 左右,prometheus 收到报警会推送至Altermanager

Altermanager则会根据我们配置时间等待 30s,进行通知告警

  1. 自愈验证,调用充值backend/account/deposit接口,使余额大于500,等待6m 左右会收到自愈告警,如果嫌时间比较长,修改alertmanager.yml中 group_waitgroup_interval参数值即可

Grafana配置

启动 Grafana,点击新增面板,创建三种图表,分别为余额走势提现与充值金额占比提现与充值笔数走势图,如下

image-20231228222038158

余额走势,报表类型为Stat

sum(balanceGauge{application="backend"})

提现与充值金额占比,报表类型为Pie chart

withdraw_amount_sum{application="backend"}
deposit_amount_sum{application="backend"}

提现与充值笔数走势图,报表类型为Time series

increase(deposit_counter_total{application="backend"}[5m])
increase(withdraw_counter_total{application="backend"}[5m])

总结

以上介绍了如何在Spring Boot中自定义业务指标以及对指标进行监控和告警,希望对你所帮助,注意以上示例只是为了简单便于理解才是这样写,真实使用中,指标可以与数据库或者缓存进行结合,比如余额报警,调用查询余额接口即可。

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

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

相关文章

Fedora操作系统有哪些优势

Fedora是一种基于Linux内核的开源操作系统&#xff0c;被广泛的认为是一款先进的、功能丰富的操作系统。它有许多的优势&#xff0c;从最新的软件版本到社区驱动的开发&#xff0c;以及安全性和稳定性等方面。下面我简单的介绍有哪些优势。 最新的软件版本 Fedora以当前最新的…

内网渗透之Vulnstack4靶场的全方位打法

靶场考察点 MS14-068漏洞 MS14-068是一个著名的Windows Kerberos安全漏洞&#xff0c;允许攻击者篡改Kerberos票据&#xff0c;从而获取非法提权。这个漏洞特别影响Windows域控制器&#xff0c;能让攻击者伪造Kerberos票据&#xff0c;获取域内几乎任意账户的权限&#xff0c…

鸿蒙系列--组件介绍之容器组件

一、Badge 描述&#xff1a;给其他组件添加标记 子组件&#xff1a;支持单个子组件 1.创建数字标记 Badge(value: {count: number, position?: BadgePosition, maxCount?: number, style: BadgeStyle}) 2.创建字符串标记 Badge(value: {value: string, position?: Badge…

关于Python里xlwings库对Excel表格的操作(二十三)

这篇小笔记主要记录如何【用“.number_format ”函数设置单元格的文本各种属性】。前面的小笔记已整理成目录&#xff0c;可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 &#xff08;1&#xff09;如何安装导入xlwings库&#xff1b; &#xff0…

批量抠图软件哪个好用?推荐这三款抠图工具给你

在数字图像处理的世界里&#xff0c;抠图是个不可或缺的环节。对于那些经常需要从复杂背景中提取主体的设计师和摄影师来说&#xff0c;抠图技巧无疑是一项宝贵的职业技能。然而&#xff0c;当面对大量的抠图需求时&#xff0c;手动处理不仅耗时&#xff0c;而且效率低下。因此…

Junit在多线程测试时的坑

Junit单元测试主线程退出&#xff0c;子线程也会退出 Testpublic void test() throws InterruptedException {Thread t1 new Thread(() -> {try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Thread.…

PowerShell Instal 一键部署gitea

gitea 前言 Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来…

在Java中使用选择排序将数组中的一列元素排列出来

思想 选择排序&#xff1a;特点有简单直观、从大到小、每趟从待选择的元素中选出最小或最大的一个元素&#xff0c;顺序放在已经排好的序列的最后&#xff0c;直到全部待排序数据元素排完。 代码 public class SelectSort {public static int[] orderby(int[] nums,String …

C++标准模板库(STL)

标准模板库&#xff08;STL&#xff09;是一组C模板类&#xff0c;提供常见的编程数据结构和函数&#xff0c;如列表、堆栈、数组等。它是一个容器类、算法和迭代器的库。它是一个通用库&#xff0c;因此&#xff0c;它的组件是参数化的。模板类的相关知识是使用STL的先决条件。…

C#下将点云数据保存为PLY格式

目前没有找到C#下将点云数据保存为PLY格式的库&#xff0c;查看了一下PLY格式&#xff0c;所以自己写了个方法实现点云数据保存PLY格式 public static string SavePointCloudToPLY(string No, float[] x, float[] y, float[] z){ string result "";Task.Run(() >…

I.MX6ULL_Linux_驱动篇(51)linux 音频驱动

音频是我们最常用到的功能&#xff0c;音频也是 linux 和安卓的重点应用场合。 I.MX6ULL 带有 SAI接口&#xff0c;正点原子的 I.MX6ULLALPHA 开发板通过此接口外接了一个 WM8960 音频 DAC 芯片&#xff0c;本章我们就来学习一下如何使能 WM8960 驱动&#xff0c;并且通过 WM89…

【MCAL】TC397+EB-tresos之MCU配置实战 - 芯片时钟

本篇文章介绍了在TC397平台使用EB-treso对MCU驱动模块进行配置的实战过程&#xff0c;主要介绍了后续基本每个外设模块都要涉及的芯片时钟部分&#xff0c;帮助读者了解TC397芯片的时钟树结构&#xff0c;在后续计算配置不同外设模块诸如通信速率&#xff0c;定时器周期等&…

自定义注解结合Hutool对SpringBoot接口返回数据进行脱敏

首先说到脱敏问题,我相信在座的很多人都需要处理这样的场景,比如前端页面显示的身份证号、地址等敏感信息都需要脱敏处理,而hutool就有这样的一个工具来辅助我们完成对某些字段属性信息的脱敏,hutool没有现成的实现方式,只是借助这个工具帮助我们来具体实现 前言 我们在…

AIGC开发:调用openai的API接口

简介 开始进行最简单的使用&#xff1a;通过API调用openai的模型能力 OpenAI的能力如下图&#xff1a; 文本生成模型 OpenAI 的文本生成模型&#xff08;通常称为生成式预训练 Transformer 或大型语言模型&#xff09;经过训练可以理解自然语言、代码和图像。这些模型提供文…

Bluetooth Mesh 入门学习干货,参考Nordic资料(更新中)

蓝牙网状网络&#xff08;Bluetooth mesh&#xff09;概念 概述 蓝牙Mesh Profile | Bluetooth Technology Website规范&#xff08;Mesh v1.1 后改名Mesh ProtocolMesh Protocol | Bluetooth Technology WebsiteMesh Protocol&#xff09;是由蓝牙技术联盟(Bluetooth SIG)开…

电影《海王2》观后感

上周看了电影《海王2》&#xff0c;整体特效和打斗还是非常不错的&#xff0c;自己在写文章的时候&#xff0c;看完电影已经一周了&#xff0c;相当于是叙事自我在描述这段经历。 &#xff08;1&#xff09;体验自我VS叙事自我 首先简单说明下“体验自我”和“叙事自我”&…

查看ios 应用程序性能

目录 摘要 前言 性能概括 CPU内存监控 内存监控 磁盘监控 网络监控 GPU fps 摘要 本篇博文将介绍一款重量级性能测试工具——克魔助手&#xff0c;针对iOS应用程序的性能监控进行详细介绍。通过克魔助手&#xff0c;开发者可以方便地查看应用程序的CPU、内存、GPU性能…

用OpenDataLab下载PASCAL VOC 2007等公开数据集

OpenDataLab OpenDataLab 公开数据集平台&#xff0c;集海量优质的多模态数据集资源、数据集智能检索、数据可视化展示、数据在线预览、下载优化、标准化管理等功能于一体&#xff0c;力争将平台打造成企业、高校、科研机构等的AI 模型训练的必备利器&#xff0c;帮大家解决数…

【Hive_04】分区分桶表以及文件格式

1、分区表1.1 分区表基本语法&#xff08;1&#xff09;创建分区表&#xff08;2&#xff09;分区表读写数据&#xff08;3&#xff09;分区表基本操作 1.2 二级分区1.3 动态分区 2、分桶表2.1 分桶表的基本语法2.2 分桶排序表 3、文件格式与压缩3.1 Hadoop压缩概述3.2 Hive文件…

前端的 js

js 点击按钮修改文字 <!DOCTYPE html> <html> <head></head><body><h2>Head 中的 JavaScript</h2><p id"demo">一个段落。</p><button type"button" onclick"myFunction()">试一…