mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
This adds the remaining two stats endpoints: `/v2/stats/self`, for various statistics on the EtcdServer, and `/v2/stats/leader`, for statistics on a leader's followers. By and large most of the stats code is copied across from 0.4.x, updated where necessary to integrate with the new decoupling of raft from transport. This does not satisfactorily resolve the question of name vs ID. In the old world, names were unique in the cluster and transmitted over the wire, so they could be used safely in all statistics. In the new world, a given EtcdServer only knows its own name, and it is instead IDs that are communicated among the cluster members. Hence in most places here we simply substitute a string-encoded ID in place of name, and only where possible do we retain the actual given name of the EtcdServer.
69 lines
2.0 KiB
Go
69 lines
2.0 KiB
Go
package stats
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
// LeaderStats is used by the leader in an etcd cluster, and encapsulates
|
|
// statistics about communication with its followers
|
|
type LeaderStats struct {
|
|
// TODO(jonboulle): clarify that these are IDs, not names
|
|
Leader string `json:"leader"`
|
|
Followers map[string]*FollowerStats `json:"followers"`
|
|
}
|
|
|
|
// NewLeaderStats generates a new LeaderStats with the given id as leader
|
|
func NewLeaderStats(id string) *LeaderStats {
|
|
return &LeaderStats{
|
|
Leader: id,
|
|
Followers: make(map[string]*FollowerStats),
|
|
}
|
|
}
|
|
|
|
// FollowerStats encapsulates various statistics about a follower in an etcd cluster
|
|
type FollowerStats struct {
|
|
Latency struct {
|
|
Current float64 `json:"current"`
|
|
Average float64 `json:"average"`
|
|
averageSquare float64
|
|
StandardDeviation float64 `json:"standardDeviation"`
|
|
Minimum float64 `json:"minimum"`
|
|
Maximum float64 `json:"maximum"`
|
|
} `json:"latency"`
|
|
|
|
Counts struct {
|
|
Fail uint64 `json:"fail"`
|
|
Success uint64 `json:"success"`
|
|
} `json:"counts"`
|
|
}
|
|
|
|
// Succ updates the FollowerStats with a successful send
|
|
func (fs *FollowerStats) Succ(d time.Duration) {
|
|
total := float64(fs.Counts.Success) * fs.Latency.Average
|
|
totalSquare := float64(fs.Counts.Success) * fs.Latency.averageSquare
|
|
|
|
fs.Counts.Success++
|
|
|
|
fs.Latency.Current = float64(d) / (1000000.0)
|
|
|
|
if fs.Latency.Current > fs.Latency.Maximum {
|
|
fs.Latency.Maximum = fs.Latency.Current
|
|
}
|
|
|
|
if fs.Latency.Current < fs.Latency.Minimum {
|
|
fs.Latency.Minimum = fs.Latency.Current
|
|
}
|
|
|
|
fs.Latency.Average = (total + fs.Latency.Current) / float64(fs.Counts.Success)
|
|
fs.Latency.averageSquare = (totalSquare + fs.Latency.Current*fs.Latency.Current) / float64(fs.Counts.Success)
|
|
|
|
// sdv = sqrt(avg(x^2) - avg(x)^2)
|
|
fs.Latency.StandardDeviation = math.Sqrt(fs.Latency.averageSquare - fs.Latency.Average*fs.Latency.Average)
|
|
}
|
|
|
|
// Fail updates the FollowerStats with an unsuccessful send
|
|
func (fs *FollowerStats) Fail() {
|
|
fs.Counts.Fail++
|
|
}
|