Skip to content

Commit 0d8afaa

Browse files
Add NewAggregateClass() to roll up classes. Test on latest two Go versions.
1 parent 2194330 commit 0d8afaa

File tree

4 files changed

+139
-6
lines changed

4 files changed

+139
-6
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
language: go
22
go:
3-
- 1.7
3+
- "1.11"
4+
- "1.12"

class.go

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2017 Daniel Nichter
2+
Copyright 2017, 2019 Daniel Nichter
33
Copyright 2014-2016 Percona LLC and/or its affiliates
44
*/
55

@@ -17,11 +17,11 @@ type Class struct {
1717
Id string // 32-character hex checksum of fingerprint
1818
Fingerprint string // canonical form of query: values replaced with "?"
1919
Metrics Metrics // statistics for each metric, e.g. max Query_time
20-
TotalQueries uint // total number of queries in class
20+
TotalQueries uint64 // total number of queries in class
2121
UniqueQueries uint // unique number of queries in class
2222
Example *Example `json:",omitempty"` // sample query with max Query_time
2323
// --
24-
outliers uint
24+
outliers uint64
2525
lastDb string
2626
sample bool
2727
}
@@ -91,8 +91,69 @@ func (c *Class) Finalize(rateLimit uint) {
9191
rateLimit = 1
9292
}
9393
c.Metrics.Finalize(rateLimit)
94-
c.TotalQueries = (c.TotalQueries * rateLimit) + c.outliers
94+
c.TotalQueries = (c.TotalQueries * uint64(rateLimit)) + c.outliers
9595
if c.Example.QueryTime == 0 {
9696
c.Example = nil
9797
}
9898
}
99+
100+
// NewAggregateClass makes a new Class from the given member classes.
101+
func NewAggregateClass(id, fingerprint string, members []*Class) *Class {
102+
aggClass := &Class{
103+
Id: id,
104+
Fingerprint: fingerprint,
105+
Metrics: NewMetrics(),
106+
UniqueQueries: uint(len(members)),
107+
TotalQueries: 0,
108+
}
109+
110+
for _, memberClass := range members {
111+
aggClass.TotalQueries += memberClass.TotalQueries
112+
113+
for newMetric, newStats := range memberClass.Metrics.TimeMetrics {
114+
stats, ok := aggClass.Metrics.TimeMetrics[newMetric]
115+
if !ok {
116+
m := *newStats
117+
aggClass.Metrics.TimeMetrics[newMetric] = &m
118+
} else {
119+
stats.Sum += newStats.Sum
120+
stats.Avg = stats.Sum / float64(aggClass.TotalQueries)
121+
if newStats.Min < stats.Min {
122+
stats.Min = newStats.Min
123+
}
124+
if newStats.Max > stats.Max {
125+
stats.Max = newStats.Max
126+
}
127+
}
128+
}
129+
130+
for newMetric, newStats := range memberClass.Metrics.NumberMetrics {
131+
stats, ok := aggClass.Metrics.NumberMetrics[newMetric]
132+
if !ok {
133+
m := *newStats
134+
aggClass.Metrics.NumberMetrics[newMetric] = &m
135+
} else {
136+
stats.Sum += newStats.Sum
137+
stats.Avg = stats.Sum / aggClass.TotalQueries
138+
if newStats.Min < stats.Min {
139+
stats.Min = newStats.Min
140+
}
141+
if newStats.Max > stats.Max {
142+
stats.Max = newStats.Max
143+
}
144+
}
145+
}
146+
147+
for newMetric, newStats := range memberClass.Metrics.BoolMetrics {
148+
stats, ok := aggClass.Metrics.BoolMetrics[newMetric]
149+
if !ok {
150+
m := *newStats
151+
aggClass.Metrics.BoolMetrics[newMetric] = &m
152+
} else {
153+
stats.Sum += newStats.Sum
154+
}
155+
}
156+
}
157+
158+
return aggClass
159+
}

class_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2019 Daniel Nichter
2+
3+
package slowlog_test
4+
5+
import (
6+
"testing"
7+
8+
"github.com/go-mysql/slowlog"
9+
"github.com/go-test/deep"
10+
)
11+
12+
func TestAggregateClass(t *testing.T) {
13+
c1 := &slowlog.Class{
14+
Id: "111",
15+
Fingerprint: "select *",
16+
TotalQueries: 5,
17+
UniqueQueries: 1,
18+
Metrics: slowlog.Metrics{
19+
TimeMetrics: map[string]*slowlog.TimeStats{
20+
"Query_time": {Sum: 1.123, Min: 0.100, Avg: 0.2, Med: 0.155, P95: 0.101, Max: 3.222},
21+
},
22+
NumberMetrics: map[string]*slowlog.NumberStats{
23+
"Rows_sent": {Sum: 90, Min: 4, Avg: 18, Med: 7, P95: 8, Max: 10},
24+
},
25+
BoolMetrics: map[string]*slowlog.BoolStats{
26+
"Full_scan": {Sum: 10},
27+
},
28+
},
29+
}
30+
c2 := &slowlog.Class{
31+
Id: "222",
32+
Fingerprint: "insert t",
33+
TotalQueries: 4,
34+
UniqueQueries: 1,
35+
Metrics: slowlog.Metrics{
36+
TimeMetrics: map[string]*slowlog.TimeStats{
37+
"Query_time": {Sum: 1.123, Min: 0.111, Avg: 0.2, Med: 5.555, P95: 9.999, Max: 5.222},
38+
},
39+
NumberMetrics: map[string]*slowlog.NumberStats{
40+
"Rows_sent": {Sum: 100, Min: 0, Avg: 25, Med: 7, P95: 8, Max: 11},
41+
},
42+
BoolMetrics: map[string]*slowlog.BoolStats{
43+
"Full_scan": {Sum: 10},
44+
},
45+
},
46+
}
47+
48+
expect := &slowlog.Class{
49+
Id: "anId",
50+
Fingerprint: "aFingerprint",
51+
TotalQueries: 9,
52+
UniqueQueries: 2,
53+
Metrics: slowlog.Metrics{
54+
TimeMetrics: map[string]*slowlog.TimeStats{
55+
"Query_time": {Sum: 2.246, Min: 0.100, Avg: 0.2495555, Med: 0.155, P95: 0.101, Max: 5.222},
56+
},
57+
NumberMetrics: map[string]*slowlog.NumberStats{
58+
"Rows_sent": {Sum: 190, Min: 0, Avg: 21, Med: 7, P95: 8, Max: 11},
59+
},
60+
BoolMetrics: map[string]*slowlog.BoolStats{
61+
"Full_scan": {Sum: 20},
62+
},
63+
},
64+
}
65+
66+
got := slowlog.NewAggregateClass("anId", "aFingerprint", []*slowlog.Class{c1, c2})
67+
68+
if diff := deep.Equal(got, expect); diff != nil {
69+
t.Error(diff)
70+
}
71+
}

parser_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ func TestParserSlowLog001StartOffset(t *testing.T) {
13111311
func TestParserSlowLog015(t *testing.T) {
13121312
got := parseSlowLog(t, "slow015.log", noOptions)
13131313
if len(got) != 2 {
1314-
t.Error("got %d expected 2", len(got))
1314+
t.Errorf("got %d expected 2", len(got))
13151315
}
13161316
}
13171317

0 commit comments

Comments
 (0)