leader.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright 2015 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package stats
  15. import (
  16. "encoding/json"
  17. "math"
  18. "sync"
  19. "time"
  20. )
  21. // LeaderStats is used by the leader in an etcd cluster, and encapsulates
  22. // statistics about communication with its followers
  23. type LeaderStats struct {
  24. // Leader is the ID of the leader in the etcd cluster.
  25. // TODO(jonboulle): clarify that these are IDs, not names
  26. Leader string `json:"leader"`
  27. Followers map[string]*FollowerStats `json:"followers"`
  28. sync.Mutex
  29. }
  30. // NewLeaderStats generates a new LeaderStats with the given id as leader
  31. func NewLeaderStats(id string) *LeaderStats {
  32. return &LeaderStats{
  33. Leader: id,
  34. Followers: make(map[string]*FollowerStats),
  35. }
  36. }
  37. func (ls *LeaderStats) JSON() []byte {
  38. ls.Lock()
  39. stats := *ls
  40. ls.Unlock()
  41. b, err := json.Marshal(stats)
  42. // TODO(jonboulle): appropriate error handling?
  43. if err != nil {
  44. plog.Errorf("error marshalling leader stats (%v)", err)
  45. }
  46. return b
  47. }
  48. func (ls *LeaderStats) Follower(name string) *FollowerStats {
  49. ls.Lock()
  50. defer ls.Unlock()
  51. fs, ok := ls.Followers[name]
  52. if !ok {
  53. fs = &FollowerStats{}
  54. fs.Latency.Minimum = 1 << 63
  55. ls.Followers[name] = fs
  56. }
  57. return fs
  58. }
  59. // FollowerStats encapsulates various statistics about a follower in an etcd cluster
  60. type FollowerStats struct {
  61. Latency LatencyStats `json:"latency"`
  62. Counts CountsStats `json:"counts"`
  63. sync.Mutex
  64. }
  65. // LatencyStats encapsulates latency statistics.
  66. type LatencyStats struct {
  67. Current float64 `json:"current"`
  68. Average float64 `json:"average"`
  69. averageSquare float64
  70. StandardDeviation float64 `json:"standardDeviation"`
  71. Minimum float64 `json:"minimum"`
  72. Maximum float64 `json:"maximum"`
  73. }
  74. // CountsStats encapsulates raft statistics.
  75. type CountsStats struct {
  76. Fail uint64 `json:"fail"`
  77. Success uint64 `json:"success"`
  78. }
  79. // Succ updates the FollowerStats with a successful send
  80. func (fs *FollowerStats) Succ(d time.Duration) {
  81. fs.Lock()
  82. defer fs.Unlock()
  83. total := float64(fs.Counts.Success) * fs.Latency.Average
  84. totalSquare := float64(fs.Counts.Success) * fs.Latency.averageSquare
  85. fs.Counts.Success++
  86. fs.Latency.Current = float64(d) / (1000000.0)
  87. if fs.Latency.Current > fs.Latency.Maximum {
  88. fs.Latency.Maximum = fs.Latency.Current
  89. }
  90. if fs.Latency.Current < fs.Latency.Minimum {
  91. fs.Latency.Minimum = fs.Latency.Current
  92. }
  93. fs.Latency.Average = (total + fs.Latency.Current) / float64(fs.Counts.Success)
  94. fs.Latency.averageSquare = (totalSquare + fs.Latency.Current*fs.Latency.Current) / float64(fs.Counts.Success)
  95. // sdv = sqrt(avg(x^2) - avg(x)^2)
  96. fs.Latency.StandardDeviation = math.Sqrt(fs.Latency.averageSquare - fs.Latency.Average*fs.Latency.Average)
  97. }
  98. // Fail updates the FollowerStats with an unsuccessful send
  99. func (fs *FollowerStats) Fail() {
  100. fs.Lock()
  101. defer fs.Unlock()
  102. fs.Counts.Fail++
  103. }