Skip to content

Commit

Permalink
feat: survey 包的 Analyzer 分析器增加大量辅助函数
Browse files Browse the repository at this point in the history
  • Loading branch information
kercylan98 committed Nov 6, 2023
1 parent 589a424 commit 85176f3
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 13 deletions.
172 changes: 166 additions & 6 deletions utils/log/survey/analyzer.go
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -29,18 +30,138 @@ 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()
if !record.Exist(recordKey) {
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]++
}

Expand All @@ -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 相同时,不会增加
Expand Down Expand Up @@ -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 ""
}
44 changes: 37 additions & 7 deletions utils/log/survey/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package survey

import (
"github.com/kercylan98/minotaur/utils/super"
"strings"
)

func newReport(analyzer *Analyzer) *Report {
Expand All @@ -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 的计数次数
Expand All @@ -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
}
Expand All @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit 85176f3

Please sign in to comment.