From 405f60e31659ea685201a7ee24eb80aab704f9ec Mon Sep 17 00:00:00 2001 From: Shafreeck Sea Date: Tue, 5 Nov 2019 17:06:03 +0800 Subject: [PATCH] cluster: fix potential panic may be caused by div 0 Signed-off-by: Shafreeck Sea --- server/cluster_stat.go | 44 ++++++++++++++++++++++++++++++++----- server/cluster_stat_test.go | 4 ++-- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/server/cluster_stat.go b/server/cluster_stat.go index b51c1d1c51c2..50918703d61b 100644 --- a/server/cluster_stat.go +++ b/server/cluster_stat.go @@ -18,6 +18,8 @@ import ( "time" "github.com/pingcap/kvproto/pkg/pdpb" + "github.com/pingcap/log" + "go.uber.org/zap" ) // Cluster State Statistics @@ -132,7 +134,11 @@ func (s *StatEntries) CPU(steps int) float64 { if steps > s.total { steps = s.total } + if steps == 0 { + return float64(0) + } + log.Debug("caculate CPU", zap.Int("steps", steps)) usage := 0.0 idx := (s.total - 1) % cap for i := 0; i < steps; i++ { @@ -148,6 +154,9 @@ func (s *StatEntries) CPU(steps int) float64 { func cpuUsageAll(usages []*pdpb.RecordPair) float64 { sum := 0.0 + if len(usages) == 0 { + return sum + } for _, usage := range usages { sum += float64(usage.Value) } @@ -164,6 +173,9 @@ func (s *StatEntries) Keys(steps int) (int64, int64) { if steps > s.total { steps = s.total } + if steps == 0 { + return 0, 0 + } var read, written int64 idx := (s.total - 1) % cap @@ -189,6 +201,9 @@ func (s *StatEntries) Bytes(steps int) (int64, int64) { if steps > s.total { steps = s.total } + if steps == 0 { + return 0, 0 + } var read, written int64 idx := (s.total - 1) % cap for i := 0; i < steps; i++ { @@ -226,13 +241,17 @@ func (cst *ClusterStatEntries) Append(stat *StatEntry) { defer cst.m.Unlock() // update interval - interval := int64(stat.Interval.GetEndTimestamp() - - stat.Interval.GetStartTimestamp()) - if interval == 0 { + start, end := stat.Interval.GetStartTimestamp(), + stat.Interval.GetEndTimestamp() + interval := int64(end - start) + if start == 0 || end == 0 || interval == 0 { interval = DefaultIntervalHint } - cst.interval = (cst.interval*cst.total + interval) / - (cst.total + 1) + if cst.total == 0 { + cst.interval = interval + } else { + cst.interval = cst.interval + (interval-cst.interval)/cst.total + } cst.total++ // append the entry @@ -260,6 +279,11 @@ func (cst *ClusterStatEntries) CPU(d time.Duration, excludes ...uint64) float64 cst.m.RLock() defer cst.m.RUnlock() + // no entries have been collected + if cst.total == 0 { + return 0 + } + steps := int64(d) / cst.interval sum := 0.0 @@ -277,6 +301,11 @@ func (cst *ClusterStatEntries) CPU(d time.Duration, excludes ...uint64) float64 func (cst *ClusterStatEntries) Keys(d time.Duration, excludes ...uint64) (int64, int64) { cst.m.RLock() defer cst.m.RUnlock() + // no entries have been collected + if cst.total == 0 { + return 0, 0 + } + steps := int64(d) / cst.interval var read, written int64 @@ -296,6 +325,11 @@ func (cst *ClusterStatEntries) Keys(d time.Duration, excludes ...uint64) (int64, func (cst *ClusterStatEntries) Bytes(d time.Duration, excludes ...uint64) (int64, int64) { cst.m.RLock() defer cst.m.RUnlock() + // no entries have been collected + if cst.total == 0 { + return 0, 0 + } + steps := int64(d) / cst.interval var read, written int64 diff --git a/server/cluster_stat_test.go b/server/cluster_stat_test.go index bcd808242c41..55e410745b4b 100644 --- a/server/cluster_stat_test.go +++ b/server/cluster_stat_test.go @@ -172,8 +172,8 @@ func (s *testClusterStatSuite) TestClusterStatCPU(c *C) { // heartbeat per 10s interval := &pdpb.TimeInterval{ - StartTimestamp: 0, - EndTimestamp: 10 * uint64(time.Second), + StartTimestamp: 1, + EndTimestamp: 11, } // the average cpu usage is 20% usages := cpu(20)