app/vmselect/querystats: show the number of matching queries in the top by average duration and in the top by summary duration

This should help debugging slow queries.
This commit is contained in:
Aliaksandr Valialkin 2021-02-28 19:40:16 +02:00
parent 0165063362
commit 3b1c2f03c3

View file

@ -108,8 +108,8 @@ func (qst *queryStatsTracker) writeJSONQueryStats(w io.Writer, topN int, apFilte
fmt.Fprintf(w, `],"topByAvgDuration":[`) fmt.Fprintf(w, `],"topByAvgDuration":[`)
topByAvgDuration := qst.getTopByAvgDuration(topN, apFilter, maxLifetime) topByAvgDuration := qst.getTopByAvgDuration(topN, apFilter, maxLifetime)
for i, r := range topByAvgDuration { for i, r := range topByAvgDuration {
fmt.Fprintf(w, `{"accountID":%d,"projectID":%d,"query":%q,"timeRangeSeconds":%d,"avgDurationSeconds":%.3f}`, fmt.Fprintf(w, `{"accountID":%d,"projectID":%d,"query":%q,"timeRangeSeconds":%d,"avgDurationSeconds":%.3f,"count":%d}`,
r.accountID, r.projectID, r.query, r.timeRangeSecs, r.duration.Seconds()) r.accountID, r.projectID, r.query, r.timeRangeSecs, r.duration.Seconds(), r.count)
if i+1 < len(topByAvgDuration) { if i+1 < len(topByAvgDuration) {
fmt.Fprintf(w, `,`) fmt.Fprintf(w, `,`)
} }
@ -117,8 +117,8 @@ func (qst *queryStatsTracker) writeJSONQueryStats(w io.Writer, topN int, apFilte
fmt.Fprintf(w, `],"topBySumDuration":[`) fmt.Fprintf(w, `],"topBySumDuration":[`)
topBySumDuration := qst.getTopBySumDuration(topN, apFilter, maxLifetime) topBySumDuration := qst.getTopBySumDuration(topN, apFilter, maxLifetime)
for i, r := range topBySumDuration { for i, r := range topBySumDuration {
fmt.Fprintf(w, `{"accountID":%d,"projectID":%d,"query":%q,"timeRangeSeconds":%d,"sumDurationSeconds":%.3f}`, fmt.Fprintf(w, `{"accountID":%d,"projectID":%d,"query":%q,"timeRangeSeconds":%d,"sumDurationSeconds":%.3f,"count":%d}`,
r.accountID, r.projectID, r.query, r.timeRangeSecs, r.duration.Seconds()) r.accountID, r.projectID, r.query, r.timeRangeSecs, r.duration.Seconds(), r.count)
if i+1 < len(topBySumDuration) { if i+1 < len(topBySumDuration) {
fmt.Fprintf(w, `,`) fmt.Fprintf(w, `,`)
} }
@ -236,6 +236,7 @@ func (qst *queryStatsTracker) getTopByAvgDuration(topN int, apFilter *accountPro
query: k.query, query: k.query,
timeRangeSecs: k.timeRangeSecs, timeRangeSecs: k.timeRangeSecs,
duration: ks.sum / time.Duration(ks.count), duration: ks.sum / time.Duration(ks.count),
count: ks.count,
}) })
} }
sort.Slice(a, func(i, j int) bool { sort.Slice(a, func(i, j int) bool {
@ -253,28 +254,37 @@ type queryStatByDuration struct {
query string query string
timeRangeSecs int64 timeRangeSecs int64
duration time.Duration duration time.Duration
count int
} }
func (qst *queryStatsTracker) getTopBySumDuration(topN int, apFilter *accountProjectFilter, maxLifetime time.Duration) []queryStatByDuration { func (qst *queryStatsTracker) getTopBySumDuration(topN int, apFilter *accountProjectFilter, maxLifetime time.Duration) []queryStatByDuration {
currentTime := time.Now() currentTime := time.Now()
qst.mu.Lock() qst.mu.Lock()
m := make(map[queryStatKey]time.Duration) type countDuration struct {
count int
sum time.Duration
}
m := make(map[queryStatKey]countDuration)
for _, r := range qst.a { for _, r := range qst.a {
if r.matches(apFilter, currentTime, maxLifetime) { if r.matches(apFilter, currentTime, maxLifetime) {
k := r.key() k := r.key()
m[k] = m[k] + r.duration kd := m[k]
kd.count++
kd.sum += r.duration
m[k] = kd
} }
} }
qst.mu.Unlock() qst.mu.Unlock()
var a []queryStatByDuration var a []queryStatByDuration
for k, d := range m { for k, kd := range m {
a = append(a, queryStatByDuration{ a = append(a, queryStatByDuration{
accountID: k.accountID, accountID: k.accountID,
projectID: k.projectID, projectID: k.projectID,
query: k.query, query: k.query,
timeRangeSecs: k.timeRangeSecs, timeRangeSecs: k.timeRangeSecs,
duration: d, duration: kd.sum,
count: kd.count,
}) })
} }
sort.Slice(a, func(i, j int) bool { sort.Slice(a, func(i, j int) bool {