github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/dbs/query_stat_manager.go (about) 1 // Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. 2 3 package dbs 4 5 import ( 6 "fmt" 7 teaconst "github.com/TeaOSLab/EdgeNode/internal/const" 8 "github.com/TeaOSLab/EdgeNode/internal/events" 9 "github.com/TeaOSLab/EdgeNode/internal/goman" 10 "github.com/iwind/TeaGo/logs" 11 "sort" 12 "strings" 13 "sync" 14 "time" 15 ) 16 17 func init() { 18 if !teaconst.IsMain { 19 return 20 } 21 22 var ticker = time.NewTicker(5 * time.Second) 23 24 events.On(events.EventLoaded, func() { 25 if teaconst.EnableDBStat { 26 goman.New(func() { 27 for range ticker.C { 28 var stats = []string{} 29 for _, stat := range SharedQueryStatManager.TopN(10) { 30 var avg = stat.CostTotal / float64(stat.Calls) 31 var query = stat.Query 32 if len(query) > 128 { 33 query = query[:128] 34 } 35 stats = append(stats, fmt.Sprintf("%.2fms/%.2fms/%.2fms - %d - %s", stat.CostMin*1000, stat.CostMax*1000, avg*1000, stat.Calls, query)) 36 } 37 logs.Println("\n========== DB STATS ==========\n" + strings.Join(stats, "\n") + "\n=============================") 38 } 39 }) 40 } 41 }) 42 } 43 44 var SharedQueryStatManager = NewQueryStatManager() 45 46 type QueryStatManager struct { 47 statsMap map[string]*QueryStat // query => *QueryStat 48 locker sync.Mutex 49 } 50 51 func NewQueryStatManager() *QueryStatManager { 52 return &QueryStatManager{ 53 statsMap: map[string]*QueryStat{}, 54 } 55 } 56 57 func (this *QueryStatManager) AddQuery(query string) *QueryLabel { 58 return NewQueryLabel(this, query) 59 } 60 61 func (this *QueryStatManager) AddCost(query string, cost float64) { 62 this.locker.Lock() 63 defer this.locker.Unlock() 64 65 stat, ok := this.statsMap[query] 66 if !ok { 67 stat = NewQueryStat(query) 68 this.statsMap[query] = stat 69 } 70 stat.AddCost(cost) 71 } 72 73 func (this *QueryStatManager) TopN(n int) []*QueryStat { 74 this.locker.Lock() 75 defer this.locker.Unlock() 76 77 var stats = []*QueryStat{} 78 for _, stat := range this.statsMap { 79 stats = append(stats, stat) 80 } 81 sort.Slice(stats, func(i, j int) bool { 82 return stats[i].CostMax > stats[j].CostMax 83 }) 84 85 if len(stats) > n { 86 return stats[:n] 87 } 88 return stats 89 }