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  }