feat: survey 包的 Analyzer 分析器增加大量辅助函数

This commit is contained in:
kercylan98 2023-11-06 20:26:12 +08:00
parent 589a424491
commit 85176f32f9
2 changed files with 203 additions and 13 deletions

View File

@ -1,13 +1,14 @@
package survey package survey
import ( import (
"github.com/tidwall/gjson"
"strings" "strings"
"sync" "sync"
) )
// Analyzer 分析器 // Analyzer 分析器
type Analyzer struct { type Analyzer struct {
v map[string]float64 // 记录了每个 key 的当前值 v map[string]any // 记录了每个 key 的当前值
vc map[string]int64 // 记录了每个 key 生效的计数数量 vc map[string]int64 // 记录了每个 key 生效的计数数量
repeat map[string]struct{} // 去重信息 repeat map[string]struct{} // 去重信息
subs map[string]*Analyzer subs map[string]*Analyzer
@ -29,7 +30,106 @@ func (slf *Analyzer) Sub(key string) *Analyzer {
return sub 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 的值 // Increase 在指定 key 现有值的基础上增加 recordKey 的值
// - 当分析器已经记录过相同 key 的值时,会根据已有的值类型进行不同处理
//
// 处理方式:
// - 当已有值类型为 string 时,将会使用新的值的 string 类型进行覆盖
// - 当已有值类型为 float64 时,当新的值类型不为 float64 时,将会被忽略
func (slf *Analyzer) Increase(key string, record R, recordKey string) { func (slf *Analyzer) Increase(key string, record R, recordKey string) {
slf.m.Lock() slf.m.Lock()
defer slf.m.Unlock() defer slf.m.Unlock()
@ -37,10 +137,31 @@ func (slf *Analyzer) Increase(key string, record R, recordKey string) {
return return
} }
if slf.v == nil { if slf.v == nil {
slf.v = make(map[string]float64) slf.v = make(map[string]any)
slf.vc = make(map[string]int64) 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]++ slf.vc[key]++
} }
@ -49,11 +170,20 @@ func (slf *Analyzer) IncreaseValue(key string, value float64) {
slf.m.Lock() slf.m.Lock()
defer slf.m.Unlock() defer slf.m.Unlock()
if slf.v == nil { if slf.v == nil {
slf.v = make(map[string]float64) slf.v = make(map[string]any)
slf.vc = make(map[string]int64) slf.vc = make(map[string]int64)
} }
slf.v[key] += value v, exist := slf.v[key]
slf.vc[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 相同时,不会增加 // IncreaseNonRepeat 在指定 key 现有值的基础上增加 recordKey 的值,但是当去重维度 dimension 相同时,不会增加
@ -99,3 +229,33 @@ func (slf *Analyzer) IncreaseValueNonRepeat(key string, record R, value float64,
slf.m.Unlock() slf.m.Unlock()
slf.IncreaseValue(key, value) 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 ""
}

View File

@ -2,6 +2,7 @@ package survey
import ( import (
"github.com/kercylan98/minotaur/utils/super" "github.com/kercylan98/minotaur/utils/super"
"strings"
) )
func newReport(analyzer *Analyzer) *Report { func newReport(analyzer *Analyzer) *Report {
@ -23,15 +24,23 @@ func newReport(analyzer *Analyzer) *Report {
// Report 分析报告 // Report 分析报告
type Report struct { type Report struct {
analyzer *Analyzer analyzer *Analyzer
Name string // 报告名称(默认为 ROOT Name string // 报告名称(默认为 ROOT
Values map[string]float64 `json:"Values,omitempty"` Values map[string]any `json:"Values,omitempty"`
Counter map[string]int64 `json:"Count,omitempty"` Counter map[string]int64 `json:"Count,omitempty"`
Subs []*Report `json:"Reports,omitempty"` Subs []*Report `json:"Reports,omitempty"`
} }
// Avg 计算平均值 // Avg 计算平均值
func (slf *Report) Avg(key string) float64 { 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 的计数次数 // Count 获取特定 key 的计数次数
@ -43,7 +52,15 @@ func (slf *Report) Count(key string) int64 {
func (slf *Report) Sum(keys ...string) float64 { func (slf *Report) Sum(keys ...string) float64 {
var sum float64 var sum float64
for _, key := range keys { 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 return sum
} }
@ -58,6 +75,19 @@ func (slf *Report) Sub(name string) *Report {
return nil 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 仅保留特定名称子报告 // ReserveSub 仅保留特定名称子报告
func (slf *Report) ReserveSub(names ...string) *Report { func (slf *Report) ReserveSub(names ...string) *Report {
report := newReport(slf.analyzer) report := newReport(slf.analyzer)
@ -78,7 +108,7 @@ func (slf *Report) ReserveSub(names ...string) *Report {
return report return report
} }
// FilterSub 过滤特定名称的子报告 // FilterSub 将特定名称的子报告过滤掉
func (slf *Report) FilterSub(names ...string) *Report { func (slf *Report) FilterSub(names ...string) *Report {
report := newReport(slf.analyzer) report := newReport(slf.analyzer)
var newSub []*Report var newSub []*Report