feat: survey 包的 Analyzer 分析器增加大量辅助函数
This commit is contained in:
parent
589a424491
commit
85176f32f9
|
@ -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 ""
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue