nightingale/http/router_collect_rule.go

259 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package http
import (
"regexp"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/didi/nightingale/v5/cache"
"github.com/didi/nightingale/v5/models"
"github.com/didi/nightingale/v5/pkg/i18n"
)
type collectRuleForm struct {
ClasspathId int64 `json:"classpath_id"`
PrefixMatch int `json:"prefix_match"`
Name string `json:"name"`
Note string `json:"note"`
Step int `json:"step"`
Type string `json:"type"`
Data string `json:"data"`
AppendTags string `json:"append_tags"`
}
func collectRuleAdd(c *gin.Context) {
var f collectRuleForm
bind(c, &f)
me := loginUser(c).MustPerm("collect_rule_create")
cr := models.CollectRule{
ClasspathId: f.ClasspathId,
PrefixMatch: f.PrefixMatch,
Name: f.Name,
Note: f.Note,
Step: f.Step,
Type: f.Type,
Data: f.Data,
AppendTags: f.AppendTags,
CreateBy: me.Username,
UpdateBy: me.Username,
}
renderMessage(c, cr.Add())
}
func collectRulePut(c *gin.Context) {
var f collectRuleForm
bind(c, &f)
me := loginUser(c).MustPerm("collect_rule_modify")
cr := CollectRule(urlParamInt64(c, "id"))
cr.PrefixMatch = f.PrefixMatch
cr.Name = f.Name
cr.Note = f.Note
cr.Step = f.Step
cr.Type = f.Type
cr.Data = f.Data
cr.AppendTags = f.AppendTags
cr.UpdateAt = time.Now().Unix()
cr.UpdateBy = me.Username
renderMessage(c, cr.Update(
"prefix_match",
"name",
"note",
"step",
"type",
"data",
"update_at",
"update_by",
"append_tags",
))
}
func collectRuleDel(c *gin.Context) {
var f idsForm
bind(c, &f)
f.Validate()
loginUser(c).MustPerm("collect_rule_delete")
renderMessage(c, models.CollectRulesDel(f.Ids))
}
func collectRuleGets(c *gin.Context) {
classpathId := urlParamInt64(c, "id")
where := "classpath_id = ?"
param := []interface{}{classpathId}
typ := queryStr(c, "type", "")
if typ != "" {
where += " and type = ?"
param = append(param, typ)
}
objs, err := models.CollectRuleGets(where, param...)
renderData(c, objs, err)
}
func collectRuleGetsByIdent(c *gin.Context) {
ident := queryStr(c, "ident")
objs := cache.CollectRulesOfIdent.GetBy(ident)
renderData(c, objs, nil)
}
type Summary struct {
LatestUpdatedAt int64 `json:"latestUpdatedAt"`
Total int `json:"total"`
}
func collectRuleSummaryGetByIdent(c *gin.Context) {
ident := queryStr(c, "ident")
var summary Summary
objs := cache.CollectRulesOfIdent.GetBy(ident)
total := len(objs)
if total > 0 {
summary.Total = total
var latestUpdatedAt int64
for _, obj := range objs {
if latestUpdatedAt < obj.UpdateAt {
latestUpdatedAt = obj.UpdateAt
}
}
summary.LatestUpdatedAt = latestUpdatedAt
}
renderData(c, summary, nil)
}
type RegExpCheck struct {
Success bool `json:"success"`
Data []map[string]string `json:"tags"`
}
func regExpCheck(c *gin.Context) {
param := make(map[string]string)
dangerous(c.ShouldBind(&param))
ret := &RegExpCheck{
Success: true,
Data: make([]map[string]string, 0),
}
calcMethod := param["func"]
if calcMethod == "" {
tmp := map[string]string{"func": "is empty"}
ret.Data = append(ret.Data, tmp)
renderData(c, ret, nil)
return
}
// 处理主正则
if re, ok := param["re"]; !ok || re == "" {
tmp := map[string]string{"re": "regex does not exist or is empty"}
ret.Data = append(ret.Data, tmp)
renderData(c, ret, nil)
return
}
// 匹配主正则
suc, reRes, isSub := checkRegex(param["re"], param["log"])
if !suc {
ret.Success = false
reRes = genErrMsg("re")
ret.Data = append(ret.Data, map[string]string{"re": reRes})
renderData(c, ret, nil)
return
}
if calcMethod == "histogram" && !isSub {
ret.Success = false
reRes = genSubErrMsg("re")
ret.Data = append(ret.Data, map[string]string{"re": reRes})
renderData(c, ret, nil)
return
}
ret.Data = append(ret.Data, map[string]string{"re": reRes})
// 处理tags
var nonTagKey = map[string]bool{
"re": true,
"log": true,
"func": true,
}
for tagk, pat := range param {
// 如果不是tag就继续循环
if _, ok := nonTagKey[tagk]; ok {
continue
}
suc, tagRes, isSub := checkRegex(pat, param["log"])
if !suc {
// 正则错误
ret.Success = false
tagRes = genErrMsg(tagk)
} else if !isSub {
// 未匹配出子串
ret.Success = false
tagRes = genSubErrMsg(tagk)
} else if includeIllegalChar(tagRes) || includeIllegalChar(tagk) {
// 保留字报错
ret.Success = false
tagRes = genIllegalCharErrMsg()
}
tmp := map[string]string{tagk: tagRes}
ret.Data = append(ret.Data, tmp)
}
renderData(c, ret, nil)
}
// 出错信息直接放在body里
func checkRegex(pat string, log string) (succ bool, result string, isSub bool) {
if pat == "" {
return false, "", false
}
reg, err := regexp.Compile(pat)
if err != nil {
return false, "", false
}
res := reg.FindStringSubmatch(log)
switch len(res) {
// 没查到
case 0:
return false, "", false
// 没查到括号内的串,返回整个匹配串
case 1:
return true, res[0], false
// 查到了,默认取第一个串
default:
return true, res[1], true
}
}
func includeIllegalChar(s string) bool {
illegalChars := ":,=\r\n\t"
return strings.ContainsAny(s, illegalChars)
}
// 生成返回错误信息
func genErrMsg(sign string) string {
return i18n.Sprintf("regular match failed, please check your configuration:[%s]", sign)
}
// 生成子串匹配错误信息
func genSubErrMsg(sign string) string {
return i18n.Sprintf("regular match was successful. according to the configuration, it does not get the substring inside(), please check your configuration:[%s]", sign)
}
// 生成子串匹配错误信息
func genIllegalCharErrMsg() string {
return i18n.Sprintf(`key or value of tag contains illegal characters:[:,/=\r\n\t]`)
}