Java中的SkyWalking监控告警详解

 更新时间:2023年11月06日 10:09:04   作者:杨小胖要减肥  
这篇文章主要介绍了Java中的SkyWalking监控告警详解,SkyWalking在6.x版本中新增了告警功能,其核心在于config/alarm-settings.yaml文件中,该文件分为rules和webhooks两部分,需要的朋友可以参考下

SkyWalking监控告警

SkyWalking在6.x版本中新增了告警功能,其核心在于config/alarm-settings.yaml文件中,该文件分为rules和webhooks两部分。

rules用于定义告警的条件,webhook则用于定于告警触发时,需要通知哪些服务。

告警规则配置项的说明:

  • **Rule name:**规则名称,也是在告警信息中显示的唯一名称。必须以_rule结尾,前缀可自定义
  • **Metrics name:**度量名称,取值为oal脚本中的度量名,目前只支持long、double和int类型。详见 Official OAL script
  • **Include names:**该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部)
  • **Exclude names:**该规则作不用于哪些实体名称,比如服务名,终端名(可选,默认为空)
  • **Threshold:**阈值
  • OP: 操作符,目前支持 >、<、=
  • **Period:**多久告警规则需要被核实一下。这是一个时间窗口,与后端部署环境时间相匹配
  • **Count:**在一个Period窗口中,如果values超过Threshold值(按op),达到Count值,需要发送警报
  • **Silence period:**在时间N中触发报警后,在TN -> TN + period这个阶段不告警。 默认情况下,它和Period一样,这意味着相同的告警(在同一个Metrics name拥有相同的Id)在同一个Period内只会触发一次
  • **message:**告警消息

webhook会在触发告警时,向配置的地址发送http POST请求,并将Content-Type为application/json,也就是说会发送json格式的POST请求。

webhooks发送的字段包含

  • **scopeId、scope
  • **name:**目标 Scope 的实体名称
  • **id0:**Scope 实体的 ID
  • **id1:**保留字段,目前暂未使用
  • **ruleName:**告警规则名称
  • **alarmMessage:**告警消息内容
  • **startTime:**告警时间,格式为时间戳
  • **tags:**alarm-settings.yml中配置的tags

具体字段类型可以参考官方定义的AlarmMessage

由于邮件系统之前的通讯方式都是基于MQ进行的,所以需要定义一个Controller,用于接收Skywalking的请求,官方给出的请求数据示例为

[{
  "scopeId": 1, 
  "scope": "SERVICE",
  "name": "serviceA", 
  "id0": "12",  
  "id1": "",  
    "ruleName": "service_resp_time_rule",
  "alarmMessage": "alarmMessage xxxx",
  "startTime": 1560524171000,
    "tags": [{
        "key": "level",
        "value": "WARNING"
     }]
}, {
  "scopeId": 1,
  "scope": "SERVICE",
  "name": "serviceB",
  "id0": "23",
  "id1": "",
    "ruleName": "service_resp_time_rule",
  "alarmMessage": "alarmMessage yyy",
  "startTime": 1560524171000,
    "tags": [{
        "key": "level",
        "value": "CRITICAL"
    }]
}]

所以可以定义接口为

@PostMapping("/skywalking/alarm")
public void alarm(@RequestBody List<SkyWalkingAlarmMessage> alarmList) {
  ......
  ......
}

接收到数据之后,如果不为空,就可以组装邮件发送给配置的相关开发或运维人员。

定义SkyWalking邮件的相关配置

@Data
@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "alarm")
public class AlarmMailConfig {

    private AlarmMailInfo skyWalking;

    @Data
    public static class AlarmMailInfo{
      	/**
      	 * 发件昵称
      	 */
        private String nickName;
      	/**
      	 * 收件地址
      	 */
        private List<String> toAddress;
      	/**
      	 * 是否转义告警字段
      	 */
        private boolean translateField = true;
    }
}

定义告警字段的中文映射

enum Mapping{
    scopeId("scopeId"),
    scope("scope"),
    name("目标Scope的实体名称"),
    id0("Scope实体的ID"),
    id1("id1"),
    ruleName("警告规则名称"),
    alarmMessage("告警消息内容"),
    startTime("告警时间"),
    tags("tags")
    ;
     private String fieldName;

    Mapping(String fieldName) {
        this.fieldName = fieldName;
    }
    private static final Map<String,String> cacheMap =
            Arrays.stream(Mapping.values()).collect(Collectors.toMap(Enum::name, e->e.fieldName));

}

定义SkyWalking的处理Controller

@Slf4j
@RestController
public class AlarmMailController {
	 // 时间格式化pattern
   public static final String TIME_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
   // 发送邮件Service
   @Autowired
   private SendMailService sendMailService;
   // 告警邮件配置
   @Autowired
   private AlarmMailConfig alarmMailConfig;
   // 通过反射获取请求字段的字段名
   private final List<String> skyWalkingAlarmMessageFieldName =
         ReflectUtils.getAllNoStaticFieldList(SkyWalkingAlarmMessage.class).stream().map(Field::getName)
               .collect(Collectors.toList());

   @PostMapping("/skywalking/alarm")
   public void alarm(@RequestBody List<SkyWalkingAlarmMessage> alarmList) {
      log.info("接收到skywalking监控调用");
      if (CollectionUtil.isEmpty(alarmList)) {
         log.info("监控调用为空");
         return;
      }
      SendMailRequest sendMailRequest = fillSkyWalkingMailRequest(alarmList);
      sendMailService.sendCustomizeMail(sendMailRequest);
   }

   private SendMailRequest fillSkyWalkingMailRequest(List<SkyWalkingAlarmMessage> alarmList) {
      SendMailRequest sendMailRequest = new SendMailRequest();
     	// 设置主题
      sendMailRequest.setSubject("SkyWalking监控邮件");
     	// 定义请求的系统
      sendMailRequest.setSystemMark("SkyWalking");
      sendMailRequest.setRequestTime(LocalDateTime.now());

      AlarmMailConfig.AlarmMailInfo skyWalkingConfig = alarmMailConfig.getSkyWalking();
     	// 发件人昵称
      sendMailRequest.setSenderNickname(skyWalkingConfig.getNickName());
     	// 收件人地址
      sendMailRequest.setToAddress(skyWalkingConfig.getToAddress());
     	// 邮件主题是否为html格式
      sendMailRequest.setHtmlText(true);
     	// 添加默认的免责声明
      sendMailRequest.setAddDefaultDisclaimer(true);
     	// 生成邮件正文
      String mailBody = fillSkyWalkingAlarmMessage(alarmList);
      sendMailRequest.setContentText(mailBody);
      return sendMailRequest;
   }

   private String fillSkyWalkingAlarmMessage(List<SkyWalkingAlarmMessage> alarmList) {
      AlarmMailConfig.AlarmMailInfo skyWalkingConfig = alarmMailConfig.getSkyWalking();
      String mailBody = alarmList.stream().map(message -> skyWalkingAlarmMessageFieldName.stream().map(field -> {
         Object value;
         // 如果参数是startTime
         if (StringUtils.equals(field, "startTime")) {
            Long startTime = message.getStartTime();
           	// 如果为空
            if (startTime == null) {
               // 展示数据为空
               value = StringUtils.EMPTY;
            } else {
               // 否则进行格式化便于展示
               value = DateUtils.format(DateUtils.getDate(startTime), TIME_PATTERN);
            }
          // 如果是tags字段
         } else if (StringUtils.equals(field, "tags")) {
            List<SkyWalkingAlarmMessage.Tag> tags = message.getTags();
            if (CollectionUtil.isEmpty(tags)) {
               value = StringUtils.EMPTY;
            } else {
               // 进行拼接
               value = tags.stream().map(v -> v.getKey() + ":" + v.getValue())
                     .collect(Collectors.joining(";
", "[", "]"));
            }
         } else {
           	// 直接获取属性值
            value = ReflectUtils.getFieldValue(message, field);
         }
         // 是否需要翻译告警字段
         boolean translateField = skyWalkingConfig.isTranslateField();
         if (translateField){
           	// 拼接翻译字段的和对应的值
            return SkyWalkingAlarmMessage.getFieldName(f) + ":" + value;
         }else {
           // 拼接字段和对应的值
            return f + ":" + value;
         }
      }).collect(Collectors.joining("
"))).collect(Collectors.joining("

<HR>

"));
      return mailBody;
   }
}

到此这篇关于Java中的SkyWalking监控告警详解的文章就介绍到这了,更多相关SkyWalking监控告警内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章带你了解XGBoost算法

    一篇文章带你了解XGBoost算法

    XGBoost全名叫(eXtreme Gradient Boosting)极端梯度提升,经常被用在一些比赛中,其效果显著。它是大规模并行boosted tree的工具,它是目前最快最好的开源boosted tree工具包
    2021-08-08
  • SpringBoot中使用MyBatis-Plus详细步骤

    SpringBoot中使用MyBatis-Plus详细步骤

    MyBatis-Plus是MyBatis的增强工具,简化了MyBatis的使用,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • java迭代器中删除元素的实例操作详解

    java迭代器中删除元素的实例操作详解

    在本篇内容里小编给各位分享了一篇关于java迭代器中删除元素的实例操作详解内容,有兴趣的朋友们可以学习下。
    2021-01-01
  • Springboot深入讲解nocos的整合与使用

    Springboot深入讲解nocos的整合与使用

    Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,在项目开发过程中,我们经常使用nacos作为配置中心和注册中心。本文章我们就从代码层面研究下springboot是如何整合nacos使用的
    2022-07-07
  • 打开.properties中文显示unicode编码问题以及解决

    打开.properties中文显示unicode编码问题以及解决

    这篇文章主要介绍了打开.properties中文显示unicode编码问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Springboot集成Mybatis-plus、ClickHouse实现增加数据、查询数据功能

    Springboot集成Mybatis-plus、ClickHouse实现增加数据、查询数据功能

    本文给大家讲解Springboot + mybatis-plus 集成ClickHouse,实现增加数据、查询数据功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • Java排序算法之选择排序代码实例

    Java排序算法之选择排序代码实例

    这篇文章主要介绍了Java排序算法之选择排序代码实例,从数组的第一个元素开始,每次遍历数组找出一个最小值放在最左侧,第二次从第二个元素开始,依次类推,直到起始元素为数组的倒数第二个元素时,直接和最后一个元素比较,较小值放左边,完成排序,需要的朋友可以参考下
    2023-11-11
  • Java SPI模块化解耦的技术指南

    Java SPI模块化解耦的技术指南

    Java 的 Service Provider Interface (SPI) 是一种提供模块化和扩展性的方法,使得程序能够通过动态加载服务实现类来实现解耦,本文将详细介绍 Java SPI 的机制、应用场景及实现步骤,并通过示例代码展示如何使用 SPI,需要的朋友可以参考下
    2025-03-03
  • Java线程同步方法实例总结

    Java线程同步方法实例总结

    这篇文章主要介绍了Java线程同步方法,结合实例形式总结分析了Java线程同步、并发控制相关实现方法及操作注意事项,需要的朋友可以参考下
    2018-08-08
  • 关于SpringSecurity简介以及和Shiro的区别

    关于SpringSecurity简介以及和Shiro的区别

    这篇文章主要介绍了关于SpringSecurity简介以及和Shiro的区别,在Java应用安全领域,Spring Security会成为被首先推崇的解决方案,就像我们看到服务器就会联想到Linux一样顺理成章,需要的朋友可以参考下
    2023-07-07

最新评论