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 15package rafthttp 16 17import ( 18 "errors" 19 "fmt" 20 "sync" 21 "time" 22 23 "go.etcd.io/etcd/pkg/types" 24 25 "go.uber.org/zap" 26) 27 28type failureType struct { 29 source string 30 action string 31} 32 33type peerStatus struct { 34 lg *zap.Logger 35 local types.ID 36 id types.ID 37 mu sync.Mutex // protect variables below 38 active bool 39 since time.Time 40} 41 42func newPeerStatus(lg *zap.Logger, local, id types.ID) *peerStatus { 43 return &peerStatus{lg: lg, local: local, id: id} 44} 45 46func (s *peerStatus) activate() { 47 s.mu.Lock() 48 defer s.mu.Unlock() 49 if !s.active { 50 if s.lg != nil { 51 s.lg.Info("peer became active", zap.String("peer-id", s.id.String())) 52 } else { 53 plog.Infof("peer %s became active", s.id) 54 } 55 s.active = true 56 s.since = time.Now() 57 58 activePeers.WithLabelValues(s.local.String(), s.id.String()).Inc() 59 } 60} 61 62func (s *peerStatus) deactivate(failure failureType, reason string) { 63 s.mu.Lock() 64 defer s.mu.Unlock() 65 msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason) 66 if s.active { 67 if s.lg != nil { 68 s.lg.Warn("peer became inactive (message send to peer failed)", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg))) 69 } else { 70 plog.Errorf(msg) 71 plog.Infof("peer %s became inactive (message send to peer failed)", s.id) 72 } 73 s.active = false 74 s.since = time.Time{} 75 76 activePeers.WithLabelValues(s.local.String(), s.id.String()).Dec() 77 disconnectedPeers.WithLabelValues(s.local.String(), s.id.String()).Inc() 78 return 79 } 80 81 if s.lg != nil { 82 s.lg.Debug("peer deactivated again", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg))) 83 } 84} 85 86func (s *peerStatus) isActive() bool { 87 s.mu.Lock() 88 defer s.mu.Unlock() 89 return s.active 90} 91 92func (s *peerStatus) activeSince() time.Time { 93 s.mu.Lock() 94 defer s.mu.Unlock() 95 return s.since 96} 97