go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/stats/server.go (about)

     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  
    15  package stats
    16  
    17  import (
    18  	"encoding/json"
    19  	"log"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/coreos/etcd/raft"
    24  )
    25  
    26  // ServerStats encapsulates various statistics about an EtcdServer and its
    27  // communication with other members of the cluster
    28  type ServerStats struct {
    29  	serverStats
    30  	sync.Mutex
    31  }
    32  
    33  func 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  
    48  type 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  
    74  func (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
    91  func (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
   114  func (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  
   130  func (ss *ServerStats) BecomeLeader() {
   131  	ss.Lock()
   132  	defer ss.Unlock()
   133  	ss.becomeLeader()
   134  }
   135  
   136  func (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  }