From 85176f32f918b3ad02ace7fa6217b55b6d457d0e Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Mon, 6 Nov 2023 20:26:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20survey=20=E5=8C=85=E7=9A=84=20Analyzer?= =?UTF-8?q?=20=E5=88=86=E6=9E=90=E5=99=A8=E5=A2=9E=E5=8A=A0=E5=A4=A7?= =?UTF-8?q?=E9=87=8F=E8=BE=85=E5=8A=A9=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/log/survey/analyzer.go | 172 +++++++++++++++++++++++++++++++++-- utils/log/survey/report.go | 44 +++++++-- 2 files changed, 203 insertions(+), 13 deletions(-) diff --git a/utils/log/survey/analyzer.go b/utils/log/survey/analyzer.go index 7cdf9ae..c626820 100644 --- a/utils/log/survey/analyzer.go +++ b/utils/log/survey/analyzer.go @@ -1,13 +1,14 @@ package survey import ( + "github.com/tidwall/gjson" "strings" "sync" ) // Analyzer 分析器 type Analyzer struct { - v map[string]float64 // 记录了每个 key 的当前值 + v map[string]any // 记录了每个 key 的当前值 vc map[string]int64 // 记录了每个 key 生效的计数数量 repeat map[string]struct{} // 去重信息 subs map[string]*Analyzer @@ -29,7 +30,106 @@ func (slf *Analyzer) Sub(key string) *Analyzer { return sub } +// SetValueIfGreaterThan 设置指定 key 的值,当新值大于旧值时 +// - 当已有值不为 float64 时,将会被忽略 +func (slf *Analyzer) SetValueIfGreaterThan(key string, value float64) { + slf.m.Lock() + defer slf.m.Unlock() + if slf.v == nil { + slf.v = make(map[string]any) + slf.vc = make(map[string]int64) + } + v, exist := slf.v[key] + if !exist { + slf.v[key] = value + slf.vc[key]++ + return + } + switch v := v.(type) { + case float64: + if v < value { + slf.v[key] = value + slf.vc[key]++ + } + } +} + +// SetValueIfLessThan 设置指定 key 的值,当新值小于旧值时 +// - 当已有值不为 float64 时,将会被忽略 +func (slf *Analyzer) SetValueIfLessThan(key string, value float64) { + slf.m.Lock() + defer slf.m.Unlock() + if slf.v == nil { + slf.v = make(map[string]any) + slf.vc = make(map[string]int64) + } + v, exist := slf.v[key] + if !exist { + slf.v[key] = value + slf.vc[key]++ + return + } + switch v := v.(type) { + case float64: + if v > value { + slf.v[key] = value + slf.vc[key]++ + } + } +} + +// SetValueIf 当表达式满足的时候将设置指定 key 的值为 value +func (slf *Analyzer) SetValueIf(key string, expression bool, value float64) { + if !expression { + return + } + slf.m.Lock() + defer slf.m.Unlock() + slf.v[key] = value + slf.vc[key]++ +} + +// SetValueStringIf 当表达式满足的时候将设置指定 key 的值为 value +func (slf *Analyzer) SetValueStringIf(key string, expression bool, value string) { + if !expression { + return + } + slf.m.Lock() + defer slf.m.Unlock() + slf.v[key] = value + slf.vc[key]++ +} + +// SetValue 设置指定 key 的值 +func (slf *Analyzer) SetValue(key string, value float64) { + slf.m.Lock() + defer slf.m.Unlock() + if slf.v == nil { + slf.v = make(map[string]any) + slf.vc = make(map[string]int64) + } + slf.v[key] = value + slf.vc[key]++ +} + +// SetValueString 设置指定 key 的值 +func (slf *Analyzer) SetValueString(key string, value string) { + slf.m.Lock() + defer slf.m.Unlock() + if slf.v == nil { + slf.v = make(map[string]any) + slf.vc = make(map[string]int64) + } + slf.v[key] = value + slf.vc[key]++ +} + // Increase 在指定 key 现有值的基础上增加 recordKey 的值 +// - 当分析器已经记录过相同 key 的值时,会根据已有的值类型进行不同处理 +// +// 处理方式: +// - 当已有值类型为 string 时,将会使用新的值的 string 类型进行覆盖 +// - 当已有值类型为 float64 时,当新的值类型不为 float64 时,将会被忽略 func (slf *Analyzer) Increase(key string, record R, recordKey string) { slf.m.Lock() defer slf.m.Unlock() @@ -37,10 +137,31 @@ func (slf *Analyzer) Increase(key string, record R, recordKey string) { return } if slf.v == nil { - slf.v = make(map[string]float64) + slf.v = make(map[string]any) slf.vc = make(map[string]int64) } - slf.v[key] += record.GetFloat64(recordKey) + value, exist := slf.v[key] + if !exist { + result := gjson.Get(string(record), recordKey) + switch result.Type { + case gjson.String: + slf.v[key] = result.String() + case gjson.Number: + slf.v[key] = result.Float() + default: + return + } + slf.vc[key]++ + return + } + switch v := value.(type) { + case string: + slf.v[key] = record.GetString(recordKey) + case float64: + slf.v[key] = v + record.GetFloat64(recordKey) + default: + return + } slf.vc[key]++ } @@ -49,11 +170,20 @@ func (slf *Analyzer) IncreaseValue(key string, value float64) { slf.m.Lock() defer slf.m.Unlock() if slf.v == nil { - slf.v = make(map[string]float64) + slf.v = make(map[string]any) slf.vc = make(map[string]int64) } - slf.v[key] += value - slf.vc[key]++ + v, exist := slf.v[key] + if !exist { + slf.v[key] = value + slf.vc[key]++ + return + } + switch v := v.(type) { + case float64: + slf.v[key] = v + value + slf.vc[key]++ + } } // IncreaseNonRepeat 在指定 key 现有值的基础上增加 recordKey 的值,但是当去重维度 dimension 相同时,不会增加 @@ -99,3 +229,33 @@ func (slf *Analyzer) IncreaseValueNonRepeat(key string, record R, value float64, slf.m.Unlock() slf.IncreaseValue(key, value) } + +// GetValue 获取当前记录的值 +func (slf *Analyzer) GetValue(key string) float64 { + slf.m.Lock() + defer slf.m.Unlock() + value, exist := slf.v[key] + if !exist { + return 0 + } + switch v := value.(type) { + case float64: + return v + } + return 0 +} + +// GetValueString 获取当前记录的值 +func (slf *Analyzer) GetValueString(key string) string { + slf.m.Lock() + defer slf.m.Unlock() + value, exist := slf.v[key] + if !exist { + return "" + } + switch v := value.(type) { + case string: + return v + } + return "" +} diff --git a/utils/log/survey/report.go b/utils/log/survey/report.go index 111e6ab..3cfac94 100644 --- a/utils/log/survey/report.go +++ b/utils/log/survey/report.go @@ -2,6 +2,7 @@ package survey import ( "github.com/kercylan98/minotaur/utils/super" + "strings" ) func newReport(analyzer *Analyzer) *Report { @@ -23,15 +24,23 @@ func newReport(analyzer *Analyzer) *Report { // Report 分析报告 type Report struct { analyzer *Analyzer - Name string // 报告名称(默认为 ROOT) - Values map[string]float64 `json:"Values,omitempty"` - Counter map[string]int64 `json:"Count,omitempty"` - Subs []*Report `json:"Reports,omitempty"` + Name string // 报告名称(默认为 ROOT) + Values map[string]any `json:"Values,omitempty"` + Counter map[string]int64 `json:"Count,omitempty"` + Subs []*Report `json:"Reports,omitempty"` } // Avg 计算平均值 func (slf *Report) Avg(key string) float64 { - return slf.Values[key] / float64(slf.Counter[key]) + value, exist := slf.Values[key] + if !exist { + return 0 + } + valF, ok := value.(float64) + if !ok { + return 0 + } + return valF / float64(slf.Counter[key]) } // Count 获取特定 key 的计数次数 @@ -43,7 +52,15 @@ func (slf *Report) Count(key string) int64 { func (slf *Report) Sum(keys ...string) float64 { var sum float64 for _, key := range keys { - sum += slf.Values[key] + value, exist := slf.Values[key] + if !exist { + continue + } + valF, ok := value.(float64) + if !ok { + continue + } + sum += valF } return sum } @@ -58,6 +75,19 @@ func (slf *Report) Sub(name string) *Report { return nil } +// ReserveSubByPrefix 仅保留特定前缀的子报告 +func (slf *Report) ReserveSubByPrefix(prefix string) *Report { + report := newReport(slf.analyzer) + var newSub []*Report + for _, sub := range slf.Subs { + if strings.HasPrefix(sub.Name, prefix) { + newSub = append(newSub, sub) + } + } + report.Subs = newSub + return report +} + // ReserveSub 仅保留特定名称子报告 func (slf *Report) ReserveSub(names ...string) *Report { report := newReport(slf.analyzer) @@ -78,7 +108,7 @@ func (slf *Report) ReserveSub(names ...string) *Report { return report } -// FilterSub 过滤特定名称的子报告 +// FilterSub 将特定名称的子报告过滤掉 func (slf *Report) FilterSub(names ...string) *Report { report := newReport(slf.analyzer) var newSub []*Report