From a65632620376d3e841ca51b9c305175458f63f1f Mon Sep 17 00:00:00 2001 From: liugq Date: Fri, 13 May 2022 18:22:33 +0800 Subject: [PATCH] add template funcs --- plugin/api/alerting/rule.go | 36 ++++++ service/alerting/elasticsearch/engine.go | 5 +- service/alerting/funcs/bytes.go | 11 ++ service/alerting/funcs/date.go | 151 +++++++++++++++++++++++ service/alerting/funcs/function.go | 23 ++++ service/alerting/funcs/numberic.go | 11 ++ 6 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 service/alerting/funcs/bytes.go create mode 100644 service/alerting/funcs/date.go create mode 100644 service/alerting/funcs/function.go create mode 100644 service/alerting/funcs/numberic.go diff --git a/plugin/api/alerting/rule.go b/plugin/api/alerting/rule.go index b89198c8..1abd055d 100644 --- a/plugin/api/alerting/rule.go +++ b/plugin/api/alerting/rule.go @@ -19,6 +19,7 @@ import ( "infini.sh/framework/modules/elastic/api" "infini.sh/framework/modules/elastic/common" "net/http" + "strconv" "strings" "time" ) @@ -523,11 +524,15 @@ func (alertAPI *AlertAPI) getMetricData(w http.ResponseWriter, req *http.Request Ticks: 5}, }, } + var sampleData []alerting.TimeMetricData for _, md := range metricData { if len(md.Data) == 0 { continue } //filteredMetricData = append(filteredMetricData, md) + if sampleData == nil { + sampleData = md.Data["result"] + } metricItem.Lines = append(metricItem.Lines, &common.MetricLine{ Data: md.Data["result"], BucketSize: filterParam.BucketSize, @@ -539,6 +544,37 @@ func (alertAPI *AlertAPI) getMetricData(w http.ResponseWriter, req *http.Request }, }) } + //add guidelines + for _, cond := range rule.Conditions.Items{ + if len(cond.Values) > 0 { + val, err := strconv.ParseFloat(cond.Values[0], 64) + if err != nil { + log.Errorf("parse condition value error: %v", err) + continue + } + if sampleData != nil { + newData := make([]alerting.TimeMetricData,0, len(sampleData)) + for _, td := range sampleData { + if len(td) < 2{ + continue + } + newData = append(newData, alerting.TimeMetricData{ + td[0], val, + }) + } + metricItem.Lines = append(metricItem.Lines, &common.MetricLine{ + Data: newData, + BucketSize: filterParam.BucketSize, + Metric: common.MetricSummary{ + Label: "", + Group: rule.ID, + TickFormat: "0,0.[00]", + FormatType: "num", + }, + }) + } + } + } alertAPI.WriteJSON(w, util.MapStr{ "metric": metricItem, }, http.StatusOK) diff --git a/service/alerting/elasticsearch/engine.go b/service/alerting/elasticsearch/engine.go index 205587f2..22301ac7 100644 --- a/service/alerting/elasticsearch/engine.go +++ b/service/alerting/elasticsearch/engine.go @@ -13,6 +13,7 @@ import ( "infini.sh/console/model/alerting" alerting2 "infini.sh/console/service/alerting" "infini.sh/console/service/alerting/action" + "infini.sh/console/service/alerting/funcs" "infini.sh/framework/core/elastic" "infini.sh/framework/core/kv" "infini.sh/framework/core/orm" @@ -758,9 +759,7 @@ func performChannels(channels []alerting.Channel, ctx map[string]interface{}) ([ func resolveMessage(messageTemplate string, ctx map[string]interface{}) ([]byte, error){ msg := messageTemplate - tmpl, err := template.New("alert-message").Funcs(template.FuncMap{ - "format_bytes": func(precision int, bytes float64) string { return util.FormatBytes(bytes, precision)}, - }).Parse(msg) + tmpl, err := template.New("alert-message").Funcs(funcs.GenericFuncMap()).Parse(msg) if err !=nil { return nil, fmt.Errorf("parse message temlate error: %w", err) } diff --git a/service/alerting/funcs/bytes.go b/service/alerting/funcs/bytes.go new file mode 100644 index 00000000..759264c3 --- /dev/null +++ b/service/alerting/funcs/bytes.go @@ -0,0 +1,11 @@ +/* Copyright © INFINI Ltd. All rights reserved. + * web: https://infinilabs.com + * mail: hello#infini.ltd */ + +package funcs + +import "infini.sh/framework/core/util" + +func formatBytes(precision int, bytes float64) string { + return util.FormatBytes(bytes, precision) +} \ No newline at end of file diff --git a/service/alerting/funcs/date.go b/service/alerting/funcs/date.go new file mode 100644 index 00000000..52de96a4 --- /dev/null +++ b/service/alerting/funcs/date.go @@ -0,0 +1,151 @@ +/* Copyright © INFINI Ltd. All rights reserved. + * web: https://infinilabs.com + * mail: hello#infini.ltd */ + +package funcs + +import ( + "strconv" + "time" +) + +func date(fmt string, date interface{}) string { + return dateInZone(fmt, date, "Local") +} + +func htmlDate(date interface{}) string { + return dateInZone("2006-01-02", date, "Local") +} + +func htmlDateInZone(date interface{}, zone string) string { + return dateInZone("2006-01-02", date, zone) +} + +func dateInZone(fmt string, date interface{}, zone string) string { + var t time.Time + switch date := date.(type) { + default: + t = time.Now() + case time.Time: + t = date + case *time.Time: + t = *date + case int64: + t = time.Unix(date, 0) + case int: + t = time.Unix(int64(date), 0) + case int32: + t = time.Unix(int64(date), 0) + } + + loc, err := time.LoadLocation(zone) + if err != nil { + loc, _ = time.LoadLocation("UTC") + } + + return t.In(loc).Format(fmt) +} + +func dateModify(fmt string, date time.Time) time.Time { + d, err := time.ParseDuration(fmt) + if err != nil { + return date + } + return date.Add(d) +} + +func mustDateModify(fmt string, date time.Time) (time.Time, error) { + d, err := time.ParseDuration(fmt) + if err != nil { + return time.Time{}, err + } + return date.Add(d), nil +} + +func dateAgo(date interface{}) string { + var t time.Time + + switch date := date.(type) { + default: + t = time.Now() + case time.Time: + t = date + case int64: + t = time.Unix(date, 0) + case int: + t = time.Unix(int64(date), 0) + } + // Drop resolution to seconds + duration := time.Since(t).Round(time.Second) + return duration.String() +} + +func duration(sec interface{}) string { + var n int64 + switch value := sec.(type) { + default: + n = 0 + case string: + n, _ = strconv.ParseInt(value, 10, 64) + case int64: + n = value + } + return (time.Duration(n) * time.Second).String() +} + +func durationRound(duration interface{}) string { + var d time.Duration + switch duration := duration.(type) { + default: + d = 0 + case string: + d, _ = time.ParseDuration(duration) + case int64: + d = time.Duration(duration) + case time.Time: + d = time.Since(duration) + } + + u := uint64(d) + neg := d < 0 + if neg { + u = -u + } + + var ( + year = uint64(time.Hour) * 24 * 365 + month = uint64(time.Hour) * 24 * 30 + day = uint64(time.Hour) * 24 + hour = uint64(time.Hour) + minute = uint64(time.Minute) + second = uint64(time.Second) + ) + switch { + case u > year: + return strconv.FormatUint(u/year, 10) + "y" + case u > month: + return strconv.FormatUint(u/month, 10) + "mo" + case u > day: + return strconv.FormatUint(u/day, 10) + "d" + case u > hour: + return strconv.FormatUint(u/hour, 10) + "h" + case u > minute: + return strconv.FormatUint(u/minute, 10) + "m" + case u > second: + return strconv.FormatUint(u/second, 10) + "s" + } + return "0s" +} + +func toDate(fmt, str string) time.Time { + t, _ := time.ParseInLocation(fmt, str, time.Local) + return t +} + +func mustToDate(fmt, str string) (time.Time, error) { + return time.ParseInLocation(fmt, str, time.Local) +} + +func unixEpoch(date time.Time) string { + return strconv.FormatInt(date.Unix(), 10) +} diff --git a/service/alerting/funcs/function.go b/service/alerting/funcs/function.go new file mode 100644 index 00000000..7eeaac87 --- /dev/null +++ b/service/alerting/funcs/function.go @@ -0,0 +1,23 @@ +/* Copyright © INFINI Ltd. All rights reserved. + * web: https://infinilabs.com + * mail: hello#infini.ltd */ + +package funcs + +import "text/template" + +func GenericFuncMap() template.FuncMap { + gfm := make(map[string]interface{}, len(genericMap)) + for k, v := range genericMap { + gfm[k] = v + } + return gfm +} + +var genericMap = map[string]interface{}{ + "hello": func() string { return "Hello!" }, + "format_bytes": formatBytes, + "to_fixed": toFixed, + "date": date, + "date_in_zone": dateInZone, +} diff --git a/service/alerting/funcs/numberic.go b/service/alerting/funcs/numberic.go new file mode 100644 index 00000000..daf7a74b --- /dev/null +++ b/service/alerting/funcs/numberic.go @@ -0,0 +1,11 @@ +/* Copyright © INFINI Ltd. All rights reserved. + * web: https://infinilabs.com + * mail: hello#infini.ltd */ + +package funcs + +import "infini.sh/framework/core/util" + +func toFixed(precision int, num float64) float64{ + return util.ToFixed(num, precision) +}