leader.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2015 CoreOS, Inc.
  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. // TODO(jonboulle): clarify that these are IDs, not names
  25. Leader string `json:"leader"`
  26. Followers map[string]*FollowerStats `json:"followers"`
  27. sync.Mutex
  28. }
  29. // NewLeaderStats generates a new LeaderStats with the given id as leader
  30. func NewLeaderStats(id string) *LeaderStats {
  31. return &LeaderStats{
  32. Leader: id,
  33. Followers: make(map[string]*FollowerStats),
  34. }
  35. }
  36. func (ls *LeaderStats) JSON() []byte {
  37. ls.Lock()
  38. stats := *ls
  39. ls.Unlock()
  40. b, err := json.Marshal(stats)
  41. // TODO(jonboulle): appropriate error handling?
  42. if err != nil {
  43. plog.Errorf("error marshalling leader stats (%v)", err)
  44. }
  45. return b
  46. }
  47. func (ls *LeaderStats) Follower(name string) *FollowerStats {
  48. ls.Lock()
  49. defer ls.Unlock()
  50. fs, ok := ls.Followers[name]
  51. if !ok {
  52. fs = &FollowerStats{}
  53. fs.Latency.Minimum = 1 << 63
  54. ls.Followers[name] = fs
  55. }
  56. return fs
  57. }
  58. // FollowerStats encapsulates various statistics about a follower in an etcd cluster
  59. type FollowerStats struct {
  60. Latency LatencyStats `json:"latency"`
  61. Counts CountsStats `json:"counts"`
  62. sync.Mutex
  63. }
  64. // LatencyStats encapsulates latency statistics.
  65. type LatencyStats struct {
  66. Current float64 `json:"current"`
  67. Average float64 `json:"average"`
  68. averageSquare float64
  69. StandardDeviation float64 `json:"standardDeviation"`
  70. Minimum float64 `json:"minimum"`
  71. Maximum float64 `json:"maximum"`
  72. }
  73. // CountsStats encapsulates raft statistics.
  74. type CountsStats struct {
  75. Fail uint64 `json:"fail"`
  76. Success uint64 `json:"success"`
  77. }
  78. // Succ updates the FollowerStats with a successful send
  79. func (fs *FollowerStats) Succ(d time.Duration) {
  80. fs.Lock()
  81. defer fs.Unlock()
  82. total := float64(fs.Counts.Success) * fs.Latency.Average
  83. totalSquare := float64(fs.Counts.Success) * fs.Latency.averageSquare
  84. fs.Counts.Success++
  85. fs.Latency.Current = float64(d) / (1000000.0)
  86. if fs.Latency.Current > fs.Latency.Maximum {
  87. fs.Latency.Maximum = fs.Latency.Current
  88. }
  89. if fs.Latency.Current < fs.Latency.Minimum {
  90. fs.Latency.Minimum = fs.Latency.Current
  91. }
  92. fs.Latency.Average = (total + fs.Latency.Current) / float64(fs.Counts.Success)
  93. fs.Latency.averageSquare = (totalSquare + fs.Latency.Current*fs.Latency.Current) / float64(fs.Counts.Success)
  94. // sdv = sqrt(avg(x^2) - avg(x)^2)
  95. fs.Latency.StandardDeviation = math.Sqrt(fs.Latency.averageSquare - fs.Latency.Average*fs.Latency.Average)
  96. }
  97. // Fail updates the FollowerStats with an unsuccessful send
  98. func (fs *FollowerStats) Fail() {
  99. fs.Lock()
  100. defer fs.Unlock()
  101. fs.Counts.Fail++
  102. }