Skywalking配置告警触发
Skywalking安装好了,大致的指标也看了,告警规则也看了,剩下的就是研究下如何将告警信息发出去,不可能人工一直盯着浏览器去看,因此及时触发告警是个好办法,比如:在调用某个接口的时候出现了响应超时,超过了预期范围,那么此时就可以触发告警,及时去排查接口情况
告警触发的配置也是在alarm-settings.yml文件中,在最下面,如下:
hooks:
webhook:
default:
is-default: true
urls:
- http://192.168.51.15:8866/alarm
# - http://127.0.0.1/go-wechat/
其中的urls里面配置的就是告警的url,如果有多个,可以写多个,我这里写的一个,是我自己写的告警接收接口,要自定义告警接收接口,首先要知道告警后发送出来的数据是什么格式,通过程序获取,格式为JSON类型,如下:
[{ "scopeId": 6, "scope": "ENDPOINT_RELATION", "name": "User in User to POST:/cmb/restartContract in test_name", "id0": "VXNlcg==".0_VXNlcg==", "id1": "enlsY190ZXN0.1_UE9TVDovY21iL3Jlc3RhcnRDb250cmFjdA==", "ruleName": "endpoint_relation_75_rule", "alarmMessage": "endpoint relation percentile User in User to POST:/cmb/restartContract in zylc_test is less than 5000ms", "tags": [], "startTime": 1763028144347, "hooks": ["webhook.default"]}]
scopeId:监控范围的ID,6代表端点关系(Endpoint Relation),SkyWalking常用scopeId对照表:
- Service(服务)
- Service Instance(服务实例)
- Endpoint(端点)
- Endpoint Relation(端点关系)
- Service Relation(服务关系)
scope: 监控范围的名称,表示这是端点关系级别的监控
name: 端点关系的描述名称
- 格式:
[源端点] in [源服务] to [目标端点] in [目标服务] (这个目标服务就是agent启动的时候指定的服务名)
id0: 经过Base64编码的端点关系标识符,表示源端点的编码标识
id1: 经过Base64编码的端点关系标识符,表示目标端点的编码标识
ruleName:触发告警的规则名称,也就是在alarm-settings.yml中定义的名称
alarmMessage:告警的详细描述信息,这个才是重点
tags:标签信息,用于附加元数据
- 用途:可以包含自定义标签,如环境、区域等信息
- 示例:[“env:prod”, “region:us-east”]
startTime:告警触发的时间戳,Unix时间戳(毫秒)
hooks:告警触发的钩子列表,定义告警要发送到的处理端点
在本例子中,我是将告警信息发送到了自定义的脚本接口中,通过邮件实现告警,golang脚本如下:
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/jordan-wright/email"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"net/smtp"
"time"
)
type test struct {
ScopeID int
Scope string
Name string
ID0 string
ID1 string
RuleName string
AlarmMessage string
Tags []string
StartTime int
Hooks []string
}
type mailConfig struct {
Send_mail string //发件人
Recv_mail []string //收件人,可以多个,所以用字符串切片
Cc_mail []string //抄送人,也可以多个
Smtp_address string //smtp服务器地址
Smtp_port int //smtp端口
Auth_code string //授权码
}
func createMail() *mailConfig {
var mc *mailConfig
by, err := ioutil.ReadFile("/etc/monitor.yaml")
if err != nil {
log.Fatal(err)
}
err = yaml.Unmarshal(by, &mc)
if err != nil {
fmt.Println(1000)
log.Fatal(err)
}
return mc
}
func sendmail(id int, scope, name, ruleName, alarmMessage, startTime, alarmStatus string) {
mc := createMail()
e := email.NewEmail()
//设置发送方的邮箱
e.From = mc.Send_mail
// 设置接收方的邮箱
e.To = mc.Recv_mail
e.Cc = mc.Cc_mail
//设置主题
e.Subject = alarmStatus
//设置文件发送的内容
text := fmt.Sprintf("监控范围ID: %d\n监控范围名称: %s\n监控端点名称: %s\n告警规则名: %s\n告警详细信息: %s\n告警时间: %s\n", id, scope, name, ruleName, alarmMessage, startTime)
e.Text = []byte(text)
//设置服务器相关的配置
e.Send(fmt.Sprintf("%s:%d", mc.Smtp_address, mc.Smtp_port), smtp.PlainAuth("", mc.Send_mail, mc.Auth_code, mc.Smtp_address))
}
// 将时间戳转换为标准时间
func timestamp(t int) string {
beijingTime := time.UnixMilli(int64(t)).In(time.FixedZone("CST", 8*60*60))
return beijingTime.Format("2006年01月02日 15时04分05秒")
}
func main() {
r := gin.New()
r.POST("/alarm", func(c *gin.Context) {
var t []test
//获取原始数据,实际是一个[]uint8类型,也就是[]byte类型,可直接反序列化到结构体即可
by, err := c.GetRawData()
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(by, &t) //反序列化到结构体中
if err != nil {
log.Fatal(err)
}
id := t[0].ScopeID
scope := t[0].Scope
name := t[0].Name
ruleName := t[0].RuleName
alarmMessage := t[0].AlarmMessage
startTime := timestamp(t[0].StartTime)
alarmStatus := "SKywalking告警触发!!!!!!!"
sendmail(id, scope, name, ruleName, alarmMessage, startTime, alarmStatus)
})
r.Run(":8866")
}
注:实际告警信息中并没有包含ID0、ID1、tags、hooks,因为这些都是非必要信息,当然如果需要可自定修改脚本添加上
邮件的配置文件monitor.yml内容如下:
#发件人
send_mail: abcd@qq.com
#收件人邮箱,可写多个
recv_mail:
- 111111@qq.com
#抄送人邮箱
cc_mail:
- 2222222@outlook.com
#smtp服务器地址
smtp_address: smtp.qq.com
#smtp端口
smtp_port: 25
#授权码
auth_code: adfdtvteisffeff
启动脚本后,触发告警,查看邮箱告警内容如图:



