nightingale/http/router_collect_rule.go

258 lines
5.5 KiB
Go
Raw Normal View History

2020-09-26 16:53:10 +08:00
package http
import (
"regexp"
"strings"
"time"
2020-09-26 16:53:10 +08:00
"github.com/gin-gonic/gin"
"github.com/didi/nightingale/v5/cache"
"github.com/didi/nightingale/v5/models"
2020-09-26 16:53:10 +08:00
)
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"`
2020-09-26 16:53:10 +08:00
}
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,
2020-09-26 16:53:10 +08:00
}
renderMessage(c, cr.Add())
2020-09-26 16:53:10 +08:00
}
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",
))
2020-09-26 16:53:10 +08:00
}
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))
2020-09-26 16:53:10 +08:00
}
func collectRuleGets(c *gin.Context) {
classpathId := urlParamInt64(c, "id")
2020-09-26 16:53:10 +08:00
where := "classpath_id = ?"
param := []interface{}{classpathId}
Rdb (#479) * use collector interface * mysql can work fine * add basecollector * add prober & monapi.plugins * enable mysql plugins work * rename collector -> manager * add white list access check for rdb * add cache module for authConfig & session * rollback n9e_rdb_3.3.0.sql * add sql ddl document * add white_list, pwd, login access control * add email code for login & reset password * use sessionUsername instead of cookieUsername * remove cookie name and data from session * rename userName to username * add remote_addr with session connection * add get user by sid with cache * enable cookie life time could be zero * go mod tidy * Rdb with session & monapi with telegraf (#456) * use collector interface * mysql can work fine * add basecollector * add prober & monapi.plugins * enable mysql plugins work * rename collector -> manager * add white list access check for rdb * add cache module for authConfig & session * rollback n9e_rdb_3.3.0.sql * add sql ddl document * add white_list, pwd, login access control * add email code for login & reset password * use sessionUsername instead of cookieUsername * remove cookie name and data from session * rename userName to username * add remote_addr with session connection * add get user by sid with cache * enable cookie life time could be zero * go mod tidy * add plugins config for prober * add prober plugin expression parse * update transfer default config for m3 * Rdb (#458) * bugfix: session gc * use flag for pwdMustInclude * change user login function * delete invite token after use * bugfix: login response * add sessionStart middle ware * add auth module * add i18n for rdb * add i18n.zh for rdb.auth * add mon plugins(redis, mongodb) * update config * add sub struct into definitions * clean up sid cache after session destory * bugfix: get user return nil when not found * update i18n * bugfix: ignore cache nologin user * add user for callback output * add password change api * update default configfile & sql patch * merge mon http middleware from rdb * remove sso logout, sso already supporte one time auth
2021-01-01 10:41:30 +08:00
typ := queryStr(c, "type", "")
if typ != "" {
where += " and type = ?"
param = append(param, typ)
2020-09-26 16:53:10 +08:00
}
objs, err := models.CollectRuleGets(where, param...)
renderData(c, objs, err)
2020-09-26 16:53:10 +08:00
}
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"`
2020-09-26 16:53:10 +08:00
}
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
2020-09-26 16:53:10 +08:00
}
}
summary.LatestUpdatedAt = latestUpdatedAt
2020-09-26 16:53:10 +08:00
}
renderData(c, summary, nil)
2020-09-26 16:53:10 +08:00
}
type RegExpCheck struct {
2020-09-26 16:53:10 +08:00
Success bool `json:"success"`
Data []map[string]string `json:"tags"`
}
func regExpCheck(c *gin.Context) {
param := make(map[string]string)
dangerous(c.ShouldBind(&param))
2020-09-26 16:53:10 +08:00
ret := &RegExpCheck{
2020-09-26 16:53:10 +08:00
Success: true,
Data: make([]map[string]string, 0),
}
2021-06-29 20:09:40 +08:00
calcMethod := param["func"]
if calcMethod == "" {
tmp := map[string]string{"func": "is empty"}
2020-09-26 16:53:10 +08:00
ret.Data = append(ret.Data, tmp)
2021-06-29 20:09:40 +08:00
renderData(c, ret, nil)
return
2020-09-26 16:53:10 +08:00
}
2021-06-29 20:09:40 +08:00
// 处理主正则
2020-09-26 16:53:10 +08:00
if re, ok := param["re"]; !ok || re == "" {
2021-06-29 20:09:40 +08:00
tmp := map[string]string{"re": "regex does not exist or is empty"}
2020-09-26 16:53:10 +08:00
ret.Data = append(ret.Data, tmp)
2021-06-29 20:09:40 +08:00
renderData(c, ret, nil)
return
}
2020-09-26 16:53:10 +08:00
2021-06-29 20:09:40 +08:00
// 匹配主正则
suc, reRes, isSub := checkRegex(param["re"], param["log"])
if !suc {
ret.Success = false
reRes = genErrMsg(param["re"])
2021-06-29 20:09:40 +08:00
ret.Data = append(ret.Data, map[string]string{"re": reRes})
renderData(c, ret, nil)
return
}
if calcMethod == "histogram" && !isSub {
ret.Success = false
reRes = genSubErrMsg(param["re"])
2021-06-29 20:09:40 +08:00
ret.Data = append(ret.Data, map[string]string{"re": reRes})
renderData(c, ret, nil)
return
2020-09-26 16:53:10 +08:00
}
2021-06-29 20:09:40 +08:00
ret.Data = append(ret.Data, map[string]string{"re": reRes})
2020-09-26 16:53:10 +08:00
// 处理tags
var nonTagKey = map[string]bool{
2021-06-29 20:09:40 +08:00
"re": true,
"log": true,
"func": true,
2020-09-26 16:53:10 +08:00
}
for tagk, pat := range param {
// 如果不是tag就继续循环
if _, ok := nonTagKey[tagk]; ok {
continue
}
2021-06-29 20:09:40 +08:00
suc, tagRes, isSub := checkRegex(pat, param["log"])
2020-09-26 16:53:10 +08:00
if !suc {
// 正则错误
ret.Success = false
tagRes = genErrMsg(pat)
2020-09-26 16:53:10 +08:00
} else if !isSub {
// 未匹配出子串
ret.Success = false
tagRes = genSubErrMsg(pat)
2020-09-26 16:53:10 +08:00
} 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里
2021-06-29 20:09:40 +08:00
func checkRegex(pat string, log string) (succ bool, result string, isSub bool) {
2020-09-26 16:53:10 +08:00
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:
2021-06-29 20:09:40 +08:00
return true, res[1], true
2020-09-26 16:53:10 +08:00
}
}
func includeIllegalChar(s string) bool {
illegalChars := ":,=\r\n\t"
return strings.ContainsAny(s, illegalChars)
}
// 生成返回错误信息
func genErrMsg(pattern string) string {
return _s("Regexp[%s] matching failed", pattern)
2020-09-26 16:53:10 +08:00
}
// 生成子串匹配错误信息
func genSubErrMsg(pattern string) string {
return _s("Regexp[%s] matched, but cannot get substring()", pattern)
2020-09-26 16:53:10 +08:00
}
// 生成子串匹配错误信息
func genIllegalCharErrMsg() string {
return _s(`TagKey or TagValue contains illegal characters[:,/=\r\n\t]`)
2021-04-13 11:38:40 +08:00
}