blob: c4accc73519790b5aad25e49d12863fdf2fc22c2 [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001// 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
15package v2stats
16
17import (
18 "encoding/json"
19 "log"
20 "sync"
21 "time"
22
23 "go.etcd.io/etcd/raft"
24)
25
26// ServerStats encapsulates various statistics about an EtcdServer and its
27// communication with other members of the cluster
28type ServerStats struct {
29 serverStats
30 sync.Mutex
31}
32
33func NewServerStats(name, id string) *ServerStats {
34 ss := &ServerStats{
35 serverStats: serverStats{
36 Name: name,
37 ID: id,
38 },
39 }
40 now := time.Now()
41 ss.StartTime = now
42 ss.LeaderInfo.StartTime = now
43 ss.sendRateQueue = &statsQueue{back: -1}
44 ss.recvRateQueue = &statsQueue{back: -1}
45 return ss
46}
47
48type serverStats struct {
49 Name string `json:"name"`
50 // ID is the raft ID of the node.
51 // TODO(jonboulle): use ID instead of name?
52 ID string `json:"id"`
53 State raft.StateType `json:"state"`
54 StartTime time.Time `json:"startTime"`
55
56 LeaderInfo struct {
57 Name string `json:"leader"`
58 Uptime string `json:"uptime"`
59 StartTime time.Time `json:"startTime"`
60 } `json:"leaderInfo"`
61
62 RecvAppendRequestCnt uint64 `json:"recvAppendRequestCnt,"`
63 RecvingPkgRate float64 `json:"recvPkgRate,omitempty"`
64 RecvingBandwidthRate float64 `json:"recvBandwidthRate,omitempty"`
65
66 SendAppendRequestCnt uint64 `json:"sendAppendRequestCnt"`
67 SendingPkgRate float64 `json:"sendPkgRate,omitempty"`
68 SendingBandwidthRate float64 `json:"sendBandwidthRate,omitempty"`
69
70 sendRateQueue *statsQueue
71 recvRateQueue *statsQueue
72}
73
74func (ss *ServerStats) JSON() []byte {
75 ss.Lock()
76 stats := ss.serverStats
77 stats.SendingPkgRate, stats.SendingBandwidthRate = stats.sendRateQueue.Rate()
78 stats.RecvingPkgRate, stats.RecvingBandwidthRate = stats.recvRateQueue.Rate()
79 stats.LeaderInfo.Uptime = time.Since(stats.LeaderInfo.StartTime).String()
80 ss.Unlock()
81 b, err := json.Marshal(stats)
82 // TODO(jonboulle): appropriate error handling?
83 if err != nil {
84 log.Printf("stats: error marshalling server stats: %v", err)
85 }
86 return b
87}
88
89// RecvAppendReq updates the ServerStats in response to an AppendRequest
90// from the given leader being received
91func (ss *ServerStats) RecvAppendReq(leader string, reqSize int) {
92 ss.Lock()
93 defer ss.Unlock()
94
95 now := time.Now()
96
97 ss.State = raft.StateFollower
98 if leader != ss.LeaderInfo.Name {
99 ss.LeaderInfo.Name = leader
100 ss.LeaderInfo.StartTime = now
101 }
102
103 ss.recvRateQueue.Insert(
104 &RequestStats{
105 SendingTime: now,
106 Size: reqSize,
107 },
108 )
109 ss.RecvAppendRequestCnt++
110}
111
112// SendAppendReq updates the ServerStats in response to an AppendRequest
113// being sent by this server
114func (ss *ServerStats) SendAppendReq(reqSize int) {
115 ss.Lock()
116 defer ss.Unlock()
117
118 ss.becomeLeader()
119
120 ss.sendRateQueue.Insert(
121 &RequestStats{
122 SendingTime: time.Now(),
123 Size: reqSize,
124 },
125 )
126
127 ss.SendAppendRequestCnt++
128}
129
130func (ss *ServerStats) BecomeLeader() {
131 ss.Lock()
132 defer ss.Unlock()
133 ss.becomeLeader()
134}
135
136func (ss *ServerStats) becomeLeader() {
137 if ss.State != raft.StateLeader {
138 ss.State = raft.StateLeader
139 ss.LeaderInfo.Name = ss.ID
140 ss.LeaderInfo.StartTime = time.Now()
141 }
142}